diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..fc1e8716 --- /dev/null +++ b/404.html @@ -0,0 +1,2982 @@ + + + + + + + + + + + + + + + + outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 00000000..1cf13b9f Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.078830c0.min.js b/assets/javascripts/bundle.078830c0.min.js new file mode 100644 index 00000000..af96b246 --- /dev/null +++ b/assets/javascripts/bundle.078830c0.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var aa=Object.create;var wr=Object.defineProperty;var sa=Object.getOwnPropertyDescriptor;var ca=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,fa=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,fn=Object.prototype.propertyIsEnumerable;var cn=(e,t,r)=>t in e?wr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,H=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&cn(e,r,t[r]);if(kt)for(var r of kt(t))fn.call(t,r)&&cn(e,r,t[r]);return e};var un=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&fn.call(e,n)&&(r[n]=e[n]);return r};var yt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var ua=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ca(t))!Er.call(e,o)&&o!==r&&wr(e,o,{get:()=>t[o],enumerable:!(n=sa(t,o))||n.enumerable});return e};var Ye=(e,t,r)=>(r=e!=null?aa(fa(e)):{},ua(t||!e||!e.__esModule?wr(r,"default",{value:e,enumerable:!0}):r,e));var ln=yt((Sr,pn)=>{(function(e,t){typeof Sr=="object"&&typeof pn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Sr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(_){return!!(_&&_!==document&&_.nodeName!=="HTML"&&_.nodeName!=="BODY"&&"classList"in _&&"contains"in _.classList)}function c(_){var We=_.type,Fe=_.tagName;return!!(Fe==="INPUT"&&s[We]&&!_.readOnly||Fe==="TEXTAREA"&&!_.readOnly||_.isContentEditable)}function f(_){_.classList.contains("focus-visible")||(_.classList.add("focus-visible"),_.setAttribute("data-focus-visible-added",""))}function u(_){!_.hasAttribute("data-focus-visible-added")||(_.classList.remove("focus-visible"),_.removeAttribute("data-focus-visible-added"))}function p(_){_.metaKey||_.altKey||_.ctrlKey||(a(r.activeElement)&&f(r.activeElement),n=!0)}function l(_){n=!1}function d(_){!a(_.target)||(n||c(_.target))&&f(_.target)}function h(_){!a(_.target)||(_.target.classList.contains("focus-visible")||_.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(_.target))}function b(_){document.visibilityState==="hidden"&&(o&&(n=!0),U())}function U(){document.addEventListener("mousemove",W),document.addEventListener("mousedown",W),document.addEventListener("mouseup",W),document.addEventListener("pointermove",W),document.addEventListener("pointerdown",W),document.addEventListener("pointerup",W),document.addEventListener("touchmove",W),document.addEventListener("touchstart",W),document.addEventListener("touchend",W)}function G(){document.removeEventListener("mousemove",W),document.removeEventListener("mousedown",W),document.removeEventListener("mouseup",W),document.removeEventListener("pointermove",W),document.removeEventListener("pointerdown",W),document.removeEventListener("pointerup",W),document.removeEventListener("touchmove",W),document.removeEventListener("touchstart",W),document.removeEventListener("touchend",W)}function W(_){_.target.nodeName&&_.target.nodeName.toLowerCase()==="html"||(n=!1,G())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",l,!0),document.addEventListener("pointerdown",l,!0),document.addEventListener("touchstart",l,!0),document.addEventListener("visibilitychange",b,!0),U(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var mn=yt(Or=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(f){return!1}},r=t(),n=function(f){var u={next:function(){var p=f.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(f){return encodeURIComponent(f).replace(/%20/g,"+")},i=function(f){return decodeURIComponent(String(f).replace(/\+/g," "))},s=function(){var f=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var l=typeof p;if(l!=="undefined")if(l==="string")p!==""&&this._fromString(p);else if(p instanceof f){var d=this;p.forEach(function(G,W){d.append(W,G)})}else if(p!==null&&l==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),f._entries&&(f._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Or);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(c,f){typeof c!="string"&&(c=String(c)),f&&typeof f!="string"&&(f=String(f));var u=document,p;if(f&&(e.location===void 0||f!==e.location.href)){f=f.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=f,u.head.appendChild(p);try{if(p.href.indexOf(f)!==0)throw new Error(p.href)}catch(_){throw new Error("URL unable to set base "+f+" due to "+_)}}var l=u.createElement("a");l.href=c,p&&(u.body.appendChild(l),l.href=l.href);var d=u.createElement("input");if(d.type="url",d.value=c,l.protocol===":"||!/:/.test(l.href)||!d.checkValidity()&&!f)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:l});var h=new e.URLSearchParams(this.search),b=!0,U=!0,G=this;["append","delete","set"].forEach(function(_){var We=h[_];h[_]=function(){We.apply(h,arguments),b&&(U=!1,G.search=h.toString(),U=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var W=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==W&&(W=this.search,U&&(b=!1,this.searchParams._fromString(this.search),b=!0))}})},s=i.prototype,a=function(c){Object.defineProperty(s,c,{get:function(){return this._anchorElement[c]},set:function(f){this._anchorElement[c]=f},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(c){a(c)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(c){this._anchorElement.search=c,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var c=this;return function(){return c.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(c){this._anchorElement.href=c,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(c){this._anchorElement.pathname=c},enumerable:!0},origin:{get:function(){var c={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],f=this._anchorElement.port!=c&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(f?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(c){},enumerable:!0},username:{get:function(){return""},set:function(c){},enumerable:!0}}),i.createObjectURL=function(c){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(c){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Or)});var Pn=yt((Ks,$t)=>{/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */var dn,hn,bn,vn,gn,yn,xn,wn,En,Ht,_r,Sn,On,_n,rt,Tn,Mn,Ln,An,Cn,Rn,kn,Hn,Pt;(function(e){var t=typeof global=="object"?global:typeof self=="object"?self:typeof this=="object"?this:{};typeof define=="function"&&define.amd?define("tslib",["exports"],function(n){e(r(t,r(n)))}):typeof $t=="object"&&typeof $t.exports=="object"?e(r(t,r($t.exports))):e(r(t));function r(n,o){return n!==t&&(typeof Object.create=="function"?Object.defineProperty(n,"__esModule",{value:!0}):n.__esModule=!0),function(i,s){return n[i]=o?o(i,s):s}}})(function(e){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(n,o){n.__proto__=o}||function(n,o){for(var i in o)Object.prototype.hasOwnProperty.call(o,i)&&(n[i]=o[i])};dn=function(n,o){if(typeof o!="function"&&o!==null)throw new TypeError("Class extends value "+String(o)+" is not a constructor or null");t(n,o);function i(){this.constructor=n}n.prototype=o===null?Object.create(o):(i.prototype=o.prototype,new i)},hn=Object.assign||function(n){for(var o,i=1,s=arguments.length;i=0;u--)(f=n[u])&&(c=(a<3?f(c):a>3?f(o,i,c):f(o,i))||c);return a>3&&c&&Object.defineProperty(o,i,c),c},gn=function(n,o){return function(i,s){o(i,s,n)}},yn=function(n,o){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(n,o)},xn=function(n,o,i,s){function a(c){return c instanceof i?c:new i(function(f){f(c)})}return new(i||(i=Promise))(function(c,f){function u(d){try{l(s.next(d))}catch(h){f(h)}}function p(d){try{l(s.throw(d))}catch(h){f(h)}}function l(d){d.done?c(d.value):a(d.value).then(u,p)}l((s=s.apply(n,o||[])).next())})},wn=function(n,o){var i={label:0,sent:function(){if(c[0]&1)throw c[1];return c[1]},trys:[],ops:[]},s,a,c,f;return f={next:u(0),throw:u(1),return:u(2)},typeof Symbol=="function"&&(f[Symbol.iterator]=function(){return this}),f;function u(l){return function(d){return p([l,d])}}function p(l){if(s)throw new TypeError("Generator is already executing.");for(;i;)try{if(s=1,a&&(c=l[0]&2?a.return:l[0]?a.throw||((c=a.return)&&c.call(a),0):a.next)&&!(c=c.call(a,l[1])).done)return c;switch(a=0,c&&(l=[l[0]&2,c.value]),l[0]){case 0:case 1:c=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,a=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(c=i.trys,!(c=c.length>0&&c[c.length-1])&&(l[0]===6||l[0]===2)){i=0;continue}if(l[0]===3&&(!c||l[1]>c[0]&&l[1]=n.length&&(n=void 0),{value:n&&n[s++],done:!n}}};throw new TypeError(o?"Object is not iterable.":"Symbol.iterator is not defined.")},_r=function(n,o){var i=typeof Symbol=="function"&&n[Symbol.iterator];if(!i)return n;var s=i.call(n),a,c=[],f;try{for(;(o===void 0||o-- >0)&&!(a=s.next()).done;)c.push(a.value)}catch(u){f={error:u}}finally{try{a&&!a.done&&(i=s.return)&&i.call(s)}finally{if(f)throw f.error}}return c},Sn=function(){for(var n=[],o=0;o1||u(b,U)})})}function u(b,U){try{p(s[b](U))}catch(G){h(c[0][3],G)}}function p(b){b.value instanceof rt?Promise.resolve(b.value.v).then(l,d):h(c[0][2],b)}function l(b){u("next",b)}function d(b){u("throw",b)}function h(b,U){b(U),c.shift(),c.length&&u(c[0][0],c[0][1])}},Mn=function(n){var o,i;return o={},s("next"),s("throw",function(a){throw a}),s("return"),o[Symbol.iterator]=function(){return this},o;function s(a,c){o[a]=n[a]?function(f){return(i=!i)?{value:rt(n[a](f)),done:a==="return"}:c?c(f):f}:c}},Ln=function(n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var o=n[Symbol.asyncIterator],i;return o?o.call(n):(n=typeof Ht=="function"?Ht(n):n[Symbol.iterator](),i={},s("next"),s("throw"),s("return"),i[Symbol.asyncIterator]=function(){return this},i);function s(c){i[c]=n[c]&&function(f){return new Promise(function(u,p){f=n[c](f),a(u,p,f.done,f.value)})}}function a(c,f,u,p){Promise.resolve(p).then(function(l){c({value:l,done:u})},f)}},An=function(n,o){return Object.defineProperty?Object.defineProperty(n,"raw",{value:o}):n.raw=o,n};var r=Object.create?function(n,o){Object.defineProperty(n,"default",{enumerable:!0,value:o})}:function(n,o){n.default=o};Cn=function(n){if(n&&n.__esModule)return n;var o={};if(n!=null)for(var i in n)i!=="default"&&Object.prototype.hasOwnProperty.call(n,i)&&Pt(o,n,i);return r(o,n),o},Rn=function(n){return n&&n.__esModule?n:{default:n}},kn=function(n,o,i,s){if(i==="a"&&!s)throw new TypeError("Private accessor was defined without a getter");if(typeof o=="function"?n!==o||!s:!o.has(n))throw new TypeError("Cannot read private member from an object whose class did not declare it");return i==="m"?s:i==="a"?s.call(n):s?s.value:o.get(n)},Hn=function(n,o,i,s,a){if(s==="m")throw new TypeError("Private method is not writable");if(s==="a"&&!a)throw new TypeError("Private accessor was defined without a setter");if(typeof o=="function"?n!==o||!a:!o.has(n))throw new TypeError("Cannot write private member to an object whose class did not declare it");return s==="a"?a.call(n,i):a?a.value=i:o.set(n,i),i},e("__extends",dn),e("__assign",hn),e("__rest",bn),e("__decorate",vn),e("__param",gn),e("__metadata",yn),e("__awaiter",xn),e("__generator",wn),e("__exportStar",En),e("__createBinding",Pt),e("__values",Ht),e("__read",_r),e("__spread",Sn),e("__spreadArrays",On),e("__spreadArray",_n),e("__await",rt),e("__asyncGenerator",Tn),e("__asyncDelegator",Mn),e("__asyncValues",Ln),e("__makeTemplateObject",An),e("__importStar",Cn),e("__importDefault",Rn),e("__classPrivateFieldGet",kn),e("__classPrivateFieldSet",Hn)})});var Br=yt((At,Yr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof At=="object"&&typeof Yr=="object"?Yr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof At=="object"?At.ClipboardJS=r():t.ClipboardJS=r()})(At,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ia}});var s=i(279),a=i.n(s),c=i(370),f=i.n(c),u=i(817),p=i.n(u);function l(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var O=p()(T);return l("cut"),O},h=d;function b(j){var T=document.documentElement.getAttribute("dir")==="rtl",O=document.createElement("textarea");O.style.fontSize="12pt",O.style.border="0",O.style.padding="0",O.style.margin="0",O.style.position="absolute",O.style[T?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return O.style.top="".concat(k,"px"),O.setAttribute("readonly",""),O.value=j,O}var U=function(T,O){var k=b(T);O.container.appendChild(k);var $=p()(k);return l("copy"),k.remove(),$},G=function(T){var O=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof T=="string"?k=U(T,O):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?k=U(T.value,O):(k=p()(T),l("copy")),k},W=G;function _(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?_=function(O){return typeof O}:_=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},_(j)}var We=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},O=T.action,k=O===void 0?"copy":O,$=T.container,q=T.target,Te=T.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&_(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Te)return W(Te,{container:$});if(q)return k==="cut"?h(q):W(q,{container:$})},Fe=We;function Pe(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Pe=function(O){return typeof O}:Pe=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},Pe(j)}function Ji(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function sn(j,T){for(var O=0;O0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof $.action=="function"?$.action:this.defaultAction,this.target=typeof $.target=="function"?$.target:this.defaultTarget,this.text=typeof $.text=="function"?$.text:this.defaultText,this.container=Pe($.container)==="object"?$.container:document.body}},{key:"listenClick",value:function($){var q=this;this.listener=f()($,"click",function(Te){return q.onClick(Te)})}},{key:"onClick",value:function($){var q=$.delegateTarget||$.currentTarget,Te=this.action(q)||"copy",Rt=Fe({action:Te,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Te,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function($){return xr("action",$)}},{key:"defaultTarget",value:function($){var q=xr("target",$);if(q)return document.querySelector(q)}},{key:"defaultText",value:function($){return xr("text",$)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function($){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return W($,q)}},{key:"cut",value:function($){return h($)}},{key:"isSupported",value:function(){var $=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof $=="string"?[$]:$,Te=!!document.queryCommandSupported;return q.forEach(function(Rt){Te=Te&&!!document.queryCommandSupported(Rt)}),Te}}]),O}(a()),ia=oa},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,c){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(c))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,l,d,h){var b=f.apply(this,arguments);return u.addEventListener(l,b,h),{destroy:function(){u.removeEventListener(l,b,h)}}}function c(u,p,l,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof l=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(b){return a(b,p,l,d,h)}))}function f(u,p,l,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=c},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function c(l,d,h){if(!l&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(l))return f(l,d,h);if(s.nodeList(l))return u(l,d,h);if(s.string(l))return p(l,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function f(l,d,h){return l.addEventListener(d,h),{destroy:function(){l.removeEventListener(d,h)}}}function u(l,d,h){return Array.prototype.forEach.call(l,function(b){b.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(l,function(b){b.removeEventListener(d,h)})}}}function p(l,d,h){return a(document.body,l,d,h)}n.exports=c},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var c=window.getSelection(),f=document.createRange();f.selectNodeContents(i),c.removeAllRanges(),c.addRange(f),s=c.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var c=this.e||(this.e={});return(c[i]||(c[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var c=this;function f(){c.off(i,f),s.apply(a,arguments)}return f._=s,this.on(i,f,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),c=0,f=a.length;for(c;c{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var Ms=/["'&<>]/;Si.exports=Ls;function Ls(e){var t=""+e,r=Ms.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Tr:(this.currentObservers=null,a.push(r),new $e(function(){n.currentObservers=null,Ue(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new Qn(r,n)},t}(F);var Qn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Tr},t}(E);var wt={now:function(){return(wt.delegate||Date).now()},delegate:void 0};var Et=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=wt);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,c=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+c)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),c=0;c0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=at.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(at.cancelAnimationFrame(n),r._scheduled=void 0)},t}(zt);var Gn=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Nt);var xe=new Gn(Bn);var R=new F(function(e){return e.complete()});function qt(e){return e&&L(e.schedule)}function Hr(e){return e[e.length-1]}function Ve(e){return L(Hr(e))?e.pop():void 0}function Ee(e){return qt(Hr(e))?e.pop():void 0}function Kt(e,t){return typeof Hr(e)=="number"?e.pop():t}var st=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Qt(e){return L(e==null?void 0:e.then)}function Yt(e){return L(e[it])}function Bt(e){return Symbol.asyncIterator&&L(e==null?void 0:e[Symbol.asyncIterator])}function Gt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function ya(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Jt=ya();function Xt(e){return L(e==null?void 0:e[Jt])}function Zt(e){return jn(this,arguments,function(){var r,n,o,i;return It(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,jt(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,jt(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,jt(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function er(e){return L(e==null?void 0:e.getReader)}function z(e){if(e instanceof F)return e;if(e!=null){if(Yt(e))return xa(e);if(st(e))return wa(e);if(Qt(e))return Ea(e);if(Bt(e))return Jn(e);if(Xt(e))return Sa(e);if(er(e))return Oa(e)}throw Gt(e)}function xa(e){return new F(function(t){var r=e[it]();if(L(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function wa(e){return new F(function(t){for(var r=0;r=2,!0))}function ie(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,c=a===void 0?!0:a;return function(f){var u,p,l,d=0,h=!1,b=!1,U=function(){p==null||p.unsubscribe(),p=void 0},G=function(){U(),u=l=void 0,h=b=!1},W=function(){var _=u;G(),_==null||_.unsubscribe()};return g(function(_,We){d++,!b&&!h&&U();var Fe=l=l!=null?l:r();We.add(function(){d--,d===0&&!b&&!h&&(p=Dr(W,c))}),Fe.subscribe(We),!u&&d>0&&(u=new Ge({next:function(Pe){return Fe.next(Pe)},error:function(Pe){b=!0,U(),p=Dr(G,o,Pe),Fe.error(Pe)},complete:function(){h=!0,U(),p=Dr(G,s),Fe.complete()}}),z(_).subscribe(u))})(f)}}function Dr(e,t){for(var r=[],n=2;ne.next(document)),e}function Q(e,t=document){return Array.from(t.querySelectorAll(e))}function K(e,t=document){let r=pe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function pe(e,t=document){return t.querySelector(e)||void 0}function Ie(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function nr(e){return A(v(document.body,"focusin"),v(document.body,"focusout")).pipe(Re(1),m(()=>{let t=Ie();return typeof t!="undefined"?e.contains(t):!1}),N(e===Ie()),B())}function qe(e){return{x:e.offsetLeft,y:e.offsetTop}}function yo(e){return A(v(window,"load"),v(window,"resize")).pipe(Ae(0,xe),m(()=>qe(e)),N(qe(e)))}function or(e){return{x:e.scrollLeft,y:e.scrollTop}}function pt(e){return A(v(e,"scroll"),v(window,"resize")).pipe(Ae(0,xe),m(()=>or(e)),N(or(e)))}var wo=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!qr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Ka?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!qr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=qa.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Eo=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Oo=typeof WeakMap!="undefined"?new WeakMap:new wo,_o=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Qa.getInstance(),n=new ns(t,r,this);Oo.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){_o.prototype[e]=function(){var t;return(t=Oo.get(this))[e].apply(t,arguments)}});var os=function(){return typeof ir.ResizeObserver!="undefined"?ir.ResizeObserver:_o}(),To=os;var Mo=new E,is=P(()=>I(new To(e=>{for(let t of e)Mo.next(t)}))).pipe(S(e=>A(Se,I(e)).pipe(C(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ve(e){return is.pipe(w(t=>t.observe(e)),S(t=>Mo.pipe(x(({target:r})=>r===e),C(()=>t.unobserve(e)),m(()=>he(e)))),N(he(e)))}function mt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var Lo=new E,as=P(()=>I(new IntersectionObserver(e=>{for(let t of e)Lo.next(t)},{threshold:0}))).pipe(S(e=>A(Se,I(e)).pipe(C(()=>e.disconnect()))),X(1));function fr(e){return as.pipe(w(t=>t.observe(e)),S(t=>Lo.pipe(x(({target:r})=>r===e),C(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function Ao(e,t=16){return pt(e).pipe(m(({y:r})=>{let n=he(e),o=mt(e);return r>=o.height-n.height-t}),B())}var ur={drawer:K("[data-md-toggle=drawer]"),search:K("[data-md-toggle=search]")};function Co(e){return ur[e].checked}function Ke(e,t){ur[e].checked!==t&&ur[e].click()}function dt(e){let t=ur[e];return v(t,"change").pipe(m(()=>t.checked),N(t.checked))}function ss(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ro(){return v(window,"keydown").pipe(x(e=>!(e.metaKey||e.ctrlKey)),m(e=>({mode:Co("search")?"search":"global",type:e.key,claim(){e.preventDefault(),e.stopPropagation()}})),x(({mode:e,type:t})=>{if(e==="global"){let r=Ie();if(typeof r!="undefined")return!ss(r,t)}return!0}),ie())}function Oe(){return new URL(location.href)}function pr(e){location.href=e.href}function ko(){return new E}function Ho(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Ho(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)Ho(n,o);return n}function Po(e,t){let r=t;if(e.length>r){for(;e[r]!==" "&&--r>0;);return`${e.substring(0,r)}...`}return e}function lr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function $o(){return location.hash.substring(1)}function Io(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function cs(){return v(window,"hashchange").pipe(m($o),N($o()),x(e=>e.length>0),X(1))}function jo(){return cs().pipe(m(e=>pe(`[id="${e}"]`)),x(e=>typeof e!="undefined"))}function Kr(e){let t=matchMedia(e);return rr(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function Fo(){let e=matchMedia("print");return A(v(window,"beforeprint").pipe(m(()=>!0)),v(window,"afterprint").pipe(m(()=>!1))).pipe(N(e.matches))}function Qr(e,t){return e.pipe(S(r=>r?t():R))}function mr(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(ce(()=>R),S(r=>r.status!==200?Ot(()=>new Error(r.statusText)):I(r)))}function je(e,t){return mr(e,t).pipe(S(r=>r.json()),X(1))}function Uo(e,t){let r=new DOMParser;return mr(e,t).pipe(S(n=>n.text()),m(n=>r.parseFromString(n,"text/xml")),X(1))}function Do(e){let t=M("script",{src:e});return P(()=>(document.head.appendChild(t),A(v(t,"load"),v(t,"error").pipe(S(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),C(()=>document.head.removeChild(t)),oe(1))))}function Wo(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function Vo(){return A(v(window,"scroll",{passive:!0}),v(window,"resize",{passive:!0})).pipe(m(Wo),N(Wo()))}function zo(){return{width:innerWidth,height:innerHeight}}function No(){return v(window,"resize",{passive:!0}).pipe(m(zo),N(zo()))}function qo(){return Y([Vo(),No()]).pipe(m(([e,t])=>({offset:e,size:t})),X(1))}function dr(e,{viewport$:t,header$:r}){let n=t.pipe(J("size")),o=Y([n,r]).pipe(m(()=>qe(e)));return Y([r,t,o]).pipe(m(([{height:i},{offset:s,size:a},{x:c,y:f}])=>({offset:{x:s.x-c,y:s.y-f+i},size:a})))}function Ko(e,{tx$:t}){let r=v(e,"message").pipe(m(({data:n})=>n));return t.pipe(Lt(()=>r,{leading:!0,trailing:!0}),w(n=>e.postMessage(n)),S(()=>r),ie())}var fs=K("#__config"),ht=JSON.parse(fs.textContent);ht.base=`${new URL(ht.base,Oe())}`;function le(){return ht}function Z(e){return ht.features.includes(e)}function re(e,t){return typeof t!="undefined"?ht.translations[e].replace("#",t.toString()):ht.translations[e]}function _e(e,t=document){return K(`[data-md-component=${e}]`,t)}function te(e,t=document){return Q(`[data-md-component=${e}]`,t)}function us(e){let t=K(".md-typeset > :first-child",e);return v(t,"click",{once:!0}).pipe(m(()=>K(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function Qo(e){return!Z("announce.dismiss")||!e.childElementCount?R:P(()=>{let t=new E;return t.pipe(N({hash:__md_get("__announce")})).subscribe(({hash:r})=>{var n;r&&r===((n=__md_get("__announce"))!=null?n:r)&&(e.hidden=!0,__md_set("__announce",r))}),us(e).pipe(w(r=>t.next(r)),C(()=>t.complete()),m(r=>H({ref:e},r)))})}function ps(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function Yo(e,t){let r=new E;return r.subscribe(({hidden:n})=>{e.hidden=n}),ps(e,t).pipe(w(n=>r.next(n)),C(()=>r.complete()),m(n=>H({ref:e},n)))}var ii=Ye(Br());function Gr(e){return M("div",{class:"md-tooltip",id:e},M("div",{class:"md-tooltip__inner md-typeset"}))}function Bo(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return M("aside",{class:"md-annotation",tabIndex:0},Gr(t),M("a",{href:r,class:"md-annotation__index",tabIndex:-1},M("span",{"data-md-annotation-id":e})))}else return M("aside",{class:"md-annotation",tabIndex:0},Gr(t),M("span",{class:"md-annotation__index",tabIndex:-1},M("span",{"data-md-annotation-id":e})))}function Go(e){return M("button",{class:"md-clipboard md-icon",title:re("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}function Jr(e,t){let r=t&2,n=t&1,o=Object.keys(e.terms).filter(a=>!e.terms[a]).reduce((a,c)=>[...a,M("del",null,c)," "],[]).slice(0,-1),i=new URL(e.location);Z("search.highlight")&&i.searchParams.set("h",Object.entries(e.terms).filter(([,a])=>a).reduce((a,[c])=>`${a} ${c}`.trim(),""));let{tags:s}=le();return M("a",{href:`${i}`,class:"md-search-result__link",tabIndex:-1},M("article",{class:["md-search-result__article",...r?["md-search-result__article--document"]:[]].join(" "),"data-md-score":e.score.toFixed(2)},r>0&&M("div",{class:"md-search-result__icon md-icon"}),M("h1",{class:"md-search-result__title"},e.title),n>0&&e.text.length>0&&M("p",{class:"md-search-result__teaser"},Po(e.text,320)),e.tags&&M("div",{class:"md-typeset"},e.tags.map(a=>{let c=a.replace(/<[^>]+>/g,""),f=s?c in s?`md-tag-icon md-tag-icon--${s[c]}`:"md-tag-icon":"";return M("span",{class:`md-tag ${f}`},a)})),n>0&&o.length>0&&M("p",{class:"md-search-result__terms"},re("search.result.term.missing"),": ",...o)))}function Jo(e){let t=e[0].score,r=[...e],n=r.findIndex(f=>!f.location.includes("#")),[o]=r.splice(n,1),i=r.findIndex(f=>f.scoreJr(f,1)),...a.length?[M("details",{class:"md-search-result__more"},M("summary",{tabIndex:-1},a.length>0&&a.length===1?re("search.result.more.one"):re("search.result.more.other",a.length)),...a.map(f=>Jr(f,1)))]:[]];return M("li",{class:"md-search-result__item"},c)}function Xo(e){return M("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>M("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?lr(r):r)))}function Xr(e){let t=`tabbed-control tabbed-control--${e}`;return M("div",{class:t,hidden:!0},M("button",{class:"tabbed-button",tabIndex:-1}))}function Zo(e){return M("div",{class:"md-typeset__scrollwrap"},M("div",{class:"md-typeset__table"},e))}function ls(e){let t=le(),r=new URL(`../${e.version}/`,t.base);return M("li",{class:"md-version__item"},M("a",{href:`${r}`,class:"md-version__link"},e.title))}function ei(e,t){return M("div",{class:"md-version"},M("button",{class:"md-version__current","aria-label":re("select.version.title")},t.title),M("ul",{class:"md-version__list"},e.map(ls)))}function ms(e,t){let r=P(()=>Y([yo(e),pt(t)])).pipe(m(([{x:n,y:o},i])=>{let{width:s,height:a}=he(e);return{x:n-i.x+s/2,y:o-i.y+a/2}}));return nr(e).pipe(S(n=>r.pipe(m(o=>({active:n,offset:o})),oe(+!n||1/0))))}function ti(e,t,{target$:r}){let[n,o]=Array.from(e.children);return P(()=>{let i=new E,s=i.pipe(de(1));return i.subscribe({next({offset:a}){e.style.setProperty("--md-tooltip-x",`${a.x}px`),e.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),fr(e).pipe(ee(s)).subscribe(a=>{e.toggleAttribute("data-md-visible",a)}),A(i.pipe(x(({active:a})=>a)),i.pipe(Re(250),x(({active:a})=>!a))).subscribe({next({active:a}){a?e.prepend(n):n.remove()},complete(){e.prepend(n)}}),i.pipe(Ae(16,xe)).subscribe(({active:a})=>{n.classList.toggle("md-tooltip--active",a)}),i.pipe(zr(125,xe),x(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?e.style.setProperty("--md-tooltip-0",`${-a}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),v(o,"click").pipe(ee(s),x(a=>!(a.metaKey||a.ctrlKey))).subscribe(a=>a.preventDefault()),v(o,"mousedown").pipe(ee(s),ae(i)).subscribe(([a,{active:c}])=>{var f;if(a.button!==0||a.metaKey||a.ctrlKey)a.preventDefault();else if(c){a.preventDefault();let u=e.parentElement.closest(".md-annotation");u instanceof HTMLElement?u.focus():(f=Ie())==null||f.blur()}}),r.pipe(ee(s),x(a=>a===n),ke(125)).subscribe(()=>e.focus()),ms(e,t).pipe(w(a=>i.next(a)),C(()=>i.complete()),m(a=>H({ref:e},a)))})}function ds(e){let t=[];for(let r of Q(".c, .c1, .cm",e)){let n=[],o=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=o.nextNode();i;i=o.nextNode())n.push(i);for(let i of n){let s;for(;s=/(\(\d+\))(!)?/.exec(i.textContent);){let[,a,c]=s;if(typeof c=="undefined"){let f=i.splitText(s.index);i=f.splitText(a.length),t.push(f)}else{i.textContent=a,t.push(i);break}}}}return t}function ri(e,t){t.append(...Array.from(e.childNodes))}function ni(e,t,{target$:r,print$:n}){let o=t.closest("[id]"),i=o==null?void 0:o.id,s=new Map;for(let a of ds(t)){let[,c]=a.textContent.match(/\((\d+)\)/);pe(`li:nth-child(${c})`,e)&&(s.set(c,Bo(c,i)),a.replaceWith(s.get(c)))}return s.size===0?R:P(()=>{let a=new E,c=[];for(let[f,u]of s)c.push([K(".md-typeset",u),K(`li:nth-child(${f})`,e)]);return n.pipe(ee(a.pipe(de(1)))).subscribe(f=>{e.hidden=!f;for(let[u,p]of c)f?ri(u,p):ri(p,u)}),A(...[...s].map(([,f])=>ti(f,t,{target$:r}))).pipe(C(()=>a.complete()),ie())})}var hs=0;function ai(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return ai(t)}}function oi(e){return ve(e).pipe(m(({width:t})=>({scrollable:mt(e).width>t})),J("scrollable"))}function si(e,t){let{matches:r}=matchMedia("(hover)"),n=P(()=>{let o=new E;if(o.subscribe(({scrollable:s})=>{s&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")}),ii.default.isSupported()){let s=e.closest("pre");s.id=`__code_${++hs}`,s.insertBefore(Go(s.id),e)}let i=e.closest(".highlight");if(i instanceof HTMLElement){let s=ai(i);if(typeof s!="undefined"&&(i.classList.contains("annotate")||Z("content.code.annotate"))){let a=ni(s,e,t);return oi(e).pipe(w(c=>o.next(c)),C(()=>o.complete()),m(c=>H({ref:e},c)),et(ve(i).pipe(m(({width:c,height:f})=>c&&f),B(),S(c=>c?a:R))))}}return oi(e).pipe(w(s=>o.next(s)),C(()=>o.complete()),m(s=>H({ref:e},s)))});return Z("content.lazy")?fr(e).pipe(x(o=>o),oe(1),S(()=>n)):n}var ci=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:transparent}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel rect,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel rect{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color)}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}defs #flowchart-circleEnd,defs #flowchart-circleStart,defs #flowchart-crossEnd,defs #flowchart-crossStart,defs #flowchart-pointEnd,defs #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}.actor,defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{stroke:var(--md-mermaid-node-fg-color)}text.actor>tspan{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-default-fg-color--lighter)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-edge-color)}.loopText>tspan,.messageText,.noteText>tspan{font-family:var(--md-mermaid-font-family)!important}#arrowhead path,.loopText>tspan,.messageText,.noteText>tspan{fill:var(--md-mermaid-edge-color);stroke:none}.loopLine{stroke:var(--md-mermaid-node-fg-color)}.labelBox,.loopLine{fill:var(--md-mermaid-node-bg-color)}.labelBox{stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-node-fg-color);font-family:var(--md-mermaid-font-family)}";var Zr,vs=0;function gs(){return typeof mermaid=="undefined"||mermaid instanceof Element?Do("https://unpkg.com/mermaid@9.1.7/dist/mermaid.min.js"):I(void 0)}function fi(e){return e.classList.remove("mermaid"),Zr||(Zr=gs().pipe(w(()=>mermaid.initialize({startOnLoad:!1,themeCSS:ci,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),X(1))),Zr.subscribe(()=>{e.classList.add("mermaid");let t=`__mermaid_${vs++}`,r=M("div",{class:"mermaid"});mermaid.mermaidAPI.render(t,e.textContent,n=>{let o=r.attachShadow({mode:"closed"});o.innerHTML=n,e.replaceWith(r)})}),Zr.pipe(m(()=>({ref:e})))}function ys(e,{target$:t,print$:r}){let n=!0;return A(t.pipe(m(o=>o.closest("details:not([open])")),x(o=>e===o),m(()=>({action:"open",reveal:!0}))),r.pipe(x(o=>o||!n),w(()=>n=e.open),m(o=>({action:o?"open":"close"}))))}function ui(e,t){return P(()=>{let r=new E;return r.subscribe(({action:n,reveal:o})=>{e.toggleAttribute("open",n==="open"),o&&e.scrollIntoView()}),ys(e,t).pipe(w(n=>r.next(n)),C(()=>r.complete()),m(n=>H({ref:e},n)))})}var pi=M("table");function li(e){return e.replaceWith(pi),pi.replaceWith(Zo(e)),I({ref:e})}function xs(e){let t=Q(":scope > input",e),r=t.find(n=>n.checked)||t[0];return A(...t.map(n=>v(n,"change").pipe(m(()=>K(`label[for="${n.id}"]`))))).pipe(N(K(`label[for="${r.id}"]`)),m(n=>({active:n})))}function mi(e,{viewport$:t}){let r=Xr("prev");e.append(r);let n=Xr("next");e.append(n);let o=K(".tabbed-labels",e);return P(()=>{let i=new E,s=i.pipe(de(1));return Y([i,ve(e)]).pipe(Ae(1,xe),ee(s)).subscribe({next([{active:a},c]){let f=qe(a),{width:u}=he(a);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let p=or(o);(f.xp.x+c.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),Y([pt(o),ve(o)]).pipe(ee(s)).subscribe(([a,c])=>{let f=mt(o);r.hidden=a.x<16,n.hidden=a.x>f.width-c.width-16}),A(v(r,"click").pipe(m(()=>-1)),v(n,"click").pipe(m(()=>1))).pipe(ee(s)).subscribe(a=>{let{width:c}=he(o);o.scrollBy({left:c*a,behavior:"smooth"})}),Z("content.tabs.link")&&i.pipe(He(1),ae(t)).subscribe(([{active:a},{offset:c}])=>{let f=a.innerText.trim();if(a.hasAttribute("data-md-switching"))a.removeAttribute("data-md-switching");else{let u=e.offsetTop-c.y;for(let l of Q("[data-tabs]"))for(let d of Q(":scope > input",l)){let h=K(`label[for="${d.id}"]`);if(h!==a&&h.innerText.trim()===f){h.setAttribute("data-md-switching",""),d.click();break}}window.scrollTo({top:e.offsetTop-u});let p=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...p])])}}),xs(e).pipe(w(a=>i.next(a)),C(()=>i.complete()),m(a=>H({ref:e},a)))}).pipe(Je(fe))}function di(e,{viewport$:t,target$:r,print$:n}){return A(...Q("pre:not(.mermaid) > code",e).map(o=>si(o,{target$:r,print$:n})),...Q("pre.mermaid",e).map(o=>fi(o)),...Q("table:not([class])",e).map(o=>li(o)),...Q("details",e).map(o=>ui(o,{target$:r,print$:n})),...Q("[data-tabs]",e).map(o=>mi(o,{viewport$:t})))}function ws(e,{alert$:t}){return t.pipe(S(r=>A(I(!0),I(!1).pipe(ke(2e3))).pipe(m(n=>({message:r,active:n})))))}function hi(e,t){let r=K(".md-typeset",e);return P(()=>{let n=new E;return n.subscribe(({message:o,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=o}),ws(e,t).pipe(w(o=>n.next(o)),C(()=>n.complete()),m(o=>H({ref:e},o)))})}function Es({viewport$:e}){if(!Z("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:o}})=>o),Ce(2,1),m(([o,i])=>[oMath.abs(i-o.y)>100),m(([,[o]])=>o),B()),n=dt("search");return Y([e,n]).pipe(m(([{offset:o},i])=>o.y>400&&!i),B(),S(o=>o?r:I(!1)),N(!1))}function bi(e,t){return P(()=>Y([ve(e),Es(t)])).pipe(m(([{height:r},n])=>({height:r,hidden:n})),B((r,n)=>r.height===n.height&&r.hidden===n.hidden),X(1))}function vi(e,{header$:t,main$:r}){return P(()=>{let n=new E,o=n.pipe(de(1));return n.pipe(J("active"),Ze(t)).subscribe(([{active:i},{hidden:s}])=>{e.classList.toggle("md-header--shadow",i&&!s),e.hidden=s}),r.subscribe(n),t.pipe(ee(o),m(i=>H({ref:e},i)))})}function Ss(e,{viewport$:t,header$:r}){return dr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:n}})=>{let{height:o}=he(e);return{active:n>=o}}),J("active"))}function gi(e,t){return P(()=>{let r=new E;r.subscribe(({active:o})=>{e.classList.toggle("md-header__title--active",o)});let n=pe("article h1");return typeof n=="undefined"?R:Ss(n,t).pipe(w(o=>r.next(o)),C(()=>r.complete()),m(o=>H({ref:e},o)))})}function yi(e,{viewport$:t,header$:r}){let n=r.pipe(m(({height:i})=>i),B()),o=n.pipe(S(()=>ve(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),J("bottom"))));return Y([n,o,t]).pipe(m(([i,{top:s,bottom:a},{offset:{y:c},size:{height:f}}])=>(f=Math.max(0,f-Math.max(0,s-c,i)-Math.max(0,f+c-a)),{offset:s-i,height:f,active:s-i<=c})),B((i,s)=>i.offset===s.offset&&i.height===s.height&&i.active===s.active))}function Os(e){let t=__md_get("__palette")||{index:e.findIndex(r=>matchMedia(r.getAttribute("data-md-color-media")).matches)};return I(...e).pipe(se(r=>v(r,"change").pipe(m(()=>r))),N(e[Math.max(0,t.index)]),m(r=>({index:e.indexOf(r),color:{scheme:r.getAttribute("data-md-color-scheme"),primary:r.getAttribute("data-md-color-primary"),accent:r.getAttribute("data-md-color-accent")}})),X(1))}function xi(e){return P(()=>{let t=new E;t.subscribe(n=>{document.body.setAttribute("data-md-color-switching","");for(let[o,i]of Object.entries(n.color))document.body.setAttribute(`data-md-color-${o}`,i);for(let o=0;o{document.body.removeAttribute("data-md-color-switching")});let r=Q("input",e);return Os(r).pipe(w(n=>t.next(n)),C(()=>t.complete()),m(n=>H({ref:e},n)))})}var en=Ye(Br());function _s(e){e.setAttribute("data-md-copying","");let t=e.innerText;return e.removeAttribute("data-md-copying"),t}function wi({alert$:e}){en.default.isSupported()&&new F(t=>{new en.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||_s(K(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(w(t=>{t.trigger.focus()}),m(()=>re("clipboard.copied"))).subscribe(e)}function Ts(e){if(e.length<2)return[""];let[t,r]=[...e].sort((o,i)=>o.length-i.length).map(o=>o.replace(/[^/]+$/,"")),n=0;if(t===r)n=t.length;else for(;t.charCodeAt(n)===r.charCodeAt(n);)n++;return e.map(o=>o.replace(t.slice(0,n),""))}function hr(e){let t=__md_get("__sitemap",sessionStorage,e);if(t)return I(t);{let r=le();return Uo(new URL("sitemap.xml",e||r.base)).pipe(m(n=>Ts(Q("loc",n).map(o=>o.textContent))),ce(()=>R),De([]),w(n=>__md_set("__sitemap",n,sessionStorage,e)))}}function Ei({document$:e,location$:t,viewport$:r}){let n=le();if(location.protocol==="file:")return;"scrollRestoration"in history&&(history.scrollRestoration="manual",v(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}));let o=pe("link[rel=icon]");typeof o!="undefined"&&(o.href=o.href);let i=hr().pipe(m(f=>f.map(u=>`${new URL(u,n.base)}`)),S(f=>v(document.body,"click").pipe(x(u=>!u.metaKey&&!u.ctrlKey),S(u=>{if(u.target instanceof Element){let p=u.target.closest("a");if(p&&!p.target){let l=new URL(p.href);if(l.search="",l.hash="",l.pathname!==location.pathname&&f.includes(l.toString()))return u.preventDefault(),I({url:new URL(p.href)})}}return Se}))),ie()),s=v(window,"popstate").pipe(x(f=>f.state!==null),m(f=>({url:new URL(location.href),offset:f.state})),ie());A(i,s).pipe(B((f,u)=>f.url.href===u.url.href),m(({url:f})=>f)).subscribe(t);let a=t.pipe(J("pathname"),S(f=>mr(f.href).pipe(ce(()=>(pr(f),Se)))),ie());i.pipe(ut(a)).subscribe(({url:f})=>{history.pushState({},"",`${f}`)});let c=new DOMParser;a.pipe(S(f=>f.text()),m(f=>c.parseFromString(f,"text/html"))).subscribe(e),e.pipe(He(1)).subscribe(f=>{for(let u of["title","link[rel=canonical]","meta[name=author]","meta[name=description]","[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...Z("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let p=pe(u),l=pe(u,f);typeof p!="undefined"&&typeof l!="undefined"&&p.replaceWith(l)}}),e.pipe(He(1),m(()=>_e("container")),S(f=>Q("script",f)),Ir(f=>{let u=M("script");if(f.src){for(let p of f.getAttributeNames())u.setAttribute(p,f.getAttribute(p));return f.replaceWith(u),new F(p=>{u.onload=()=>p.complete()})}else return u.textContent=f.textContent,f.replaceWith(u),R})).subscribe(),A(i,s).pipe(ut(e)).subscribe(({url:f,offset:u})=>{f.hash&&!u?Io(f.hash):window.scrollTo(0,(u==null?void 0:u.y)||0)}),r.pipe(Mt(i),Re(250),J("offset")).subscribe(({offset:f})=>{history.replaceState(f,"")}),A(i,s).pipe(Ce(2,1),x(([f,u])=>f.url.pathname===u.url.pathname),m(([,f])=>f)).subscribe(({offset:f})=>{window.scrollTo(0,(f==null?void 0:f.y)||0)})}var As=Ye(tn());var Oi=Ye(tn());function rn(e,t){let r=new RegExp(e.separator,"img"),n=(o,i,s)=>`${i}${s}`;return o=>{o=o.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator})(${o.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return s=>(t?(0,Oi.default)(s):s).replace(i,n).replace(/<\/mark>(\s+)]*>/img,"$1")}}function _i(e){return e.split(/"([^"]+)"/g).map((t,r)=>r&1?t.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):t).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim()}function bt(e){return e.type===1}function Ti(e){return e.type===2}function vt(e){return e.type===3}function Rs({config:e,docs:t}){e.lang.length===1&&e.lang[0]==="en"&&(e.lang=[re("search.config.lang")]),e.separator==="[\\s\\-]+"&&(e.separator=re("search.config.separator"));let n={pipeline:re("search.config.pipeline").split(/\s*,\s*/).filter(Boolean),suggestions:Z("search.suggest")};return{config:e,docs:t,options:n}}function Mi(e,t){let r=le(),n=new Worker(e),o=new E,i=Ko(n,{tx$:o}).pipe(m(s=>{if(vt(s))for(let a of s.data.items)for(let c of a)c.location=`${new URL(c.location,r.base)}`;return s}),ie());return ue(t).pipe(m(s=>({type:0,data:Rs(s)}))).subscribe(o.next.bind(o)),{tx$:o,rx$:i}}function Li({document$:e}){let t=le(),r=je(new URL("../versions.json",t.base)).pipe(ce(()=>R)),n=r.pipe(m(o=>{let[,i]=t.base.match(/([^/]+)\/?$/);return o.find(({version:s,aliases:a})=>s===i||a.includes(i))||o[0]}));r.pipe(m(o=>new Map(o.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),S(o=>v(document.body,"click").pipe(x(i=>!i.metaKey&&!i.ctrlKey),ae(n),S(([i,s])=>{if(i.target instanceof Element){let a=i.target.closest("a");if(a&&!a.target&&o.has(a.href)){let c=a.href;return!i.target.closest(".md-version")&&o.get(c)===s?R:(i.preventDefault(),I(c))}}return R}),S(i=>{let{version:s}=o.get(i);return hr(new URL(i)).pipe(m(a=>{let f=Oe().href.replace(t.base,"");return a.includes(f.split("#")[0])?new URL(`../${s}/${f}`,t.base):new URL(i)}))})))).subscribe(o=>pr(o)),Y([r,n]).subscribe(([o,i])=>{K(".md-header__topic").appendChild(ei(o,i))}),e.pipe(S(()=>n)).subscribe(o=>{var s;let i=__md_get("__outdated",sessionStorage);if(i===null){let a=((s=t.version)==null?void 0:s.default)||"latest";i=!o.aliases.includes(a),__md_set("__outdated",i,sessionStorage)}if(i)for(let a of te("outdated"))a.hidden=!1})}function ks(e,{rx$:t}){let r=(__search==null?void 0:__search.transform)||_i,{searchParams:n}=Oe();n.has("q")&&Ke("search",!0);let o=t.pipe(x(bt),oe(1),m(()=>n.get("q")||""));dt("search").pipe(x(a=>!a),oe(1)).subscribe(()=>{let a=new URL(location.href);a.searchParams.delete("q"),history.replaceState({},"",`${a}`)}),o.subscribe(a=>{a&&(e.value=a,e.focus())});let i=nr(e),s=A(v(e,"keyup"),v(e,"focus").pipe(ke(1)),o).pipe(m(()=>r(e.value)),N(""),B());return Y([s,i]).pipe(m(([a,c])=>({value:a,focus:c})),X(1))}function Ai(e,{tx$:t,rx$:r}){let n=new E,o=n.pipe(de(1));return n.pipe(J("value"),m(({value:i})=>({type:2,data:i}))).subscribe(t.next.bind(t)),n.pipe(J("focus")).subscribe(({focus:i})=>{i?(Ke("search",i),e.placeholder=""):e.placeholder=re("search.placeholder")}),v(e.form,"reset").pipe(ee(o)).subscribe(()=>e.focus()),ks(e,{tx$:t,rx$:r}).pipe(w(i=>n.next(i)),C(()=>n.complete()),m(i=>H({ref:e},i)),ie())}function Ci(e,{rx$:t},{query$:r}){let n=new E,o=Ao(e.parentElement).pipe(x(Boolean)),i=K(":scope > :first-child",e),s=K(":scope > :last-child",e),a=t.pipe(x(bt),oe(1));return n.pipe(ae(r),Mt(a)).subscribe(([{items:f},{value:u}])=>{if(u)switch(f.length){case 0:i.textContent=re("search.result.none");break;case 1:i.textContent=re("search.result.one");break;default:i.textContent=re("search.result.other",lr(f.length))}else i.textContent=re("search.result.placeholder")}),n.pipe(w(()=>s.innerHTML=""),S(({items:f})=>A(I(...f.slice(0,10)),I(...f.slice(10)).pipe(Ce(4),Nr(o),S(([u])=>u))))).subscribe(f=>s.appendChild(Jo(f))),t.pipe(x(vt),m(({data:f})=>f)).pipe(w(f=>n.next(f)),C(()=>n.complete()),m(f=>H({ref:e},f)))}function Hs(e,{query$:t}){return t.pipe(m(({value:r})=>{let n=Oe();return n.hash="",n.searchParams.delete("h"),n.searchParams.set("q",r),{url:n}}))}function Ri(e,t){let r=new E;return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),v(e,"click").subscribe(n=>n.preventDefault()),Hs(e,t).pipe(w(n=>r.next(n)),C(()=>r.complete()),m(n=>H({ref:e},n)))}function ki(e,{rx$:t},{keyboard$:r}){let n=new E,o=_e("search-query"),i=A(v(o,"keydown"),v(o,"focus")).pipe(Le(fe),m(()=>o.value),B());return n.pipe(Ze(i),m(([{suggestions:a},c])=>{let f=c.split(/([\s-]+)/);if((a==null?void 0:a.length)&&f[f.length-1]){let u=a[a.length-1];u.startsWith(f[f.length-1])&&(f[f.length-1]=u)}else f.length=0;return f})).subscribe(a=>e.innerHTML=a.join("").replace(/\s/g," ")),r.pipe(x(({mode:a})=>a==="search")).subscribe(a=>{switch(a.type){case"ArrowRight":e.innerText.length&&o.selectionStart===o.value.length&&(o.value=e.innerText);break}}),t.pipe(x(vt),m(({data:a})=>a)).pipe(w(a=>n.next(a)),C(()=>n.complete()),m(()=>({ref:e})))}function Hi(e,{index$:t,keyboard$:r}){let n=le();try{let o=(__search==null?void 0:__search.worker)||n.search,i=Mi(o,t),s=_e("search-query",e),a=_e("search-result",e),{tx$:c,rx$:f}=i;c.pipe(x(Ti),ut(f.pipe(x(bt))),oe(1)).subscribe(c.next.bind(c)),r.pipe(x(({mode:l})=>l==="search")).subscribe(l=>{let d=Ie();switch(l.type){case"Enter":if(d===s){let h=new Map;for(let b of Q(":first-child [href]",a)){let U=b.firstElementChild;h.set(b,parseFloat(U.getAttribute("data-md-score")))}if(h.size){let[[b]]=[...h].sort(([,U],[,G])=>G-U);b.click()}l.claim()}break;case"Escape":case"Tab":Ke("search",!1),s.blur();break;case"ArrowUp":case"ArrowDown":if(typeof d=="undefined")s.focus();else{let h=[s,...Q(":not(details) > [href], summary, details[open] [href]",a)],b=Math.max(0,(Math.max(0,h.indexOf(d))+h.length+(l.type==="ArrowUp"?-1:1))%h.length);h[b].focus()}l.claim();break;default:s!==Ie()&&s.focus()}}),r.pipe(x(({mode:l})=>l==="global")).subscribe(l=>{switch(l.type){case"f":case"s":case"/":s.focus(),s.select(),l.claim();break}});let u=Ai(s,i),p=Ci(a,i,{query$:u});return A(u,p).pipe(et(...te("search-share",e).map(l=>Ri(l,{query$:u})),...te("search-suggest",e).map(l=>ki(l,i,{keyboard$:r}))))}catch(o){return e.hidden=!0,Se}}function Pi(e,{index$:t,location$:r}){return Y([t,r.pipe(N(Oe()),x(n=>!!n.searchParams.get("h")))]).pipe(m(([n,o])=>rn(n.config,!0)(o.searchParams.get("h"))),m(n=>{var s;let o=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let a=i.nextNode();a;a=i.nextNode())if((s=a.parentElement)!=null&&s.offsetHeight){let c=a.textContent,f=n(c);f.length>c.length&&o.set(a,f)}for(let[a,c]of o){let{childNodes:f}=M("span",null,c);a.replaceWith(...Array.from(f))}return{ref:e,nodes:o}}))}function Ps(e,{viewport$:t,main$:r}){let n=e.parentElement,o=n.offsetTop-n.parentElement.offsetTop;return Y([r,t]).pipe(m(([{offset:i,height:s},{offset:{y:a}}])=>(s=s+Math.min(o,Math.max(0,a-i))-o,{height:s,locked:a>=i+o})),B((i,s)=>i.height===s.height&&i.locked===s.locked))}function nn(e,n){var o=n,{header$:t}=o,r=un(o,["header$"]);let i=K(".md-sidebar__scrollwrap",e),{y:s}=qe(i);return P(()=>{let a=new E;return a.pipe(Ae(0,xe),ae(t)).subscribe({next([{height:c},{height:f}]){i.style.height=`${c-2*s}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),a.pipe(Le(xe),oe(1)).subscribe(()=>{for(let c of Q(".md-nav__link--active[href]",e)){let f=cr(c);if(typeof f!="undefined"){let u=c.offsetTop-f.offsetTop,{height:p}=he(f);f.scrollTo({top:u-p/2})}}}),Ps(e,r).pipe(w(c=>a.next(c)),C(()=>a.complete()),m(c=>H({ref:e},c)))})}function $i(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return _t(je(`${r}/releases/latest`).pipe(ce(()=>R),m(n=>({version:n.tag_name})),De({})),je(r).pipe(ce(()=>R),m(n=>({stars:n.stargazers_count,forks:n.forks_count})),De({}))).pipe(m(([n,o])=>H(H({},n),o)))}else{let r=`https://api.github.com/users/${e}`;return je(r).pipe(m(n=>({repositories:n.public_repos})),De({}))}}function Ii(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return je(r).pipe(ce(()=>R),m(({star_count:n,forks_count:o})=>({stars:n,forks:o})),De({}))}function ji(e){let[t]=e.match(/(git(?:hub|lab))/i)||[];switch(t.toLowerCase()){case"github":let[,r,n]=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);return $i(r,n);case"gitlab":let[,o,i]=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i);return Ii(o,i);default:return R}}var $s;function Is(e){return $s||($s=P(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(te("consent").length){let n=__md_get("__consent");if(!(n&&n.github))return R}return ji(e.href).pipe(w(n=>__md_set("__source",n,sessionStorage)))}).pipe(ce(()=>R),x(t=>Object.keys(t).length>0),m(t=>({facts:t})),X(1)))}function Fi(e){let t=K(":scope > :last-child",e);return P(()=>{let r=new E;return r.subscribe(({facts:n})=>{t.appendChild(Xo(n)),t.classList.add("md-source__repository--active")}),Is(e).pipe(w(n=>r.next(n)),C(()=>r.complete()),m(n=>H({ref:e},n)))})}function js(e,{viewport$:t,header$:r}){return ve(document.body).pipe(S(()=>dr(e,{header$:r,viewport$:t})),m(({offset:{y:n}})=>({hidden:n>=10})),J("hidden"))}function Ui(e,t){return P(()=>{let r=new E;return r.subscribe({next({hidden:n}){e.hidden=n},complete(){e.hidden=!1}}),(Z("navigation.tabs.sticky")?I({hidden:!1}):js(e,t)).pipe(w(n=>r.next(n)),C(()=>r.complete()),m(n=>H({ref:e},n)))})}function Fs(e,{viewport$:t,header$:r}){let n=new Map,o=Q("[href^=\\#]",e);for(let a of o){let c=decodeURIComponent(a.hash.substring(1)),f=pe(`[id="${c}"]`);typeof f!="undefined"&&n.set(a,f)}let i=r.pipe(J("height"),m(({height:a})=>{let c=_e("main"),f=K(":scope > :first-child",c);return a+.8*(f.offsetTop-c.offsetTop)}),ie());return ve(document.body).pipe(J("height"),S(a=>P(()=>{let c=[];return I([...n].reduce((f,[u,p])=>{for(;c.length&&n.get(c[c.length-1]).tagName>=p.tagName;)c.pop();let l=p.offsetTop;for(;!l&&p.parentElement;)p=p.parentElement,l=p.offsetTop;return f.set([...c=[...c,u]].reverse(),l)},new Map))}).pipe(m(c=>new Map([...c].sort(([,f],[,u])=>f-u))),Ze(i),S(([c,f])=>t.pipe(Ur(([u,p],{offset:{y:l},size:d})=>{let h=l+d.height>=Math.floor(a.height);for(;p.length;){let[,b]=p[0];if(b-f=l&&!h)p=[u.pop(),...p];else break}return[u,p]},[[],[...c]]),B((u,p)=>u[0]===p[0]&&u[1]===p[1])))))).pipe(m(([a,c])=>({prev:a.map(([f])=>f),next:c.map(([f])=>f)})),N({prev:[],next:[]}),Ce(2,1),m(([a,c])=>a.prev.length{let o=new E,i=o.pipe(de(1));if(o.subscribe(({prev:s,next:a})=>{for(let[c]of a)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[f]]of s.entries())f.classList.add("md-nav__link--passed"),f.classList.toggle("md-nav__link--active",c===s.length-1)}),Z("toc.follow")){let s=A(t.pipe(Re(1),m(()=>{})),t.pipe(Re(250),m(()=>"smooth")));o.pipe(x(({prev:a})=>a.length>0),ae(s)).subscribe(([{prev:a},c])=>{let[f]=a[a.length-1];if(f.offsetHeight){let u=cr(f);if(typeof u!="undefined"){let p=f.offsetTop-u.offsetTop,{height:l}=he(u);u.scrollTo({top:p-l/2,behavior:c})}}})}return Z("navigation.tracking")&&t.pipe(ee(i),J("offset"),Re(250),He(1),ee(n.pipe(He(1))),Tt({delay:250}),ae(o)).subscribe(([,{prev:s}])=>{let a=Oe(),c=s[s.length-1];if(c&&c.length){let[f]=c,{hash:u}=new URL(f.href);a.hash!==u&&(a.hash=u,history.replaceState({},"",`${a}`))}else a.hash="",history.replaceState({},"",`${a}`)}),Fs(e,{viewport$:t,header$:r}).pipe(w(s=>o.next(s)),C(()=>o.complete()),m(s=>H({ref:e},s)))})}function Us(e,{viewport$:t,main$:r,target$:n}){let o=t.pipe(m(({offset:{y:s}})=>s),Ce(2,1),m(([s,a])=>s>a&&a>0),B()),i=r.pipe(m(({active:s})=>s));return Y([i,o]).pipe(m(([s,a])=>!(s&&a)),B(),ee(n.pipe(He(1))),Fr(!0),Tt({delay:250}),m(s=>({hidden:s})))}function Wi(e,{viewport$:t,header$:r,main$:n,target$:o}){let i=new E,s=i.pipe(de(1));return i.subscribe({next({hidden:a}){e.hidden=a,a?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(ee(s),J("height")).subscribe(({height:a})=>{e.style.top=`${a+16}px`}),Us(e,{viewport$:t,main$:n,target$:o}).pipe(w(a=>i.next(a)),C(()=>i.complete()),m(a=>H({ref:e},a)))}function Vi({document$:e,tablet$:t}){e.pipe(S(()=>Q(".md-toggle--indeterminate, [data-md-state=indeterminate]")),w(r=>{r.indeterminate=!0,r.checked=!1}),se(r=>v(r,"change").pipe(Wr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),ae(t)).subscribe(([r,n])=>{r.classList.remove("md-toggle--indeterminate"),n&&(r.checked=!1)})}function Ds(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function zi({document$:e}){e.pipe(S(()=>Q("[data-md-scrollfix]")),w(t=>t.removeAttribute("data-md-scrollfix")),x(Ds),se(t=>v(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function Ni({viewport$:e,tablet$:t}){Y([dt("search"),t]).pipe(m(([r,n])=>r&&!n),S(r=>I(r).pipe(ke(r?400:100))),ae(e)).subscribe(([r,{offset:{y:n}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${n}px`;else{let o=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",o&&window.scrollTo(0,o)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let n=e[r];typeof n!="object"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?t.insertBefore(this.previousSibling,n):t.replaceChild(n,this)}}}));document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var tt=go(),vr=ko(),gt=jo(),on=Ro(),we=qo(),gr=Kr("(min-width: 960px)"),Ki=Kr("(min-width: 1220px)"),Qi=Fo(),Yi=le(),Bi=document.forms.namedItem("search")?(__search==null?void 0:__search.index)||je(new URL("search/search_index.json",Yi.base)):Se,an=new E;wi({alert$:an});Z("navigation.instant")&&Ei({document$:tt,location$:vr,viewport$:we});var qi;((qi=Yi.version)==null?void 0:qi.provider)==="mike"&&Li({document$:tt});A(vr,gt).pipe(ke(125)).subscribe(()=>{Ke("drawer",!1),Ke("search",!1)});on.pipe(x(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=pe("[href][rel=prev]");typeof t!="undefined"&&t.click();break;case"n":case".":let r=pe("[href][rel=next]");typeof r!="undefined"&&r.click();break}});Vi({document$:tt,tablet$:gr});zi({document$:tt});Ni({viewport$:we,tablet$:gr});var Qe=bi(_e("header"),{viewport$:we}),br=tt.pipe(m(()=>_e("main")),S(e=>yi(e,{viewport$:we,header$:Qe})),X(1)),Ws=A(...te("consent").map(e=>Yo(e,{target$:gt})),...te("dialog").map(e=>hi(e,{alert$:an})),...te("header").map(e=>vi(e,{viewport$:we,header$:Qe,main$:br})),...te("palette").map(e=>xi(e)),...te("search").map(e=>Hi(e,{index$:Bi,keyboard$:on})),...te("source").map(e=>Fi(e))),Vs=P(()=>A(...te("announce").map(e=>Qo(e)),...te("content").map(e=>di(e,{viewport$:we,target$:gt,print$:Qi})),...te("content").map(e=>Z("search.highlight")?Pi(e,{index$:Bi,location$:vr}):R),...te("header-title").map(e=>gi(e,{viewport$:we,header$:Qe})),...te("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Qr(Ki,()=>nn(e,{viewport$:we,header$:Qe,main$:br})):Qr(gr,()=>nn(e,{viewport$:we,header$:Qe,main$:br}))),...te("tabs").map(e=>Ui(e,{viewport$:we,header$:Qe})),...te("toc").map(e=>Di(e,{viewport$:we,header$:Qe,target$:gt})),...te("top").map(e=>Wi(e,{viewport$:we,header$:Qe,main$:br,target$:gt})))),Gi=tt.pipe(S(()=>Vs),et(Ws),X(1));Gi.subscribe();window.document$=tt;window.location$=vr;window.target$=gt;window.keyboard$=on;window.viewport$=we;window.tablet$=gr;window.screen$=Ki;window.print$=Qi;window.alert$=an;window.component$=Gi;})(); +//# sourceMappingURL=bundle.078830c0.min.js.map + diff --git a/assets/javascripts/bundle.078830c0.min.js.map b/assets/javascripts/bundle.078830c0.min.js.map new file mode 100644 index 00000000..36366697 --- /dev/null +++ b/assets/javascripts/bundle.078830c0.min.js.map @@ -0,0 +1,8 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/url-polyfill/url-polyfill.js", "node_modules/rxjs/node_modules/tslib/tslib.js", "node_modules/clipboard/dist/clipboard.js", "node_modules/escape-html/index.js", "node_modules/array-flat-polyfill/index.mjs", "src/assets/javascripts/bundle.ts", "node_modules/unfetch/polyfill/index.js", "node_modules/rxjs/node_modules/tslib/modules/index.js", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/concatMap.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/sample.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/assets/javascripts/browser/document/index.ts", "src/assets/javascripts/browser/element/_/index.ts", "src/assets/javascripts/browser/element/focus/index.ts", "src/assets/javascripts/browser/element/offset/_/index.ts", "src/assets/javascripts/browser/element/offset/content/index.ts", "node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js", "src/assets/javascripts/browser/element/size/_/index.ts", "src/assets/javascripts/browser/element/size/content/index.ts", "src/assets/javascripts/browser/element/visibility/index.ts", "src/assets/javascripts/browser/toggle/index.ts", "src/assets/javascripts/browser/keyboard/index.ts", "src/assets/javascripts/browser/location/_/index.ts", "src/assets/javascripts/utilities/h/index.ts", "src/assets/javascripts/utilities/string/index.ts", "src/assets/javascripts/browser/location/hash/index.ts", "src/assets/javascripts/browser/media/index.ts", "src/assets/javascripts/browser/request/index.ts", "src/assets/javascripts/browser/script/index.ts", "src/assets/javascripts/browser/viewport/offset/index.ts", "src/assets/javascripts/browser/viewport/size/index.ts", "src/assets/javascripts/browser/viewport/_/index.ts", "src/assets/javascripts/browser/viewport/at/index.ts", "src/assets/javascripts/browser/worker/index.ts", "src/assets/javascripts/_/index.ts", "src/assets/javascripts/components/_/index.ts", "src/assets/javascripts/components/announce/index.ts", "src/assets/javascripts/components/consent/index.ts", "src/assets/javascripts/components/content/code/_/index.ts", "src/assets/javascripts/templates/tooltip/index.tsx", "src/assets/javascripts/templates/annotation/index.tsx", "src/assets/javascripts/templates/clipboard/index.tsx", "src/assets/javascripts/templates/search/index.tsx", "src/assets/javascripts/templates/source/index.tsx", "src/assets/javascripts/templates/tabbed/index.tsx", "src/assets/javascripts/templates/table/index.tsx", "src/assets/javascripts/templates/version/index.tsx", "src/assets/javascripts/components/content/annotation/_/index.ts", "src/assets/javascripts/components/content/annotation/list/index.ts", "src/assets/javascripts/components/content/code/mermaid/index.ts", "src/assets/javascripts/components/content/details/index.ts", "src/assets/javascripts/components/content/table/index.ts", "src/assets/javascripts/components/content/tabs/index.ts", "src/assets/javascripts/components/content/_/index.ts", "src/assets/javascripts/components/dialog/index.ts", "src/assets/javascripts/components/header/_/index.ts", "src/assets/javascripts/components/header/title/index.ts", "src/assets/javascripts/components/main/index.ts", "src/assets/javascripts/components/palette/index.ts", "src/assets/javascripts/integrations/clipboard/index.ts", "src/assets/javascripts/integrations/sitemap/index.ts", "src/assets/javascripts/integrations/instant/index.ts", "src/assets/javascripts/integrations/search/document/index.ts", "src/assets/javascripts/integrations/search/highlighter/index.ts", "src/assets/javascripts/integrations/search/query/transform/index.ts", "src/assets/javascripts/integrations/search/worker/message/index.ts", "src/assets/javascripts/integrations/search/worker/_/index.ts", "src/assets/javascripts/integrations/version/index.ts", "src/assets/javascripts/components/search/query/index.ts", "src/assets/javascripts/components/search/result/index.ts", "src/assets/javascripts/components/search/share/index.ts", "src/assets/javascripts/components/search/suggest/index.ts", "src/assets/javascripts/components/search/_/index.ts", "src/assets/javascripts/components/search/highlight/index.ts", "src/assets/javascripts/components/sidebar/index.ts", "src/assets/javascripts/components/source/facts/github/index.ts", "src/assets/javascripts/components/source/facts/gitlab/index.ts", "src/assets/javascripts/components/source/facts/_/index.ts", "src/assets/javascripts/components/source/_/index.ts", "src/assets/javascripts/components/tabs/index.ts", "src/assets/javascripts/components/toc/index.ts", "src/assets/javascripts/components/top/index.ts", "src/assets/javascripts/patches/indeterminate/index.ts", "src/assets/javascripts/patches/scrollfix/index.ts", "src/assets/javascripts/patches/scrolllock/index.ts", "src/assets/javascripts/polyfills/index.ts"], + "sourceRoot": "../../../..", + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "(function(global) {\r\n /**\r\n * Polyfill URLSearchParams\r\n *\r\n * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js\r\n */\r\n\r\n var checkIfIteratorIsSupported = function() {\r\n try {\r\n return !!Symbol.iterator;\r\n } catch (error) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var iteratorSupported = checkIfIteratorIsSupported();\r\n\r\n var createIterator = function(items) {\r\n var iterator = {\r\n next: function() {\r\n var value = items.shift();\r\n return { done: value === void 0, value: value };\r\n }\r\n };\r\n\r\n if (iteratorSupported) {\r\n iterator[Symbol.iterator] = function() {\r\n return iterator;\r\n };\r\n }\r\n\r\n return iterator;\r\n };\r\n\r\n /**\r\n * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing\r\n * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`.\r\n */\r\n var serializeParam = function(value) {\r\n return encodeURIComponent(value).replace(/%20/g, '+');\r\n };\r\n\r\n var deserializeParam = function(value) {\r\n return decodeURIComponent(String(value).replace(/\\+/g, ' '));\r\n };\r\n\r\n var polyfillURLSearchParams = function() {\r\n\r\n var URLSearchParams = function(searchString) {\r\n Object.defineProperty(this, '_entries', { writable: true, value: {} });\r\n var typeofSearchString = typeof searchString;\r\n\r\n if (typeofSearchString === 'undefined') {\r\n // do nothing\r\n } else if (typeofSearchString === 'string') {\r\n if (searchString !== '') {\r\n this._fromString(searchString);\r\n }\r\n } else if (searchString instanceof URLSearchParams) {\r\n var _this = this;\r\n searchString.forEach(function(value, name) {\r\n _this.append(name, value);\r\n });\r\n } else if ((searchString !== null) && (typeofSearchString === 'object')) {\r\n if (Object.prototype.toString.call(searchString) === '[object Array]') {\r\n for (var i = 0; i < searchString.length; i++) {\r\n var entry = searchString[i];\r\n if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) {\r\n this.append(entry[0], entry[1]);\r\n } else {\r\n throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\\'s input');\r\n }\r\n }\r\n } else {\r\n for (var key in searchString) {\r\n if (searchString.hasOwnProperty(key)) {\r\n this.append(key, searchString[key]);\r\n }\r\n }\r\n }\r\n } else {\r\n throw new TypeError('Unsupported input\\'s type for URLSearchParams');\r\n }\r\n };\r\n\r\n var proto = URLSearchParams.prototype;\r\n\r\n proto.append = function(name, value) {\r\n if (name in this._entries) {\r\n this._entries[name].push(String(value));\r\n } else {\r\n this._entries[name] = [String(value)];\r\n }\r\n };\r\n\r\n proto.delete = function(name) {\r\n delete this._entries[name];\r\n };\r\n\r\n proto.get = function(name) {\r\n return (name in this._entries) ? this._entries[name][0] : null;\r\n };\r\n\r\n proto.getAll = function(name) {\r\n return (name in this._entries) ? this._entries[name].slice(0) : [];\r\n };\r\n\r\n proto.has = function(name) {\r\n return (name in this._entries);\r\n };\r\n\r\n proto.set = function(name, value) {\r\n this._entries[name] = [String(value)];\r\n };\r\n\r\n proto.forEach = function(callback, thisArg) {\r\n var entries;\r\n for (var name in this._entries) {\r\n if (this._entries.hasOwnProperty(name)) {\r\n entries = this._entries[name];\r\n for (var i = 0; i < entries.length; i++) {\r\n callback.call(thisArg, entries[i], name, this);\r\n }\r\n }\r\n }\r\n };\r\n\r\n proto.keys = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push(name);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.values = function() {\r\n var items = [];\r\n this.forEach(function(value) {\r\n items.push(value);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n proto.entries = function() {\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n });\r\n return createIterator(items);\r\n };\r\n\r\n if (iteratorSupported) {\r\n proto[Symbol.iterator] = proto.entries;\r\n }\r\n\r\n proto.toString = function() {\r\n var searchArray = [];\r\n this.forEach(function(value, name) {\r\n searchArray.push(serializeParam(name) + '=' + serializeParam(value));\r\n });\r\n return searchArray.join('&');\r\n };\r\n\r\n\r\n global.URLSearchParams = URLSearchParams;\r\n };\r\n\r\n var checkIfURLSearchParamsSupported = function() {\r\n try {\r\n var URLSearchParams = global.URLSearchParams;\r\n\r\n return (\r\n (new URLSearchParams('?a=1').toString() === 'a=1') &&\r\n (typeof URLSearchParams.prototype.set === 'function') &&\r\n (typeof URLSearchParams.prototype.entries === 'function')\r\n );\r\n } catch (e) {\r\n return false;\r\n }\r\n };\r\n\r\n if (!checkIfURLSearchParamsSupported()) {\r\n polyfillURLSearchParams();\r\n }\r\n\r\n var proto = global.URLSearchParams.prototype;\r\n\r\n if (typeof proto.sort !== 'function') {\r\n proto.sort = function() {\r\n var _this = this;\r\n var items = [];\r\n this.forEach(function(value, name) {\r\n items.push([name, value]);\r\n if (!_this._entries) {\r\n _this.delete(name);\r\n }\r\n });\r\n items.sort(function(a, b) {\r\n if (a[0] < b[0]) {\r\n return -1;\r\n } else if (a[0] > b[0]) {\r\n return +1;\r\n } else {\r\n return 0;\r\n }\r\n });\r\n if (_this._entries) { // force reset because IE keeps keys index\r\n _this._entries = {};\r\n }\r\n for (var i = 0; i < items.length; i++) {\r\n this.append(items[i][0], items[i][1]);\r\n }\r\n };\r\n }\r\n\r\n if (typeof proto._fromString !== 'function') {\r\n Object.defineProperty(proto, '_fromString', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function(searchString) {\r\n if (this._entries) {\r\n this._entries = {};\r\n } else {\r\n var keys = [];\r\n this.forEach(function(value, name) {\r\n keys.push(name);\r\n });\r\n for (var i = 0; i < keys.length; i++) {\r\n this.delete(keys[i]);\r\n }\r\n }\r\n\r\n searchString = searchString.replace(/^\\?/, '');\r\n var attributes = searchString.split('&');\r\n var attribute;\r\n for (var i = 0; i < attributes.length; i++) {\r\n attribute = attributes[i].split('=');\r\n this.append(\r\n deserializeParam(attribute[0]),\r\n (attribute.length > 1) ? deserializeParam(attribute[1]) : ''\r\n );\r\n }\r\n }\r\n });\r\n }\r\n\r\n // HTMLAnchorElement\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n\r\n(function(global) {\r\n /**\r\n * Polyfill URL\r\n *\r\n * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js\r\n */\r\n\r\n var checkIfURLIsSupported = function() {\r\n try {\r\n var u = new global.URL('b', 'http://a');\r\n u.pathname = 'c d';\r\n return (u.href === 'http://a/c%20d') && u.searchParams;\r\n } catch (e) {\r\n return false;\r\n }\r\n };\r\n\r\n\r\n var polyfillURL = function() {\r\n var _URL = global.URL;\r\n\r\n var URL = function(url, base) {\r\n if (typeof url !== 'string') url = String(url);\r\n if (base && typeof base !== 'string') base = String(base);\r\n\r\n // Only create another document if the base is different from current location.\r\n var doc = document, baseElement;\r\n if (base && (global.location === void 0 || base !== global.location.href)) {\r\n base = base.toLowerCase();\r\n doc = document.implementation.createHTMLDocument('');\r\n baseElement = doc.createElement('base');\r\n baseElement.href = base;\r\n doc.head.appendChild(baseElement);\r\n try {\r\n if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href);\r\n } catch (err) {\r\n throw new Error('URL unable to set base ' + base + ' due to ' + err);\r\n }\r\n }\r\n\r\n var anchorElement = doc.createElement('a');\r\n anchorElement.href = url;\r\n if (baseElement) {\r\n doc.body.appendChild(anchorElement);\r\n anchorElement.href = anchorElement.href; // force href to refresh\r\n }\r\n\r\n var inputElement = doc.createElement('input');\r\n inputElement.type = 'url';\r\n inputElement.value = url;\r\n\r\n if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || (!inputElement.checkValidity() && !base)) {\r\n throw new TypeError('Invalid URL');\r\n }\r\n\r\n Object.defineProperty(this, '_anchorElement', {\r\n value: anchorElement\r\n });\r\n\r\n\r\n // create a linked searchParams which reflect its changes on URL\r\n var searchParams = new global.URLSearchParams(this.search);\r\n var enableSearchUpdate = true;\r\n var enableSearchParamsUpdate = true;\r\n var _this = this;\r\n ['append', 'delete', 'set'].forEach(function(methodName) {\r\n var method = searchParams[methodName];\r\n searchParams[methodName] = function() {\r\n method.apply(searchParams, arguments);\r\n if (enableSearchUpdate) {\r\n enableSearchParamsUpdate = false;\r\n _this.search = searchParams.toString();\r\n enableSearchParamsUpdate = true;\r\n }\r\n };\r\n });\r\n\r\n Object.defineProperty(this, 'searchParams', {\r\n value: searchParams,\r\n enumerable: true\r\n });\r\n\r\n var search = void 0;\r\n Object.defineProperty(this, '_updateSearchParams', {\r\n enumerable: false,\r\n configurable: false,\r\n writable: false,\r\n value: function() {\r\n if (this.search !== search) {\r\n search = this.search;\r\n if (enableSearchParamsUpdate) {\r\n enableSearchUpdate = false;\r\n this.searchParams._fromString(this.search);\r\n enableSearchUpdate = true;\r\n }\r\n }\r\n }\r\n });\r\n };\r\n\r\n var proto = URL.prototype;\r\n\r\n var linkURLWithAnchorAttribute = function(attributeName) {\r\n Object.defineProperty(proto, attributeName, {\r\n get: function() {\r\n return this._anchorElement[attributeName];\r\n },\r\n set: function(value) {\r\n this._anchorElement[attributeName] = value;\r\n },\r\n enumerable: true\r\n });\r\n };\r\n\r\n ['hash', 'host', 'hostname', 'port', 'protocol']\r\n .forEach(function(attributeName) {\r\n linkURLWithAnchorAttribute(attributeName);\r\n });\r\n\r\n Object.defineProperty(proto, 'search', {\r\n get: function() {\r\n return this._anchorElement['search'];\r\n },\r\n set: function(value) {\r\n this._anchorElement['search'] = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n });\r\n\r\n Object.defineProperties(proto, {\r\n\r\n 'toString': {\r\n get: function() {\r\n var _this = this;\r\n return function() {\r\n return _this.href;\r\n };\r\n }\r\n },\r\n\r\n 'href': {\r\n get: function() {\r\n return this._anchorElement.href.replace(/\\?$/, '');\r\n },\r\n set: function(value) {\r\n this._anchorElement.href = value;\r\n this._updateSearchParams();\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'pathname': {\r\n get: function() {\r\n return this._anchorElement.pathname.replace(/(^\\/?)/, '/');\r\n },\r\n set: function(value) {\r\n this._anchorElement.pathname = value;\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'origin': {\r\n get: function() {\r\n // get expected port from protocol\r\n var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol];\r\n // add port to origin if, expected port is different than actual port\r\n // and it is not empty f.e http://foo:8080\r\n // 8080 != 80 && 8080 != ''\r\n var addPortToOrigin = this._anchorElement.port != expectedPort &&\r\n this._anchorElement.port !== '';\r\n\r\n return this._anchorElement.protocol +\r\n '//' +\r\n this._anchorElement.hostname +\r\n (addPortToOrigin ? (':' + this._anchorElement.port) : '');\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'password': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n\r\n 'username': { // TODO\r\n get: function() {\r\n return '';\r\n },\r\n set: function(value) {\r\n },\r\n enumerable: true\r\n },\r\n });\r\n\r\n URL.createObjectURL = function(blob) {\r\n return _URL.createObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n URL.revokeObjectURL = function(url) {\r\n return _URL.revokeObjectURL.apply(_URL, arguments);\r\n };\r\n\r\n global.URL = URL;\r\n\r\n };\r\n\r\n if (!checkIfURLIsSupported()) {\r\n polyfillURL();\r\n }\r\n\r\n if ((global.location !== void 0) && !('origin' in global.location)) {\r\n var getOrigin = function() {\r\n return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');\r\n };\r\n\r\n try {\r\n Object.defineProperty(global.location, 'origin', {\r\n get: getOrigin,\r\n enumerable: true\r\n });\r\n } catch (e) {\r\n setInterval(function() {\r\n global.location.origin = getOrigin();\r\n }, 100);\r\n }\r\n }\r\n\r\n})(\r\n (typeof global !== 'undefined') ? global\r\n : ((typeof window !== 'undefined') ? window\r\n : ((typeof self !== 'undefined') ? self : this))\r\n);\r\n", "/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global global, define, System, Reflect, Promise */\r\nvar __extends;\r\nvar __assign;\r\nvar __rest;\r\nvar __decorate;\r\nvar __param;\r\nvar __metadata;\r\nvar __awaiter;\r\nvar __generator;\r\nvar __exportStar;\r\nvar __values;\r\nvar __read;\r\nvar __spread;\r\nvar __spreadArrays;\r\nvar __spreadArray;\r\nvar __await;\r\nvar __asyncGenerator;\r\nvar __asyncDelegator;\r\nvar __asyncValues;\r\nvar __makeTemplateObject;\r\nvar __importStar;\r\nvar __importDefault;\r\nvar __classPrivateFieldGet;\r\nvar __classPrivateFieldSet;\r\nvar __createBinding;\r\n(function (factory) {\r\n var root = typeof global === \"object\" ? global : typeof self === \"object\" ? self : typeof this === \"object\" ? this : {};\r\n if (typeof define === \"function\" && define.amd) {\r\n define(\"tslib\", [\"exports\"], function (exports) { factory(createExporter(root, createExporter(exports))); });\r\n }\r\n else if (typeof module === \"object\" && typeof module.exports === \"object\") {\r\n factory(createExporter(root, createExporter(module.exports)));\r\n }\r\n else {\r\n factory(createExporter(root));\r\n }\r\n function createExporter(exports, previous) {\r\n if (exports !== root) {\r\n if (typeof Object.create === \"function\") {\r\n Object.defineProperty(exports, \"__esModule\", { value: true });\r\n }\r\n else {\r\n exports.__esModule = true;\r\n }\r\n }\r\n return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };\r\n }\r\n})\r\n(function (exporter) {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n\r\n __extends = function (d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n\r\n __assign = Object.assign || function (t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n\r\n __rest = function (s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n };\r\n\r\n __decorate = function (decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n };\r\n\r\n __param = function (paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n };\r\n\r\n __metadata = function (metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n };\r\n\r\n __awaiter = function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n };\r\n\r\n __generator = function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n };\r\n\r\n __exportStar = function(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n };\r\n\r\n __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n }) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n });\r\n\r\n __values = function (o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n };\r\n\r\n __read = function (o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n };\r\n\r\n /** @deprecated */\r\n __spread = function () {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n };\r\n\r\n /** @deprecated */\r\n __spreadArrays = function () {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n };\r\n\r\n __spreadArray = function (to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n };\r\n\r\n __await = function (v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n };\r\n\r\n __asyncGenerator = function (thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n };\r\n\r\n __asyncDelegator = function (o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n };\r\n\r\n __asyncValues = function (o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n };\r\n\r\n __makeTemplateObject = function (cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n };\r\n\r\n var __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n }) : function(o, v) {\r\n o[\"default\"] = v;\r\n };\r\n\r\n __importStar = function (mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n };\r\n\r\n __importDefault = function (mod) {\r\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\r\n };\r\n\r\n __classPrivateFieldGet = function (receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n };\r\n\r\n __classPrivateFieldSet = function (receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n };\r\n\r\n exporter(\"__extends\", __extends);\r\n exporter(\"__assign\", __assign);\r\n exporter(\"__rest\", __rest);\r\n exporter(\"__decorate\", __decorate);\r\n exporter(\"__param\", __param);\r\n exporter(\"__metadata\", __metadata);\r\n exporter(\"__awaiter\", __awaiter);\r\n exporter(\"__generator\", __generator);\r\n exporter(\"__exportStar\", __exportStar);\r\n exporter(\"__createBinding\", __createBinding);\r\n exporter(\"__values\", __values);\r\n exporter(\"__read\", __read);\r\n exporter(\"__spread\", __spread);\r\n exporter(\"__spreadArrays\", __spreadArrays);\r\n exporter(\"__spreadArray\", __spreadArray);\r\n exporter(\"__await\", __await);\r\n exporter(\"__asyncGenerator\", __asyncGenerator);\r\n exporter(\"__asyncDelegator\", __asyncDelegator);\r\n exporter(\"__asyncValues\", __asyncValues);\r\n exporter(\"__makeTemplateObject\", __makeTemplateObject);\r\n exporter(\"__importStar\", __importStar);\r\n exporter(\"__importDefault\", __importDefault);\r\n exporter(\"__classPrivateFieldGet\", __classPrivateFieldGet);\r\n exporter(\"__classPrivateFieldSet\", __classPrivateFieldSet);\r\n});\r\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "Array.prototype.flat||Object.defineProperty(Array.prototype,\"flat\",{configurable:!0,value:function r(){var t=isNaN(arguments[0])?1:Number(arguments[0]);return t?Array.prototype.reduce.call(this,function(a,e){return Array.isArray(e)?a.push.apply(a,r.call(e,t-1)):a.push(e),a},[]):Array.prototype.slice.call(this)},writable:!0}),Array.prototype.flatMap||Object.defineProperty(Array.prototype,\"flatMap\",{configurable:!0,value:function(r){return Array.prototype.map.apply(this,arguments).flat()},writable:!0})\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"array-flat-polyfill\"\nimport \"focus-visible\"\nimport \"unfetch/polyfill\"\nimport \"url-polyfill\"\n\nimport {\n EMPTY,\n NEVER,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getOptionalElement,\n requestJSON,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantLoading,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget()\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? __search?.index || requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up instant loading, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantLoading({ document$, location$, viewport$ })\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"[href][rel=prev]\")\n if (typeof prev !== \"undefined\")\n prev.click()\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"[href][rel=next]\")\n if (typeof next !== \"undefined\")\n next.click()\n break\n }\n })\n\n/* Set up patches */\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, { viewport$, header$, target$ })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.component$ = component$ /* Component observable */\n", "self.fetch||(self.fetch=function(e,n){return n=n||{},new Promise(function(t,s){var r=new XMLHttpRequest,o=[],u=[],i={},a=function(){return{ok:2==(r.status/100|0),statusText:r.statusText,status:r.status,url:r.responseURL,text:function(){return Promise.resolve(r.responseText)},json:function(){return Promise.resolve(r.responseText).then(JSON.parse)},blob:function(){return Promise.resolve(new Blob([r.response]))},clone:a,headers:{keys:function(){return o},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var c in r.open(n.method||\"get\",e,!0),r.onload=function(){r.getAllResponseHeaders().replace(/^(.*?):[^\\S\\n]*([\\s\\S]*?)$/gm,function(e,n,t){o.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+\",\"+t:t}),t(a())},r.onerror=s,r.withCredentials=\"include\"==n.credentials,n.headers)r.setRequestHeader(c,n.headers[c]);r.send(n.body||null)})});\n", "import tslib from '../tslib.js';\r\nconst {\r\n __extends,\r\n __assign,\r\n __rest,\r\n __decorate,\r\n __param,\r\n __metadata,\r\n __awaiter,\r\n __generator,\r\n __exportStar,\r\n __createBinding,\r\n __values,\r\n __read,\r\n __spread,\r\n __spreadArrays,\r\n __spreadArray,\r\n __await,\r\n __asyncGenerator,\r\n __asyncDelegator,\r\n __asyncValues,\r\n __makeTemplateObject,\r\n __importStar,\r\n __importDefault,\r\n __classPrivateFieldGet,\r\n __classPrivateFieldSet,\r\n} = tslib;\r\nexport {\r\n __extends,\r\n __assign,\r\n __rest,\r\n __decorate,\r\n __param,\r\n __metadata,\r\n __awaiter,\r\n __generator,\r\n __exportStar,\r\n __createBinding,\r\n __values,\r\n __read,\r\n __spread,\r\n __spreadArrays,\r\n __spreadArray,\r\n __await,\r\n __asyncGenerator,\r\n __asyncDelegator,\r\n __asyncValues,\r\n __makeTemplateObject,\r\n __importStar,\r\n __importDefault,\r\n __classPrivateFieldGet,\r\n __classPrivateFieldSet,\r\n};\r\n", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n ReplaySubject,\n Subject,\n fromEvent\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch document\n *\n * Documents are implemented as subjects, so all downstream observables are\n * automatically updated when a new document is emitted.\n *\n * @returns Document subject\n */\nexport function watchDocument(): Subject {\n const document$ = new ReplaySubject(1)\n fromEvent(document, \"DOMContentLoaded\", { once: true })\n .subscribe(() => document$.next(document))\n\n /* Return document */\n return document$\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Elements\n */\nexport function getElements(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T][]\n\nexport function getElements(\n selector: string, node?: ParentNode\n): T[]\n\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * Note that this function assumes that the element is present. If unsure if an\n * element is existent, use the `getOptionalElement` function instead.\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element\n */\nexport function getElement(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElement(\n selector: string, node?: ParentNode\n): T\n\nexport function getElement(\n selector: string, node: ParentNode = document\n): T {\n const el = getOptionalElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n\n /* Return element */\n return el\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an optional element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element or nothing\n */\nexport function getOptionalElement(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T] | undefined\n\nexport function getOptionalElement(\n selector: string, node?: ParentNode\n): T | undefined\n\nexport function getOptionalElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve the currently active element\n *\n * @returns Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement || undefined\n : undefined\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n debounceTime,\n distinctUntilChanged,\n fromEvent,\n map,\n merge,\n startWith\n} from \"rxjs\"\n\nimport { getActiveElement } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch element focus\n *\n * Previously, this function used `focus` and `blur` events to determine whether\n * an element is focused, but this doesn't work if there are focusable elements\n * within the elements itself. A better solutions are `focusin` and `focusout`\n * events, which bubble up the tree and allow for more fine-grained control.\n *\n * `debounceTime` is necessary, because when a focus change happens inside an\n * element, the observable would first emit `false` and then `true` again.\n *\n * @param el - Element\n *\n * @returns Element focus observable\n */\nexport function watchElementFocus(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(document.body, \"focusin\"),\n fromEvent(document.body, \"focusout\")\n )\n .pipe(\n debounceTime(1),\n map(() => {\n const active = getActiveElement()\n return typeof active !== \"undefined\"\n ? el.contains(active)\n : false\n }),\n startWith(el === getActiveElement()),\n distinctUntilChanged()\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n animationFrameScheduler,\n auditTime,\n fromEvent,\n map,\n merge,\n startWith\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element offset\n *\n * @param el - Element\n *\n * @returns Element offset\n */\nexport function getElementOffset(\n el: HTMLElement\n): ElementOffset {\n return {\n x: el.offsetLeft,\n y: el.offsetTop\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element offset\n *\n * @param el - Element\n *\n * @returns Element offset observable\n */\nexport function watchElementOffset(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(window, \"load\"),\n fromEvent(window, \"resize\")\n )\n .pipe(\n auditTime(0, animationFrameScheduler),\n map(() => getElementOffset(el)),\n startWith(getElementOffset(el))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n animationFrameScheduler,\n auditTime,\n fromEvent,\n map,\n merge,\n startWith\n} from \"rxjs\"\n\nimport { ElementOffset } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element content offset (= scroll offset)\n *\n * @param el - Element\n *\n * @returns Element content offset\n */\nexport function getElementContentOffset(\n el: HTMLElement\n): ElementOffset {\n return {\n x: el.scrollLeft,\n y: el.scrollTop\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element content offset\n *\n * @param el - Element\n *\n * @returns Element content offset observable\n */\nexport function watchElementContentOffset(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"scroll\"),\n fromEvent(window, \"resize\")\n )\n .pipe(\n auditTime(0, animationFrameScheduler),\n map(() => getElementContentOffset(el)),\n startWith(getElementContentOffset(el))\n )\n}\n", "/**\r\n * A collection of shims that provide minimal functionality of the ES6 collections.\r\n *\r\n * These implementations are not meant to be used outside of the ResizeObserver\r\n * modules as they cover only a limited range of use cases.\r\n */\r\n/* eslint-disable require-jsdoc, valid-jsdoc */\r\nvar MapShim = (function () {\r\n if (typeof Map !== 'undefined') {\r\n return Map;\r\n }\r\n /**\r\n * Returns index in provided array that matches the specified key.\r\n *\r\n * @param {Array} arr\r\n * @param {*} key\r\n * @returns {number}\r\n */\r\n function getIndex(arr, key) {\r\n var result = -1;\r\n arr.some(function (entry, index) {\r\n if (entry[0] === key) {\r\n result = index;\r\n return true;\r\n }\r\n return false;\r\n });\r\n return result;\r\n }\r\n return /** @class */ (function () {\r\n function class_1() {\r\n this.__entries__ = [];\r\n }\r\n Object.defineProperty(class_1.prototype, \"size\", {\r\n /**\r\n * @returns {boolean}\r\n */\r\n get: function () {\r\n return this.__entries__.length;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * @param {*} key\r\n * @returns {*}\r\n */\r\n class_1.prototype.get = function (key) {\r\n var index = getIndex(this.__entries__, key);\r\n var entry = this.__entries__[index];\r\n return entry && entry[1];\r\n };\r\n /**\r\n * @param {*} key\r\n * @param {*} value\r\n * @returns {void}\r\n */\r\n class_1.prototype.set = function (key, value) {\r\n var index = getIndex(this.__entries__, key);\r\n if (~index) {\r\n this.__entries__[index][1] = value;\r\n }\r\n else {\r\n this.__entries__.push([key, value]);\r\n }\r\n };\r\n /**\r\n * @param {*} key\r\n * @returns {void}\r\n */\r\n class_1.prototype.delete = function (key) {\r\n var entries = this.__entries__;\r\n var index = getIndex(entries, key);\r\n if (~index) {\r\n entries.splice(index, 1);\r\n }\r\n };\r\n /**\r\n * @param {*} key\r\n * @returns {void}\r\n */\r\n class_1.prototype.has = function (key) {\r\n return !!~getIndex(this.__entries__, key);\r\n };\r\n /**\r\n * @returns {void}\r\n */\r\n class_1.prototype.clear = function () {\r\n this.__entries__.splice(0);\r\n };\r\n /**\r\n * @param {Function} callback\r\n * @param {*} [ctx=null]\r\n * @returns {void}\r\n */\r\n class_1.prototype.forEach = function (callback, ctx) {\r\n if (ctx === void 0) { ctx = null; }\r\n for (var _i = 0, _a = this.__entries__; _i < _a.length; _i++) {\r\n var entry = _a[_i];\r\n callback.call(ctx, entry[1], entry[0]);\r\n }\r\n };\r\n return class_1;\r\n }());\r\n})();\n\n/**\r\n * Detects whether window and document objects are available in current environment.\r\n */\r\nvar isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document;\n\n// Returns global object of a current environment.\r\nvar global$1 = (function () {\r\n if (typeof global !== 'undefined' && global.Math === Math) {\r\n return global;\r\n }\r\n if (typeof self !== 'undefined' && self.Math === Math) {\r\n return self;\r\n }\r\n if (typeof window !== 'undefined' && window.Math === Math) {\r\n return window;\r\n }\r\n // eslint-disable-next-line no-new-func\r\n return Function('return this')();\r\n})();\n\n/**\r\n * A shim for the requestAnimationFrame which falls back to the setTimeout if\r\n * first one is not supported.\r\n *\r\n * @returns {number} Requests' identifier.\r\n */\r\nvar requestAnimationFrame$1 = (function () {\r\n if (typeof requestAnimationFrame === 'function') {\r\n // It's required to use a bounded function because IE sometimes throws\r\n // an \"Invalid calling object\" error if rAF is invoked without the global\r\n // object on the left hand side.\r\n return requestAnimationFrame.bind(global$1);\r\n }\r\n return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); };\r\n})();\n\n// Defines minimum timeout before adding a trailing call.\r\nvar trailingTimeout = 2;\r\n/**\r\n * Creates a wrapper function which ensures that provided callback will be\r\n * invoked only once during the specified delay period.\r\n *\r\n * @param {Function} callback - Function to be invoked after the delay period.\r\n * @param {number} delay - Delay after which to invoke callback.\r\n * @returns {Function}\r\n */\r\nfunction throttle (callback, delay) {\r\n var leadingCall = false, trailingCall = false, lastCallTime = 0;\r\n /**\r\n * Invokes the original callback function and schedules new invocation if\r\n * the \"proxy\" was called during current request.\r\n *\r\n * @returns {void}\r\n */\r\n function resolvePending() {\r\n if (leadingCall) {\r\n leadingCall = false;\r\n callback();\r\n }\r\n if (trailingCall) {\r\n proxy();\r\n }\r\n }\r\n /**\r\n * Callback invoked after the specified delay. It will further postpone\r\n * invocation of the original function delegating it to the\r\n * requestAnimationFrame.\r\n *\r\n * @returns {void}\r\n */\r\n function timeoutCallback() {\r\n requestAnimationFrame$1(resolvePending);\r\n }\r\n /**\r\n * Schedules invocation of the original function.\r\n *\r\n * @returns {void}\r\n */\r\n function proxy() {\r\n var timeStamp = Date.now();\r\n if (leadingCall) {\r\n // Reject immediately following calls.\r\n if (timeStamp - lastCallTime < trailingTimeout) {\r\n return;\r\n }\r\n // Schedule new call to be in invoked when the pending one is resolved.\r\n // This is important for \"transitions\" which never actually start\r\n // immediately so there is a chance that we might miss one if change\r\n // happens amids the pending invocation.\r\n trailingCall = true;\r\n }\r\n else {\r\n leadingCall = true;\r\n trailingCall = false;\r\n setTimeout(timeoutCallback, delay);\r\n }\r\n lastCallTime = timeStamp;\r\n }\r\n return proxy;\r\n}\n\n// Minimum delay before invoking the update of observers.\r\nvar REFRESH_DELAY = 20;\r\n// A list of substrings of CSS properties used to find transition events that\r\n// might affect dimensions of observed elements.\r\nvar transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight'];\r\n// Check if MutationObserver is available.\r\nvar mutationObserverSupported = typeof MutationObserver !== 'undefined';\r\n/**\r\n * Singleton controller class which handles updates of ResizeObserver instances.\r\n */\r\nvar ResizeObserverController = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserverController.\r\n *\r\n * @private\r\n */\r\n function ResizeObserverController() {\r\n /**\r\n * Indicates whether DOM listeners have been added.\r\n *\r\n * @private {boolean}\r\n */\r\n this.connected_ = false;\r\n /**\r\n * Tells that controller has subscribed for Mutation Events.\r\n *\r\n * @private {boolean}\r\n */\r\n this.mutationEventsAdded_ = false;\r\n /**\r\n * Keeps reference to the instance of MutationObserver.\r\n *\r\n * @private {MutationObserver}\r\n */\r\n this.mutationsObserver_ = null;\r\n /**\r\n * A list of connected observers.\r\n *\r\n * @private {Array}\r\n */\r\n this.observers_ = [];\r\n this.onTransitionEnd_ = this.onTransitionEnd_.bind(this);\r\n this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);\r\n }\r\n /**\r\n * Adds observer to observers list.\r\n *\r\n * @param {ResizeObserverSPI} observer - Observer to be added.\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.addObserver = function (observer) {\r\n if (!~this.observers_.indexOf(observer)) {\r\n this.observers_.push(observer);\r\n }\r\n // Add listeners if they haven't been added yet.\r\n if (!this.connected_) {\r\n this.connect_();\r\n }\r\n };\r\n /**\r\n * Removes observer from observers list.\r\n *\r\n * @param {ResizeObserverSPI} observer - Observer to be removed.\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.removeObserver = function (observer) {\r\n var observers = this.observers_;\r\n var index = observers.indexOf(observer);\r\n // Remove observer if it's present in registry.\r\n if (~index) {\r\n observers.splice(index, 1);\r\n }\r\n // Remove listeners if controller has no connected observers.\r\n if (!observers.length && this.connected_) {\r\n this.disconnect_();\r\n }\r\n };\r\n /**\r\n * Invokes the update of observers. It will continue running updates insofar\r\n * it detects changes.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.refresh = function () {\r\n var changesDetected = this.updateObservers_();\r\n // Continue running updates if changes have been detected as there might\r\n // be future ones caused by CSS transitions.\r\n if (changesDetected) {\r\n this.refresh();\r\n }\r\n };\r\n /**\r\n * Updates every observer from observers list and notifies them of queued\r\n * entries.\r\n *\r\n * @private\r\n * @returns {boolean} Returns \"true\" if any observer has detected changes in\r\n * dimensions of it's elements.\r\n */\r\n ResizeObserverController.prototype.updateObservers_ = function () {\r\n // Collect observers that have active observations.\r\n var activeObservers = this.observers_.filter(function (observer) {\r\n return observer.gatherActive(), observer.hasActive();\r\n });\r\n // Deliver notifications in a separate cycle in order to avoid any\r\n // collisions between observers, e.g. when multiple instances of\r\n // ResizeObserver are tracking the same element and the callback of one\r\n // of them changes content dimensions of the observed target. Sometimes\r\n // this may result in notifications being blocked for the rest of observers.\r\n activeObservers.forEach(function (observer) { return observer.broadcastActive(); });\r\n return activeObservers.length > 0;\r\n };\r\n /**\r\n * Initializes DOM listeners.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.connect_ = function () {\r\n // Do nothing if running in a non-browser environment or if listeners\r\n // have been already added.\r\n if (!isBrowser || this.connected_) {\r\n return;\r\n }\r\n // Subscription to the \"Transitionend\" event is used as a workaround for\r\n // delayed transitions. This way it's possible to capture at least the\r\n // final state of an element.\r\n document.addEventListener('transitionend', this.onTransitionEnd_);\r\n window.addEventListener('resize', this.refresh);\r\n if (mutationObserverSupported) {\r\n this.mutationsObserver_ = new MutationObserver(this.refresh);\r\n this.mutationsObserver_.observe(document, {\r\n attributes: true,\r\n childList: true,\r\n characterData: true,\r\n subtree: true\r\n });\r\n }\r\n else {\r\n document.addEventListener('DOMSubtreeModified', this.refresh);\r\n this.mutationEventsAdded_ = true;\r\n }\r\n this.connected_ = true;\r\n };\r\n /**\r\n * Removes DOM listeners.\r\n *\r\n * @private\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.disconnect_ = function () {\r\n // Do nothing if running in a non-browser environment or if listeners\r\n // have been already removed.\r\n if (!isBrowser || !this.connected_) {\r\n return;\r\n }\r\n document.removeEventListener('transitionend', this.onTransitionEnd_);\r\n window.removeEventListener('resize', this.refresh);\r\n if (this.mutationsObserver_) {\r\n this.mutationsObserver_.disconnect();\r\n }\r\n if (this.mutationEventsAdded_) {\r\n document.removeEventListener('DOMSubtreeModified', this.refresh);\r\n }\r\n this.mutationsObserver_ = null;\r\n this.mutationEventsAdded_ = false;\r\n this.connected_ = false;\r\n };\r\n /**\r\n * \"Transitionend\" event handler.\r\n *\r\n * @private\r\n * @param {TransitionEvent} event\r\n * @returns {void}\r\n */\r\n ResizeObserverController.prototype.onTransitionEnd_ = function (_a) {\r\n var _b = _a.propertyName, propertyName = _b === void 0 ? '' : _b;\r\n // Detect whether transition may affect dimensions of an element.\r\n var isReflowProperty = transitionKeys.some(function (key) {\r\n return !!~propertyName.indexOf(key);\r\n });\r\n if (isReflowProperty) {\r\n this.refresh();\r\n }\r\n };\r\n /**\r\n * Returns instance of the ResizeObserverController.\r\n *\r\n * @returns {ResizeObserverController}\r\n */\r\n ResizeObserverController.getInstance = function () {\r\n if (!this.instance_) {\r\n this.instance_ = new ResizeObserverController();\r\n }\r\n return this.instance_;\r\n };\r\n /**\r\n * Holds reference to the controller's instance.\r\n *\r\n * @private {ResizeObserverController}\r\n */\r\n ResizeObserverController.instance_ = null;\r\n return ResizeObserverController;\r\n}());\n\n/**\r\n * Defines non-writable/enumerable properties of the provided target object.\r\n *\r\n * @param {Object} target - Object for which to define properties.\r\n * @param {Object} props - Properties to be defined.\r\n * @returns {Object} Target object.\r\n */\r\nvar defineConfigurable = (function (target, props) {\r\n for (var _i = 0, _a = Object.keys(props); _i < _a.length; _i++) {\r\n var key = _a[_i];\r\n Object.defineProperty(target, key, {\r\n value: props[key],\r\n enumerable: false,\r\n writable: false,\r\n configurable: true\r\n });\r\n }\r\n return target;\r\n});\n\n/**\r\n * Returns the global object associated with provided element.\r\n *\r\n * @param {Object} target\r\n * @returns {Object}\r\n */\r\nvar getWindowOf = (function (target) {\r\n // Assume that the element is an instance of Node, which means that it\r\n // has the \"ownerDocument\" property from which we can retrieve a\r\n // corresponding global object.\r\n var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView;\r\n // Return the local global object if it's not possible extract one from\r\n // provided element.\r\n return ownerGlobal || global$1;\r\n});\n\n// Placeholder of an empty content rectangle.\r\nvar emptyRect = createRectInit(0, 0, 0, 0);\r\n/**\r\n * Converts provided string to a number.\r\n *\r\n * @param {number|string} value\r\n * @returns {number}\r\n */\r\nfunction toFloat(value) {\r\n return parseFloat(value) || 0;\r\n}\r\n/**\r\n * Extracts borders size from provided styles.\r\n *\r\n * @param {CSSStyleDeclaration} styles\r\n * @param {...string} positions - Borders positions (top, right, ...)\r\n * @returns {number}\r\n */\r\nfunction getBordersSize(styles) {\r\n var positions = [];\r\n for (var _i = 1; _i < arguments.length; _i++) {\r\n positions[_i - 1] = arguments[_i];\r\n }\r\n return positions.reduce(function (size, position) {\r\n var value = styles['border-' + position + '-width'];\r\n return size + toFloat(value);\r\n }, 0);\r\n}\r\n/**\r\n * Extracts paddings sizes from provided styles.\r\n *\r\n * @param {CSSStyleDeclaration} styles\r\n * @returns {Object} Paddings box.\r\n */\r\nfunction getPaddings(styles) {\r\n var positions = ['top', 'right', 'bottom', 'left'];\r\n var paddings = {};\r\n for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {\r\n var position = positions_1[_i];\r\n var value = styles['padding-' + position];\r\n paddings[position] = toFloat(value);\r\n }\r\n return paddings;\r\n}\r\n/**\r\n * Calculates content rectangle of provided SVG element.\r\n *\r\n * @param {SVGGraphicsElement} target - Element content rectangle of which needs\r\n * to be calculated.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getSVGContentRect(target) {\r\n var bbox = target.getBBox();\r\n return createRectInit(0, 0, bbox.width, bbox.height);\r\n}\r\n/**\r\n * Calculates content rectangle of provided HTMLElement.\r\n *\r\n * @param {HTMLElement} target - Element for which to calculate the content rectangle.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getHTMLElementContentRect(target) {\r\n // Client width & height properties can't be\r\n // used exclusively as they provide rounded values.\r\n var clientWidth = target.clientWidth, clientHeight = target.clientHeight;\r\n // By this condition we can catch all non-replaced inline, hidden and\r\n // detached elements. Though elements with width & height properties less\r\n // than 0.5 will be discarded as well.\r\n //\r\n // Without it we would need to implement separate methods for each of\r\n // those cases and it's not possible to perform a precise and performance\r\n // effective test for hidden elements. E.g. even jQuery's ':visible' filter\r\n // gives wrong results for elements with width & height less than 0.5.\r\n if (!clientWidth && !clientHeight) {\r\n return emptyRect;\r\n }\r\n var styles = getWindowOf(target).getComputedStyle(target);\r\n var paddings = getPaddings(styles);\r\n var horizPad = paddings.left + paddings.right;\r\n var vertPad = paddings.top + paddings.bottom;\r\n // Computed styles of width & height are being used because they are the\r\n // only dimensions available to JS that contain non-rounded values. It could\r\n // be possible to utilize the getBoundingClientRect if only it's data wasn't\r\n // affected by CSS transformations let alone paddings, borders and scroll bars.\r\n var width = toFloat(styles.width), height = toFloat(styles.height);\r\n // Width & height include paddings and borders when the 'border-box' box\r\n // model is applied (except for IE).\r\n if (styles.boxSizing === 'border-box') {\r\n // Following conditions are required to handle Internet Explorer which\r\n // doesn't include paddings and borders to computed CSS dimensions.\r\n //\r\n // We can say that if CSS dimensions + paddings are equal to the \"client\"\r\n // properties then it's either IE, and thus we don't need to subtract\r\n // anything, or an element merely doesn't have paddings/borders styles.\r\n if (Math.round(width + horizPad) !== clientWidth) {\r\n width -= getBordersSize(styles, 'left', 'right') + horizPad;\r\n }\r\n if (Math.round(height + vertPad) !== clientHeight) {\r\n height -= getBordersSize(styles, 'top', 'bottom') + vertPad;\r\n }\r\n }\r\n // Following steps can't be applied to the document's root element as its\r\n // client[Width/Height] properties represent viewport area of the window.\r\n // Besides, it's as well not necessary as the itself neither has\r\n // rendered scroll bars nor it can be clipped.\r\n if (!isDocumentElement(target)) {\r\n // In some browsers (only in Firefox, actually) CSS width & height\r\n // include scroll bars size which can be removed at this step as scroll\r\n // bars are the only difference between rounded dimensions + paddings\r\n // and \"client\" properties, though that is not always true in Chrome.\r\n var vertScrollbar = Math.round(width + horizPad) - clientWidth;\r\n var horizScrollbar = Math.round(height + vertPad) - clientHeight;\r\n // Chrome has a rather weird rounding of \"client\" properties.\r\n // E.g. for an element with content width of 314.2px it sometimes gives\r\n // the client width of 315px and for the width of 314.7px it may give\r\n // 314px. And it doesn't happen all the time. So just ignore this delta\r\n // as a non-relevant.\r\n if (Math.abs(vertScrollbar) !== 1) {\r\n width -= vertScrollbar;\r\n }\r\n if (Math.abs(horizScrollbar) !== 1) {\r\n height -= horizScrollbar;\r\n }\r\n }\r\n return createRectInit(paddings.left, paddings.top, width, height);\r\n}\r\n/**\r\n * Checks whether provided element is an instance of the SVGGraphicsElement.\r\n *\r\n * @param {Element} target - Element to be checked.\r\n * @returns {boolean}\r\n */\r\nvar isSVGGraphicsElement = (function () {\r\n // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement\r\n // interface.\r\n if (typeof SVGGraphicsElement !== 'undefined') {\r\n return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; };\r\n }\r\n // If it's so, then check that element is at least an instance of the\r\n // SVGElement and that it has the \"getBBox\" method.\r\n // eslint-disable-next-line no-extra-parens\r\n return function (target) { return (target instanceof getWindowOf(target).SVGElement &&\r\n typeof target.getBBox === 'function'); };\r\n})();\r\n/**\r\n * Checks whether provided element is a document element ().\r\n *\r\n * @param {Element} target - Element to be checked.\r\n * @returns {boolean}\r\n */\r\nfunction isDocumentElement(target) {\r\n return target === getWindowOf(target).document.documentElement;\r\n}\r\n/**\r\n * Calculates an appropriate content rectangle for provided html or svg element.\r\n *\r\n * @param {Element} target - Element content rectangle of which needs to be calculated.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction getContentRect(target) {\r\n if (!isBrowser) {\r\n return emptyRect;\r\n }\r\n if (isSVGGraphicsElement(target)) {\r\n return getSVGContentRect(target);\r\n }\r\n return getHTMLElementContentRect(target);\r\n}\r\n/**\r\n * Creates rectangle with an interface of the DOMRectReadOnly.\r\n * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly\r\n *\r\n * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions.\r\n * @returns {DOMRectReadOnly}\r\n */\r\nfunction createReadOnlyRect(_a) {\r\n var x = _a.x, y = _a.y, width = _a.width, height = _a.height;\r\n // If DOMRectReadOnly is available use it as a prototype for the rectangle.\r\n var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object;\r\n var rect = Object.create(Constr.prototype);\r\n // Rectangle's properties are not writable and non-enumerable.\r\n defineConfigurable(rect, {\r\n x: x, y: y, width: width, height: height,\r\n top: y,\r\n right: x + width,\r\n bottom: height + y,\r\n left: x\r\n });\r\n return rect;\r\n}\r\n/**\r\n * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates.\r\n * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit\r\n *\r\n * @param {number} x - X coordinate.\r\n * @param {number} y - Y coordinate.\r\n * @param {number} width - Rectangle's width.\r\n * @param {number} height - Rectangle's height.\r\n * @returns {DOMRectInit}\r\n */\r\nfunction createRectInit(x, y, width, height) {\r\n return { x: x, y: y, width: width, height: height };\r\n}\n\n/**\r\n * Class that is responsible for computations of the content rectangle of\r\n * provided DOM element and for keeping track of it's changes.\r\n */\r\nvar ResizeObservation = /** @class */ (function () {\r\n /**\r\n * Creates an instance of ResizeObservation.\r\n *\r\n * @param {Element} target - Element to be observed.\r\n */\r\n function ResizeObservation(target) {\r\n /**\r\n * Broadcasted width of content rectangle.\r\n *\r\n * @type {number}\r\n */\r\n this.broadcastWidth = 0;\r\n /**\r\n * Broadcasted height of content rectangle.\r\n *\r\n * @type {number}\r\n */\r\n this.broadcastHeight = 0;\r\n /**\r\n * Reference to the last observed content rectangle.\r\n *\r\n * @private {DOMRectInit}\r\n */\r\n this.contentRect_ = createRectInit(0, 0, 0, 0);\r\n this.target = target;\r\n }\r\n /**\r\n * Updates content rectangle and tells whether it's width or height properties\r\n * have changed since the last broadcast.\r\n *\r\n * @returns {boolean}\r\n */\r\n ResizeObservation.prototype.isActive = function () {\r\n var rect = getContentRect(this.target);\r\n this.contentRect_ = rect;\r\n return (rect.width !== this.broadcastWidth ||\r\n rect.height !== this.broadcastHeight);\r\n };\r\n /**\r\n * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data\r\n * from the corresponding properties of the last observed content rectangle.\r\n *\r\n * @returns {DOMRectInit} Last observed content rectangle.\r\n */\r\n ResizeObservation.prototype.broadcastRect = function () {\r\n var rect = this.contentRect_;\r\n this.broadcastWidth = rect.width;\r\n this.broadcastHeight = rect.height;\r\n return rect;\r\n };\r\n return ResizeObservation;\r\n}());\n\nvar ResizeObserverEntry = /** @class */ (function () {\r\n /**\r\n * Creates an instance of ResizeObserverEntry.\r\n *\r\n * @param {Element} target - Element that is being observed.\r\n * @param {DOMRectInit} rectInit - Data of the element's content rectangle.\r\n */\r\n function ResizeObserverEntry(target, rectInit) {\r\n var contentRect = createReadOnlyRect(rectInit);\r\n // According to the specification following properties are not writable\r\n // and are also not enumerable in the native implementation.\r\n //\r\n // Property accessors are not being used as they'd require to define a\r\n // private WeakMap storage which may cause memory leaks in browsers that\r\n // don't support this type of collections.\r\n defineConfigurable(this, { target: target, contentRect: contentRect });\r\n }\r\n return ResizeObserverEntry;\r\n}());\n\nvar ResizeObserverSPI = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserver.\r\n *\r\n * @param {ResizeObserverCallback} callback - Callback function that is invoked\r\n * when one of the observed elements changes it's content dimensions.\r\n * @param {ResizeObserverController} controller - Controller instance which\r\n * is responsible for the updates of observer.\r\n * @param {ResizeObserver} callbackCtx - Reference to the public\r\n * ResizeObserver instance which will be passed to callback function.\r\n */\r\n function ResizeObserverSPI(callback, controller, callbackCtx) {\r\n /**\r\n * Collection of resize observations that have detected changes in dimensions\r\n * of elements.\r\n *\r\n * @private {Array}\r\n */\r\n this.activeObservations_ = [];\r\n /**\r\n * Registry of the ResizeObservation instances.\r\n *\r\n * @private {Map}\r\n */\r\n this.observations_ = new MapShim();\r\n if (typeof callback !== 'function') {\r\n throw new TypeError('The callback provided as parameter 1 is not a function.');\r\n }\r\n this.callback_ = callback;\r\n this.controller_ = controller;\r\n this.callbackCtx_ = callbackCtx;\r\n }\r\n /**\r\n * Starts observing provided element.\r\n *\r\n * @param {Element} target - Element to be observed.\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.observe = function (target) {\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n // Do nothing if current environment doesn't have the Element interface.\r\n if (typeof Element === 'undefined' || !(Element instanceof Object)) {\r\n return;\r\n }\r\n if (!(target instanceof getWindowOf(target).Element)) {\r\n throw new TypeError('parameter 1 is not of type \"Element\".');\r\n }\r\n var observations = this.observations_;\r\n // Do nothing if element is already being observed.\r\n if (observations.has(target)) {\r\n return;\r\n }\r\n observations.set(target, new ResizeObservation(target));\r\n this.controller_.addObserver(this);\r\n // Force the update of observations.\r\n this.controller_.refresh();\r\n };\r\n /**\r\n * Stops observing provided element.\r\n *\r\n * @param {Element} target - Element to stop observing.\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.unobserve = function (target) {\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n // Do nothing if current environment doesn't have the Element interface.\r\n if (typeof Element === 'undefined' || !(Element instanceof Object)) {\r\n return;\r\n }\r\n if (!(target instanceof getWindowOf(target).Element)) {\r\n throw new TypeError('parameter 1 is not of type \"Element\".');\r\n }\r\n var observations = this.observations_;\r\n // Do nothing if element is not being observed.\r\n if (!observations.has(target)) {\r\n return;\r\n }\r\n observations.delete(target);\r\n if (!observations.size) {\r\n this.controller_.removeObserver(this);\r\n }\r\n };\r\n /**\r\n * Stops observing all elements.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.disconnect = function () {\r\n this.clearActive();\r\n this.observations_.clear();\r\n this.controller_.removeObserver(this);\r\n };\r\n /**\r\n * Collects observation instances the associated element of which has changed\r\n * it's content rectangle.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.gatherActive = function () {\r\n var _this = this;\r\n this.clearActive();\r\n this.observations_.forEach(function (observation) {\r\n if (observation.isActive()) {\r\n _this.activeObservations_.push(observation);\r\n }\r\n });\r\n };\r\n /**\r\n * Invokes initial callback function with a list of ResizeObserverEntry\r\n * instances collected from active resize observations.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.broadcastActive = function () {\r\n // Do nothing if observer doesn't have active observations.\r\n if (!this.hasActive()) {\r\n return;\r\n }\r\n var ctx = this.callbackCtx_;\r\n // Create ResizeObserverEntry instance for every active observation.\r\n var entries = this.activeObservations_.map(function (observation) {\r\n return new ResizeObserverEntry(observation.target, observation.broadcastRect());\r\n });\r\n this.callback_.call(ctx, entries, ctx);\r\n this.clearActive();\r\n };\r\n /**\r\n * Clears the collection of active observations.\r\n *\r\n * @returns {void}\r\n */\r\n ResizeObserverSPI.prototype.clearActive = function () {\r\n this.activeObservations_.splice(0);\r\n };\r\n /**\r\n * Tells whether observer has active observations.\r\n *\r\n * @returns {boolean}\r\n */\r\n ResizeObserverSPI.prototype.hasActive = function () {\r\n return this.activeObservations_.length > 0;\r\n };\r\n return ResizeObserverSPI;\r\n}());\n\n// Registry of internal observers. If WeakMap is not available use current shim\r\n// for the Map collection as it has all required methods and because WeakMap\r\n// can't be fully polyfilled anyway.\r\nvar observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim();\r\n/**\r\n * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation\r\n * exposing only those methods and properties that are defined in the spec.\r\n */\r\nvar ResizeObserver = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of ResizeObserver.\r\n *\r\n * @param {ResizeObserverCallback} callback - Callback that is invoked when\r\n * dimensions of the observed elements change.\r\n */\r\n function ResizeObserver(callback) {\r\n if (!(this instanceof ResizeObserver)) {\r\n throw new TypeError('Cannot call a class as a function.');\r\n }\r\n if (!arguments.length) {\r\n throw new TypeError('1 argument required, but only 0 present.');\r\n }\r\n var controller = ResizeObserverController.getInstance();\r\n var observer = new ResizeObserverSPI(callback, controller, this);\r\n observers.set(this, observer);\r\n }\r\n return ResizeObserver;\r\n}());\r\n// Expose public methods of ResizeObserver.\r\n[\r\n 'observe',\r\n 'unobserve',\r\n 'disconnect'\r\n].forEach(function (method) {\r\n ResizeObserver.prototype[method] = function () {\r\n var _a;\r\n return (_a = observers.get(this))[method].apply(_a, arguments);\r\n };\r\n});\n\nvar index = (function () {\r\n // Export existing implementation if available.\r\n if (typeof global$1.ResizeObserver !== 'undefined') {\r\n return global$1.ResizeObserver;\r\n }\r\n return ResizeObserver;\r\n})();\n\nexport default index;\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ResizeObserver from \"resize-observer-polyfill\"\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n filter,\n finalize,\n map,\n merge,\n of,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(observer => merge(NEVER, of(observer))\n .pipe(\n finalize(() => observer.disconnect())\n )\n ),\n shareReplay(1)\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementSize(\n el: HTMLElement\n): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that subscribes to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * Sadly, we can't use the `DOMRect` objects returned by the observer, because\n * we need the emitted values to be consistent with `getElementSize`, which will\n * return the used values (rounded) and not actual values (unrounded). Thus, we\n * use the `offset*` properties. See the linked GitHub issue.\n *\n * @see https://bit.ly/3m0k3he - GitHub issue\n *\n * @param el - Element\n *\n * @returns Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(() => getElementSize(el))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ElementSize } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element content size (= scroll width and height)\n *\n * @param el - Element\n *\n * @returns Element content size\n */\nexport function getElementContentSize(\n el: HTMLElement\n): ElementSize {\n return {\n width: el.scrollWidth,\n height: el.scrollHeight\n }\n}\n\n/**\n * Retrieve the overflowing container of an element, if any\n *\n * @param el - Element\n *\n * @returns Overflowing container or nothing\n */\nexport function getElementContainer(\n el: HTMLElement\n): HTMLElement | undefined {\n let parent = el.parentElement\n while (parent)\n if (\n el.scrollWidth <= parent.scrollWidth &&\n el.scrollHeight <= parent.scrollHeight\n )\n parent = (el = parent).parentElement\n else\n break\n\n /* Return overflowing container */\n return parent ? el : undefined\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n distinctUntilChanged,\n filter,\n finalize,\n map,\n merge,\n of,\n shareReplay,\n switchMap,\n tap\n} from \"rxjs\"\n\nimport {\n getElementContentSize,\n getElementSize,\n watchElementContentOffset\n} from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Intersection observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Intersection observer observable\n *\n * This observable will create an `IntersectionObserver` on first subscription\n * and will automatically terminate it when there are no more subscribers.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new IntersectionObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n }, {\n threshold: 0\n })\n))\n .pipe(\n switchMap(observer => merge(NEVER, of(observer))\n .pipe(\n finalize(() => observer.disconnect())\n )\n ),\n shareReplay(1)\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch element visibility\n *\n * @param el - Element\n *\n * @returns Element visibility observable\n */\nexport function watchElementVisibility(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ isIntersecting }) => isIntersecting)\n )\n )\n )\n}\n\n/**\n * Watch element boundary\n *\n * This function returns an observable which emits whether the bottom content\n * boundary (= scroll offset) of an element is within a certain threshold.\n *\n * @param el - Element\n * @param threshold - Threshold\n *\n * @returns Element boundary observable\n */\nexport function watchElementBoundary(\n el: HTMLElement, threshold = 16\n): Observable {\n return watchElementContentOffset(el)\n .pipe(\n map(({ y }) => {\n const visible = getElementSize(el)\n const content = getElementContentSize(el)\n return y >= (\n content.height - visible.height - threshold\n )\n }),\n distinctUntilChanged()\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n fromEvent,\n map,\n startWith\n} from \"rxjs\"\n\nimport { getElement } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElement(\"[data-md-toggle=drawer]\"),\n search: getElement(\"[data-md-toggle=search]\")\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n filter,\n fromEvent,\n map,\n share\n} from \"rxjs\"\n\nimport { getActiveElement } from \"../element\"\nimport { getToggle } from \"../toggle\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Keyboard mode\n */\nexport type KeyboardMode =\n | \"global\" /* Global */\n | \"search\" /* Search is open */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Keyboard\n */\nexport interface Keyboard {\n mode: KeyboardMode /* Keyboard mode */\n type: string /* Key type */\n claim(): void /* Key claim */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether an element may receive keyboard input\n *\n * @param el - Element\n * @param type - Key type\n *\n * @returns Test result\n */\nfunction isSusceptibleToKeyboard(\n el: HTMLElement, type: string\n): boolean {\n switch (el.constructor) {\n\n /* Input elements */\n case HTMLInputElement:\n /* @ts-expect-error - omit unnecessary type cast */\n if (el.type === \"radio\")\n return /^Arrow/.test(type)\n else\n return true\n\n /* Select element and textarea */\n case HTMLSelectElement:\n case HTMLTextAreaElement:\n return true\n\n /* Everything else */\n default:\n return el.isContentEditable\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch keyboard\n *\n * @returns Keyboard observable\n */\nexport function watchKeyboard(): Observable {\n return fromEvent(window, \"keydown\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n map(ev => ({\n mode: getToggle(\"search\") ? \"search\" : \"global\",\n type: ev.key,\n claim() {\n ev.preventDefault()\n ev.stopPropagation()\n }\n } as Keyboard)),\n filter(({ mode, type }) => {\n if (mode === \"global\") {\n const active = getActiveElement()\n if (typeof active !== \"undefined\")\n return !isSusceptibleToKeyboard(active, type)\n }\n return true\n }),\n share()\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Subject } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location\n *\n * This function returns a `URL` object (and not `Location`) to normalize the\n * typings across the application. Furthermore, locations need to be tracked\n * without setting them and `Location` is a singleton which represents the\n * current location.\n *\n * @returns URL\n */\nexport function getLocation(): URL {\n return new URL(location.href)\n}\n\n/**\n * Set location\n *\n * @param url - URL to change to\n */\nexport function setLocation(url: URL): void {\n location.href = url.href\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @returns Location subject\n */\nexport function watchLocation(): Subject {\n return new Subject()\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @template T - Element type\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @returns Element\n */\nexport function h(\n tag: T, attributes?: Attributes | null, ...children: Child[]\n): HTMLElementTagNameMap[T]\n\nexport function h(\n tag: string, attributes?: Attributes | null, ...children: Child[]\n): T\n\nexport function h(\n tag: string, attributes?: Attributes | null, ...children: Child[]\n): T {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes)) {\n if (typeof attributes[attr] === \"undefined\")\n continue\n\n /* Set default attribute or boolean */\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else\n el.setAttribute(attr, \"\")\n }\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el as T\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @returns Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0) { /* keep eating */ }\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with repository facts\n *\n * This is a reverse-engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @returns Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n filter,\n fromEvent,\n map,\n shareReplay,\n startWith\n} from \"rxjs\"\n\nimport { getOptionalElement } from \"~/browser\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @returns Location hash\n */\nexport function getLocationHash(): string {\n return location.hash.substring(1)\n}\n\n/**\n * Set location hash\n *\n * Setting a new fragment identifier via `location.hash` will have no effect\n * if the value doesn't change. When a new fragment identifier is set, we want\n * the browser to target the respective element at all times, which is why we\n * use this dirty little trick.\n *\n * @param hash - Location hash\n */\nexport function setLocationHash(hash: string): void {\n const el = h(\"a\", { href: hash })\n el.addEventListener(\"click\", ev => ev.stopPropagation())\n el.click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location hash\n *\n * @returns Location hash observable\n */\nexport function watchLocationHash(): Observable {\n return fromEvent(window, \"hashchange\")\n .pipe(\n map(getLocationHash),\n startWith(getLocationHash()),\n filter(hash => hash.length > 0),\n shareReplay(1)\n )\n}\n\n/**\n * Watch location target\n *\n * @returns Location target observable\n */\nexport function watchLocationTarget(): Observable {\n return watchLocationHash()\n .pipe(\n map(id => getOptionalElement(`[id=\"${id}\"]`)!),\n filter(el => typeof el !== \"undefined\")\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n fromEvent,\n fromEventPattern,\n map,\n merge,\n startWith,\n switchMap\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * Note that although `MediaQueryList.addListener` is deprecated we have to\n * use it, because it's the only way to ensure proper downward compatibility.\n *\n * @see https://bit.ly/3dUBH2m - GitHub issue\n *\n * @param query - Media query\n *\n * @returns Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return fromEventPattern(next => (\n media.addListener(() => next(media.matches))\n ))\n .pipe(\n startWith(media.matches)\n )\n}\n\n/**\n * Watch print mode\n *\n * @returns Print observable\n */\nexport function watchPrint(): Observable {\n const media = matchMedia(\"print\")\n return merge(\n fromEvent(window, \"beforeprint\").pipe(map(() => true)),\n fromEvent(window, \"afterprint\").pipe(map(() => false))\n )\n .pipe(\n startWith(media.matches)\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Toggle an observable with a media observable\n *\n * @template T - Data type\n *\n * @param query$ - Media observable\n * @param factory - Observable factory\n *\n * @returns Toggled observable\n */\nexport function at(\n query$: Observable, factory: () => Observable\n): Observable {\n return query$\n .pipe(\n switchMap(active => active ? factory() : EMPTY)\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n catchError,\n from,\n map,\n of,\n shareReplay,\n switchMap,\n throwError\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch the given URL\n *\n * If the request fails (e.g. when dispatched from `file://` locations), the\n * observable will complete without emitting a value.\n *\n * @param url - Request URL\n * @param options - Options\n *\n * @returns Response observable\n */\nexport function request(\n url: URL | string, options: RequestInit = { credentials: \"same-origin\" }\n): Observable {\n return from(fetch(`${url}`, options))\n .pipe(\n catchError(() => EMPTY),\n switchMap(res => res.status !== 200\n ? throwError(() => new Error(res.statusText))\n : of(res)\n )\n )\n}\n\n/**\n * Fetch JSON from the given URL\n *\n * @template T - Data type\n *\n * @param url - Request URL\n * @param options - Options\n *\n * @returns Data observable\n */\nexport function requestJSON(\n url: URL | string, options?: RequestInit\n): Observable {\n return request(url, options)\n .pipe(\n switchMap(res => res.json()),\n shareReplay(1)\n )\n}\n\n/**\n * Fetch XML from the given URL\n *\n * @param url - Request URL\n * @param options - Options\n *\n * @returns Data observable\n */\nexport function requestXML(\n url: URL | string, options?: RequestInit\n): Observable {\n const dom = new DOMParser()\n return request(url, options)\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/xml\")),\n shareReplay(1)\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n defer,\n finalize,\n fromEvent,\n map,\n merge,\n switchMap,\n take,\n throwError\n} from \"rxjs\"\n\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create and load a `script` element\n *\n * This function returns an observable that will emit when the script was\n * successfully loaded, or throw an error if it didn't.\n *\n * @param src - Script URL\n *\n * @returns Script observable\n */\nexport function watchScript(src: string): Observable {\n const script = h(\"script\", { src })\n return defer(() => {\n document.head.appendChild(script)\n return merge(\n fromEvent(script, \"load\"),\n fromEvent(script, \"error\")\n .pipe(\n switchMap(() => (\n throwError(() => new ReferenceError(`Invalid script: ${src}`))\n ))\n )\n )\n .pipe(\n map(() => undefined),\n finalize(() => document.head.removeChild(script)),\n take(1)\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n fromEvent,\n map,\n merge,\n startWith\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport offset\n */\nexport interface ViewportOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport offset\n *\n * On iOS Safari, viewport offset can be negative due to overflow scrolling.\n * As this may induce strange behaviors downstream, we'll just limit it to 0.\n *\n * @returns Viewport offset\n */\nexport function getViewportOffset(): ViewportOffset {\n return {\n x: Math.max(0, scrollX),\n y: Math.max(0, scrollY)\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport offset\n *\n * @returns Viewport offset observable\n */\nexport function watchViewportOffset(): Observable {\n return merge(\n fromEvent(window, \"scroll\", { passive: true }),\n fromEvent(window, \"resize\", { passive: true })\n )\n .pipe(\n map(getViewportOffset),\n startWith(getViewportOffset())\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n fromEvent,\n map,\n startWith\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport size\n */\nexport interface ViewportSize {\n width: number /* Viewport width */\n height: number /* Viewport height */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport size\n *\n * @returns Viewport size\n */\nexport function getViewportSize(): ViewportSize {\n return {\n width: innerWidth,\n height: innerHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport size\n *\n * @returns Viewport size observable\n */\nexport function watchViewportSize(): Observable {\n return fromEvent(window, \"resize\", { passive: true })\n .pipe(\n map(getViewportSize),\n startWith(getViewportSize())\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest,\n map,\n shareReplay\n} from \"rxjs\"\n\nimport {\n ViewportOffset,\n watchViewportOffset\n} from \"../offset\"\nimport {\n ViewportSize,\n watchViewportSize\n} from \"../size\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport\n */\nexport interface Viewport {\n offset: ViewportOffset /* Viewport offset */\n size: ViewportSize /* Viewport size */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @returns Viewport observable\n */\nexport function watchViewport(): Observable {\n return combineLatest([\n watchViewportOffset(),\n watchViewportSize()\n ])\n .pipe(\n map(([offset, size]) => ({ offset, size })),\n shareReplay(1)\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest,\n distinctUntilKeyChanged,\n map\n} from \"rxjs\"\n\nimport { Header } from \"~/components\"\n\nimport { getElementOffset } from \"../../element\"\nimport { Viewport } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
/* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport relative to element\n *\n * @param el - Element\n * @param options - Options\n *\n * @returns Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Compute element offset */\n const offset$ = combineLatest([size$, header$])\n .pipe(\n map(() => getElementOffset(el))\n )\n\n /* Compute relative viewport, return hot observable */\n return combineLatest([header$, viewport$, offset$])\n .pipe(\n map(([{ height }, { offset, size }, { x, y }]) => ({\n offset: {\n x: offset.x - x,\n y: offset.y - y + height\n },\n size\n }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n fromEvent,\n map,\n share,\n switchMap,\n tap,\n throttle\n} from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Worker message\n */\nexport interface WorkerMessage {\n type: unknown /* Message type */\n data?: unknown /* Message data */\n}\n\n/**\n * Worker handler\n *\n * @template T - Message type\n */\nexport interface WorkerHandler<\n T extends WorkerMessage\n> {\n tx$: Subject /* Message transmission subject */\n rx$: Observable /* Message receive observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n *\n * @template T - Worker message type\n */\ninterface WatchOptions {\n tx$: Observable /* Message transmission observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch a web worker\n *\n * This function returns an observable that sends all values emitted by the\n * message observable to the web worker. Web worker communication is expected\n * to be bidirectional (request-response) and synchronous. Messages that are\n * emitted during a pending request are throttled, the last one is emitted.\n *\n * @param worker - Web worker\n * @param options - Options\n *\n * @returns Worker message observable\n */\nexport function watchWorker(\n worker: Worker, { tx$ }: WatchOptions\n): Observable {\n\n /* Intercept messages from worker-like objects */\n const rx$ = fromEvent(worker, \"message\")\n .pipe(\n map(({ data }) => data as T)\n )\n\n /* Send and receive messages, return hot observable */\n return tx$\n .pipe(\n throttle(() => rx$, { leading: true, trailing: true }),\n tap(message => worker.postMessage(message)),\n switchMap(() => rx$),\n share()\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElement, getLocation } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flag\n */\nexport type Flag =\n | \"announce.dismiss\" /* Dismissable announcement bar */\n | \"content.code.annotate\" /* Code annotations */\n | \"content.lazy\" /* Lazy content elements */\n | \"content.tabs.link\" /* Link content tabs */\n | \"header.autohide\" /* Hide header */\n | \"navigation.expand\" /* Automatic expansion */\n | \"navigation.indexes\" /* Section pages */\n | \"navigation.instant\" /* Instant loading */\n | \"navigation.sections\" /* Section navigation */\n | \"navigation.tabs\" /* Tabs navigation */\n | \"navigation.tabs.sticky\" /* Tabs navigation (sticky) */\n | \"navigation.top\" /* Back-to-top button */\n | \"navigation.tracking\" /* Anchor tracking */\n | \"search.highlight\" /* Search highlighting */\n | \"search.share\" /* Search sharing */\n | \"search.suggest\" /* Search suggestions */\n | \"toc.follow\" /* Following table of contents */\n | \"toc.integrate\" /* Integrated table of contents */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Translation\n */\nexport type Translation =\n | \"clipboard.copy\" /* Copy to clipboard */\n | \"clipboard.copied\" /* Copied to clipboard */\n | \"search.config.lang\" /* Search language */\n | \"search.config.pipeline\" /* Search pipeline */\n | \"search.config.separator\" /* Search separator */\n | \"search.placeholder\" /* Search */\n | \"search.result.placeholder\" /* Type to start searching */\n | \"search.result.none\" /* No matching documents */\n | \"search.result.one\" /* 1 matching document */\n | \"search.result.other\" /* # matching documents */\n | \"search.result.more.one\" /* 1 more on this page */\n | \"search.result.more.other\" /* # more on this page */\n | \"search.result.term.missing\" /* Missing */\n | \"select.version.title\" /* Version selector */\n\n/**\n * Translations\n */\nexport type Translations = Record\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Versioning\n */\nexport interface Versioning {\n provider: \"mike\" /* Version provider */\n default?: string /* Default version */\n}\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Flag[] /* Feature flags */\n translations: Translations /* Translations */\n search: string /* Search worker URL */\n tags?: Record /* Tags mapping */\n version?: Versioning /* Versioning */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration and make base URL absolute\n */\nconst script = getElement(\"#__config\")\nconst config: Config = JSON.parse(script.textContent!)\nconfig.base = `${new URL(config.base, getLocation())}`\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration\n *\n * @returns Global configuration\n */\nexport function configuration(): Config {\n return config\n}\n\n/**\n * Check whether a feature flag is enabled\n *\n * @param flag - Feature flag\n *\n * @returns Test result\n */\nexport function feature(flag: Flag): boolean {\n return config.features.includes(flag)\n}\n\n/**\n * Retrieve the translation for the given key\n *\n * @param key - Key to be translated\n * @param value - Positional value, if any\n *\n * @returns Translation\n */\nexport function translation(\n key: Translation, value?: string | number\n): string {\n return typeof value !== \"undefined\"\n ? config.translations[key].replace(\"#\", value.toString())\n : config.translations[key]\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElement, getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Component type\n */\nexport type ComponentType =\n | \"announce\" /* Announcement bar */\n | \"container\" /* Container */\n | \"consent\" /* Consent */\n | \"content\" /* Content */\n | \"dialog\" /* Dialog */\n | \"header\" /* Header */\n | \"header-title\" /* Header title */\n | \"header-topic\" /* Header topic */\n | \"main\" /* Main area */\n | \"outdated\" /* Version warning */\n | \"palette\" /* Color palette */\n | \"search\" /* Search */\n | \"search-query\" /* Search input */\n | \"search-result\" /* Search results */\n | \"search-share\" /* Search sharing */\n | \"search-suggest\" /* Search suggestions */\n | \"sidebar\" /* Sidebar */\n | \"skip\" /* Skip link */\n | \"source\" /* Repository information */\n | \"tabs\" /* Navigation tabs */\n | \"toc\" /* Table of contents */\n | \"top\" /* Back-to-top button */\n\n/**\n * Component\n *\n * @template T - Component type\n * @template U - Reference type\n */\nexport type Component<\n T extends {} = {},\n U extends HTMLElement = HTMLElement\n> =\n T & {\n ref: U /* Component reference */\n }\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Component type map\n */\ninterface ComponentTypeMap {\n \"announce\": HTMLElement /* Announcement bar */\n \"container\": HTMLElement /* Container */\n \"consent\": HTMLElement /* Consent */\n \"content\": HTMLElement /* Content */\n \"dialog\": HTMLElement /* Dialog */\n \"header\": HTMLElement /* Header */\n \"header-title\": HTMLElement /* Header title */\n \"header-topic\": HTMLElement /* Header topic */\n \"main\": HTMLElement /* Main area */\n \"outdated\": HTMLElement /* Version warning */\n \"palette\": HTMLElement /* Color palette */\n \"search\": HTMLElement /* Search */\n \"search-query\": HTMLInputElement /* Search input */\n \"search-result\": HTMLElement /* Search results */\n \"search-share\": HTMLAnchorElement /* Search sharing */\n \"search-suggest\": HTMLElement /* Search suggestions */\n \"sidebar\": HTMLElement /* Sidebar */\n \"skip\": HTMLAnchorElement /* Skip link */\n \"source\": HTMLAnchorElement /* Repository information */\n \"tabs\": HTMLElement /* Navigation tabs */\n \"toc\": HTMLElement /* Table of contents */\n \"top\": HTMLAnchorElement /* Back-to-top button */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the element for a given component or throw a reference error\n *\n * @template T - Component type\n *\n * @param type - Component type\n * @param node - Node of reference\n *\n * @returns Element\n */\nexport function getComponentElement(\n type: T, node: ParentNode = document\n): ComponentTypeMap[T] {\n return getElement(`[data-md-component=${type}]`, node)\n}\n\n/**\n * Retrieve all elements for a given component\n *\n * @template T - Component type\n *\n * @param type - Component type\n * @param node - Node of reference\n *\n * @returns Elements\n */\nexport function getComponentElements(\n type: T, node: ParentNode = document\n): ComponentTypeMap[T][] {\n return getElements(`[data-md-component=${type}]`, node)\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n Subject,\n defer,\n finalize,\n fromEvent,\n map,\n startWith,\n tap\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport { getElement } from \"~/browser\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Announcement bar\n */\nexport interface Announce {\n hash: number /* Content hash */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch announcement bar\n *\n * @param el - Announcement bar element\n *\n * @returns Announcement bar observable\n */\nexport function watchAnnounce(\n el: HTMLElement\n): Observable {\n const button = getElement(\".md-typeset > :first-child\", el)\n return fromEvent(button, \"click\", { once: true })\n .pipe(\n map(() => getElement(\".md-typeset\", el)),\n map(content => ({ hash: __md_hash(content.innerHTML) }))\n )\n}\n\n/**\n * Mount announcement bar\n *\n * @param el - Announcement bar element\n *\n * @returns Announcement bar component observable\n */\nexport function mountAnnounce(\n el: HTMLElement\n): Observable> {\n if (!feature(\"announce.dismiss\") || !el.childElementCount)\n return EMPTY\n\n /* Mount component on subscription */\n return defer(() => {\n const push$ = new Subject()\n push$\n .pipe(\n startWith({ hash: __md_get(\"__announce\") })\n )\n .subscribe(({ hash }) => {\n if (hash && hash === (__md_get(\"__announce\") ?? hash)) {\n el.hidden = true\n\n /* Persist preference in local storage */\n __md_set(\"__announce\", hash)\n }\n })\n\n /* Create and return component */\n return watchAnnounce(el)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n finalize,\n map,\n tap\n} from \"rxjs\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Consent\n */\nexport interface Consent {\n hidden: boolean /* Consent is hidden */\n}\n\n/**\n * Consent defaults\n */\nexport interface ConsentDefaults {\n analytics?: boolean /* Consent for Analytics */\n github?: boolean /* Consent for GitHub */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n target$: Observable /* Target observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Target observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch consent\n *\n * @param el - Consent element\n * @param options - Options\n *\n * @returns Consent observable\n */\nexport function watchConsent(\n el: HTMLElement, { target$ }: WatchOptions\n): Observable {\n return target$\n .pipe(\n map(target => ({ hidden: target !== el }))\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Mount consent\n *\n * @param el - Consent element\n * @param options - Options\n *\n * @returns Consent component observable\n */\nexport function mountConsent(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$.subscribe(({ hidden }) => {\n el.hidden = hidden\n })\n\n /* Create and return component */\n return watchConsent(el, options)\n .pipe(\n tap(state => internal$.next(state)),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport {\n EMPTY,\n Observable,\n Subject,\n defer,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n finalize,\n map,\n mergeWith,\n switchMap,\n take,\n tap\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport {\n getElementContentSize,\n watchElementSize,\n watchElementVisibility\n} from \"~/browser\"\nimport { renderClipboardButton } from \"~/templates\"\n\nimport { Component } from \"../../../_\"\nimport {\n Annotation,\n mountAnnotationList\n} from \"../../annotation\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Code block\n */\nexport interface CodeBlock {\n scrollable: boolean /* Code block overflows */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Media print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Global sequence number for code blocks\n */\nlet sequence = 0\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Find candidate list element directly following a code block\n *\n * @param el - Code block element\n *\n * @returns List element or nothing\n */\nfunction findCandidateList(el: HTMLElement): HTMLElement | undefined {\n if (el.nextElementSibling) {\n const sibling = el.nextElementSibling as HTMLElement\n if (sibling.tagName === \"OL\")\n return sibling\n\n /* Skip empty paragraphs - see https://bit.ly/3r4ZJ2O */\n else if (sibling.tagName === \"P\" && !sibling.children.length)\n return findCandidateList(sibling)\n }\n\n /* Everything else */\n return undefined\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch code block\n *\n * This function monitors size changes of the viewport, as well as switches of\n * content tabs with embedded code blocks, as both may trigger overflow.\n *\n * @param el - Code block element\n *\n * @returns Code block observable\n */\nexport function watchCodeBlock(\n el: HTMLElement\n): Observable {\n return watchElementSize(el)\n .pipe(\n map(({ width }) => {\n const content = getElementContentSize(el)\n return {\n scrollable: content.width > width\n }\n }),\n distinctUntilKeyChanged(\"scrollable\")\n )\n}\n\n/**\n * Mount code block\n *\n * This function ensures that an overflowing code block is focusable through\n * keyboard, so it can be scrolled without a mouse to improve on accessibility.\n * Furthermore, if code annotations are enabled, they are mounted if and only\n * if the code block is currently visible, e.g., not in a hidden content tab.\n *\n * Note that code blocks may be mounted eagerly or lazily. If they're mounted\n * lazily (on first visibility), code annotation anchor links will not work,\n * as they are evaluated on initial page load, and code annotations in general\n * might feel a little bumpier.\n *\n * @param el - Code block element\n * @param options - Options\n *\n * @returns Code block and annotation component observable\n */\nexport function mountCodeBlock(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const { matches: hover } = matchMedia(\"(hover)\")\n\n /* Defer mounting of code block - see https://bit.ly/3vHVoVD */\n const factory$ = defer(() => {\n const push$ = new Subject()\n push$.subscribe(({ scrollable }) => {\n if (scrollable && hover)\n el.setAttribute(\"tabindex\", \"0\")\n else\n el.removeAttribute(\"tabindex\")\n })\n\n /* Render button for Clipboard.js integration */\n if (ClipboardJS.isSupported()) {\n const parent = el.closest(\"pre\")!\n parent.id = `__code_${++sequence}`\n parent.insertBefore(\n renderClipboardButton(parent.id),\n el\n )\n }\n\n /* Handle code annotations */\n const container = el.closest(\".highlight\")\n if (container instanceof HTMLElement) {\n const list = findCandidateList(container)\n\n /* Mount code annotations, if enabled */\n if (typeof list !== \"undefined\" && (\n container.classList.contains(\"annotate\") ||\n feature(\"content.code.annotate\")\n )) {\n const annotations$ = mountAnnotationList(list, el, options)\n\n /* Create and return component */\n return watchCodeBlock(el)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state })),\n mergeWith(\n watchElementSize(container)\n .pipe(\n map(({ width, height }) => width && height),\n distinctUntilChanged(),\n switchMap(active => active ? annotations$ : EMPTY)\n )\n )\n )\n }\n }\n\n /* Create and return component */\n return watchCodeBlock(el)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n\n /* Mount code block lazily */\n if (feature(\"content.lazy\"))\n return watchElementVisibility(el)\n .pipe(\n filter(visible => visible),\n take(1),\n switchMap(() => factory$)\n )\n\n /* Mount code block */\n return factory$\n}\n", "/*\n * Copyright (c) 2016-2021 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a tooltip\n *\n * @param id - Tooltip identifier\n *\n * @returns Element\n */\nexport function renderTooltip(id?: string): HTMLElement {\n return (\n
\n
\n
\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"~/utilities\"\n\nimport { renderTooltip } from \"../tooltip\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render an annotation\n *\n * @param id - Annotation identifier\n * @param prefix - Tooltip identifier prefix\n *\n * @returns Element\n */\nexport function renderAnnotation(\n id: string | number, prefix?: string\n): HTMLElement {\n prefix = prefix ? `${prefix}_annotation_${id}` : undefined\n\n /* Render tooltip with anchor, if given */\n if (prefix) {\n const anchor = prefix ? `#${prefix}` : undefined\n return (\n \n )\n } else {\n return (\n \n )\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @returns Element\n */\nexport function renderClipboardButton(id: string): HTMLElement {\n return (\n code`}\n >\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ComponentChild } from \"preact\"\n\nimport { configuration, feature, translation } from \"~/_\"\nimport {\n SearchDocument,\n SearchMetadata,\n SearchResultItem\n} from \"~/integrations/search\"\nimport { h, truncate } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Render flag\n */\nconst enum Flag {\n TEASER = 1, /* Render teaser */\n PARENT = 2 /* Render as parent */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper function\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search document\n *\n * @param document - Search document\n * @param flag - Render flags\n *\n * @returns Element\n */\nfunction renderSearchDocument(\n document: SearchDocument & SearchMetadata, flag: Flag\n): HTMLElement {\n const parent = flag & Flag.PARENT\n const teaser = flag & Flag.TEASER\n\n /* Render missing query terms */\n const missing = Object.keys(document.terms)\n .filter(key => !document.terms[key])\n .reduce((list, key) => [\n ...list, {key}, \" \"\n ], [])\n .slice(0, -1)\n\n /* Assemble query string for highlighting */\n const url = new URL(document.location)\n if (feature(\"search.highlight\"))\n url.searchParams.set(\"h\", Object.entries(document.terms)\n .filter(([, match]) => match)\n .reduce((highlight, [value]) => `${highlight} ${value}`.trim(), \"\")\n )\n\n /* Render article or section, depending on flags */\n const { tags } = configuration()\n return (\n \n \n {parent > 0 &&
}\n

{document.title}

\n {teaser > 0 && document.text.length > 0 &&\n

\n {truncate(document.text, 320)}\n

\n }\n {document.tags && (\n
\n {document.tags.map(tag => {\n const id = tag.replace(/<[^>]+>/g, \"\")\n const type = tags\n ? id in tags\n ? `md-tag-icon md-tag-icon--${tags[id]}`\n : \"md-tag-icon\"\n : \"\"\n return (\n {tag}\n )\n })}\n
\n )}\n {teaser > 0 && missing.length > 0 &&\n

\n {translation(\"search.result.term.missing\")}: {...missing}\n

\n }\n \n
\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n *\n * @returns Element\n */\nexport function renderSearchResultItem(\n result: SearchResultItem\n): HTMLElement {\n const threshold = result[0].score\n const docs = [...result]\n\n /* Find and extract parent article */\n const parent = docs.findIndex(doc => !doc.location.includes(\"#\"))\n const [article] = docs.splice(parent, 1)\n\n /* Determine last index above threshold */\n let index = docs.findIndex(doc => doc.score < threshold)\n if (index === -1)\n index = docs.length\n\n /* Partition sections */\n const best = docs.slice(0, index)\n const more = docs.slice(index)\n\n /* Render children */\n const children = [\n renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)),\n ...best.map(section => renderSearchDocument(section, Flag.TEASER)),\n ...more.length ? [\n
\n \n {more.length > 0 && more.length === 1\n ? translation(\"search.result.more.one\")\n : translation(\"search.result.more.other\", more.length)\n }\n \n {...more.map(section => renderSearchDocument(section, Flag.TEASER))}\n
\n ] : []\n ]\n\n /* Render search result */\n return (\n
  • \n {children}\n
  • \n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SourceFacts } from \"~/components\"\nimport { h, round } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render repository facts\n *\n * @param facts - Repository facts\n *\n * @returns Element\n */\nexport function renderSourceFacts(facts: SourceFacts): HTMLElement {\n return (\n
      \n {Object.entries(facts).map(([key, value]) => (\n
    • \n {typeof value === \"number\" ? round(value) : value}\n
    • \n ))}\n
    \n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Tabbed control type\n */\ntype TabbedControlType =\n | \"prev\"\n | \"next\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render control for content tabs\n *\n * @param type - Control type\n *\n * @returns Element\n */\nexport function renderTabbedControl(\n type: TabbedControlType\n): HTMLElement {\n const classes = `tabbed-control tabbed-control--${type}`\n return (\n \n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a table inside a wrapper to improve scrolling on mobile\n *\n * @param table - Table element\n *\n * @returns Element\n */\nexport function renderTable(table: HTMLElement): HTMLElement {\n return (\n
    \n
    \n {table}\n
    \n
    \n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { configuration, translation } from \"~/_\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Version\n */\nexport interface Version {\n version: string /* Version identifier */\n title: string /* Version title */\n aliases: string[] /* Version aliases */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a version\n *\n * @param version - Version\n *\n * @returns Element\n */\nfunction renderVersion(version: Version): HTMLElement {\n const config = configuration()\n\n /* Ensure trailing slash - see https://bit.ly/3rL5u3f */\n const url = new URL(`../${version.version}/`, config.base)\n return (\n
  • \n \n {version.title}\n \n
  • \n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a version selector\n *\n * @param versions - Versions\n * @param active - Active version\n *\n * @returns Element\n */\nexport function renderVersionSelector(\n versions: Version[], active: Version\n): HTMLElement {\n return (\n
    \n \n {active.title}\n \n
      \n {versions.map(renderVersion)}\n
    \n
    \n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n auditTime,\n combineLatest,\n debounceTime,\n defer,\n delay,\n filter,\n finalize,\n fromEvent,\n map,\n merge,\n switchMap,\n take,\n takeLast,\n takeUntil,\n tap,\n throttleTime,\n withLatestFrom\n} from \"rxjs\"\n\nimport {\n ElementOffset,\n getActiveElement,\n getElementSize,\n watchElementContentOffset,\n watchElementFocus,\n watchElementOffset,\n watchElementVisibility\n} from \"~/browser\"\n\nimport { Component } from \"../../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Annotation\n */\nexport interface Annotation {\n active: boolean /* Annotation is active */\n offset: ElementOffset /* Annotation offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch annotation\n *\n * @param el - Annotation element\n * @param container - Containing element\n *\n * @returns Annotation observable\n */\nexport function watchAnnotation(\n el: HTMLElement, container: HTMLElement\n): Observable {\n const offset$ = defer(() => combineLatest([\n watchElementOffset(el),\n watchElementContentOffset(container)\n ]))\n .pipe(\n map(([{ x, y }, scroll]): ElementOffset => {\n const { width, height } = getElementSize(el)\n return ({\n x: x - scroll.x + width / 2,\n y: y - scroll.y + height / 2\n })\n })\n )\n\n /* Actively watch annotation on focus */\n return watchElementFocus(el)\n .pipe(\n switchMap(active => offset$\n .pipe(\n map(offset => ({ active, offset })),\n take(+!active || Infinity)\n )\n )\n )\n}\n\n/**\n * Mount annotation\n *\n * @param el - Annotation element\n * @param container - Containing element\n * @param options - Options\n *\n * @returns Annotation component observable\n */\nexport function mountAnnotation(\n el: HTMLElement, container: HTMLElement, { target$ }: MountOptions\n): Observable> {\n const [tooltip, index] = Array.from(el.children)\n\n /* Mount component on subscription */\n return defer(() => {\n const push$ = new Subject()\n const done$ = push$.pipe(takeLast(1))\n push$.subscribe({\n\n /* Handle emission */\n next({ offset }) {\n el.style.setProperty(\"--md-tooltip-x\", `${offset.x}px`)\n el.style.setProperty(\"--md-tooltip-y\", `${offset.y}px`)\n },\n\n /* Handle complete */\n complete() {\n el.style.removeProperty(\"--md-tooltip-x\")\n el.style.removeProperty(\"--md-tooltip-y\")\n }\n })\n\n /* Start animation only when annotation is visible */\n watchElementVisibility(el)\n .pipe(\n takeUntil(done$)\n )\n .subscribe(visible => {\n el.toggleAttribute(\"data-md-visible\", visible)\n })\n\n /* Toggle tooltip presence to mitigate empty lines when copying */\n merge(\n push$.pipe(filter(({ active }) => active)),\n push$.pipe(debounceTime(250), filter(({ active }) => !active))\n )\n .subscribe({\n\n /* Handle emission */\n next({ active }) {\n if (active)\n el.prepend(tooltip)\n else\n tooltip.remove()\n },\n\n /* Handle complete */\n complete() {\n el.prepend(tooltip)\n }\n })\n\n /* Toggle tooltip visibility */\n push$\n .pipe(\n auditTime(16, animationFrameScheduler)\n )\n .subscribe(({ active }) => {\n tooltip.classList.toggle(\"md-tooltip--active\", active)\n })\n\n /* Track relative origin of tooltip */\n push$\n .pipe(\n throttleTime(125, animationFrameScheduler),\n filter(() => !!el.offsetParent),\n map(() => el.offsetParent!.getBoundingClientRect()),\n map(({ x }) => x)\n )\n .subscribe({\n\n /* Handle emission */\n next(origin) {\n if (origin)\n el.style.setProperty(\"--md-tooltip-0\", `${-origin}px`)\n else\n el.style.removeProperty(\"--md-tooltip-0\")\n },\n\n /* Handle complete */\n complete() {\n el.style.removeProperty(\"--md-tooltip-0\")\n }\n })\n\n /* Allow to copy link without scrolling to anchor */\n fromEvent(index, \"click\")\n .pipe(\n takeUntil(done$),\n filter(ev => !(ev.metaKey || ev.ctrlKey))\n )\n .subscribe(ev => ev.preventDefault())\n\n /* Allow to open link in new tab or blur on close */\n fromEvent(index, \"mousedown\")\n .pipe(\n takeUntil(done$),\n withLatestFrom(push$)\n )\n .subscribe(([ev, { active }]) => {\n\n /* Open in new tab */\n if (ev.button !== 0 || ev.metaKey || ev.ctrlKey) {\n ev.preventDefault()\n\n /* Close annotation */\n } else if (active) {\n ev.preventDefault()\n\n /* Focus parent annotation, if any */\n const parent = el.parentElement!.closest(\".md-annotation\")\n if (parent instanceof HTMLElement)\n parent.focus()\n else\n getActiveElement()?.blur()\n }\n })\n\n /* Open and focus annotation on location target */\n target$\n .pipe(\n takeUntil(done$),\n filter(target => target === tooltip),\n delay(125)\n )\n .subscribe(() => el.focus())\n\n /* Create and return component */\n return watchAnnotation(el, container)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n Subject,\n defer,\n finalize,\n merge,\n share,\n takeLast,\n takeUntil\n} from \"rxjs\"\n\nimport {\n getElement,\n getElements,\n getOptionalElement\n} from \"~/browser\"\nimport { renderAnnotation } from \"~/templates\"\n\nimport { Component } from \"../../../_\"\nimport {\n Annotation,\n mountAnnotation\n} from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Media print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Find all annotation markers in the given code block\n *\n * @param container - Containing element\n *\n * @returns Annotation markers\n */\nfunction findAnnotationMarkers(container: HTMLElement): Text[] {\n const markers: Text[] = []\n for (const el of getElements(\".c, .c1, .cm\", container)) {\n const nodes: Text[] = []\n\n /* Find all text nodes in current element */\n const it = document.createNodeIterator(el, NodeFilter.SHOW_TEXT)\n for (let node = it.nextNode(); node; node = it.nextNode())\n nodes.push(node as Text)\n\n /* Find all markers in each text node */\n for (let text of nodes) {\n let match: RegExpExecArray | null\n\n /* Split text at marker and add to list */\n while ((match = /(\\(\\d+\\))(!)?/.exec(text.textContent!))) {\n const [, id, force] = match\n if (typeof force === \"undefined\") {\n const marker = text.splitText(match.index)\n text = marker.splitText(id.length)\n markers.push(marker)\n\n /* Replace entire text with marker */\n } else {\n text.textContent = id\n markers.push(text)\n break\n }\n }\n }\n }\n return markers\n}\n\n/**\n * Swap the child nodes of two elements\n *\n * @param source - Source element\n * @param target - Target element\n */\nfunction swap(source: HTMLElement, target: HTMLElement): void {\n target.append(...Array.from(source.childNodes))\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount annotation list\n *\n * This function analyzes the containing code block and checks for markers\n * referring to elements in the given annotation list. If no markers are found,\n * the list is left untouched. Otherwise, list elements are rendered as\n * annotations inside the code block.\n *\n * @param el - Annotation list element\n * @param container - Containing element\n * @param options - Options\n *\n * @returns Annotation component observable\n */\nexport function mountAnnotationList(\n el: HTMLElement, container: HTMLElement, { target$, print$ }: MountOptions\n): Observable> {\n\n /* Compute prefix for tooltip anchors */\n const parent = container.closest(\"[id]\")\n const prefix = parent?.id\n\n /* Find and replace all markers with empty annotations */\n const annotations = new Map()\n for (const marker of findAnnotationMarkers(container)) {\n const [, id] = marker.textContent!.match(/\\((\\d+)\\)/)!\n if (getOptionalElement(`li:nth-child(${id})`, el)) {\n annotations.set(id, renderAnnotation(id, prefix))\n marker.replaceWith(annotations.get(id)!)\n }\n }\n\n /* Keep list if there are no annotations to render */\n if (annotations.size === 0)\n return EMPTY\n\n /* Mount component on subscription */\n return defer(() => {\n const done$ = new Subject()\n\n /* Retrieve container pairs for swapping */\n const pairs: [HTMLElement, HTMLElement][] = []\n for (const [id, annotation] of annotations)\n pairs.push([\n getElement(\".md-typeset\", annotation),\n getElement(`li:nth-child(${id})`, el)\n ])\n\n /* Handle print mode - see https://bit.ly/3rgPdpt */\n print$\n .pipe(\n takeUntil(done$.pipe(takeLast(1)))\n )\n .subscribe(active => {\n el.hidden = !active\n\n /* Show annotations in code block or list (print) */\n for (const [inner, child] of pairs)\n if (!active)\n swap(child, inner)\n else\n swap(inner, child)\n })\n\n /* Create and return component */\n return merge(...[...annotations]\n .map(([, annotation]) => (\n mountAnnotation(annotation, container, { target$ })\n ))\n )\n .pipe(\n finalize(() => done$.complete()),\n share()\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n map,\n of,\n shareReplay,\n tap\n} from \"rxjs\"\n\nimport { watchScript } from \"~/browser\"\nimport { h } from \"~/utilities\"\n\nimport { Component } from \"../../../_\"\n\nimport themeCSS from \"./index.css\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mermaid diagram\n */\nexport interface Mermaid {}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Mermaid instance observable\n */\nlet mermaid$: Observable\n\n/**\n * Global sequence number for diagrams\n */\nlet sequence = 0\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch Mermaid script\n *\n * @returns Mermaid scripts observable\n */\nfunction fetchScripts(): Observable {\n return typeof mermaid === \"undefined\" || mermaid instanceof Element\n ? watchScript(\"https://unpkg.com/mermaid@9.1.7/dist/mermaid.min.js\")\n : of(undefined)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount Mermaid diagram\n *\n * @param el - Code block element\n *\n * @returns Mermaid diagram component observable\n */\nexport function mountMermaid(\n el: HTMLElement\n): Observable> {\n el.classList.remove(\"mermaid\") // Hack: mitigate https://bit.ly/3CiN6Du\n mermaid$ ||= fetchScripts()\n .pipe(\n tap(() => mermaid.initialize({\n startOnLoad: false,\n themeCSS,\n sequence: {\n actorFontSize: \"16px\", // Hack: mitigate https://bit.ly/3y0NEi3\n messageFontSize: \"16px\",\n noteFontSize: \"16px\"\n }\n })),\n map(() => undefined),\n shareReplay(1)\n )\n\n /* Render diagram */\n mermaid$.subscribe(() => {\n el.classList.add(\"mermaid\") // Hack: mitigate https://bit.ly/3CiN6Du\n const id = `__mermaid_${sequence++}`\n const host = h(\"div\", { class: \"mermaid\" })\n mermaid.mermaidAPI.render(id, el.textContent, (svg: string) => {\n\n /* Create a shadow root and inject diagram */\n const shadow = host.attachShadow({ mode: \"closed\" })\n shadow.innerHTML = svg\n\n /* Replace code block with diagram */\n el.replaceWith(host)\n })\n })\n\n /* Create and return component */\n return mermaid$\n .pipe(\n map(() => ({ ref: el }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n defer,\n filter,\n finalize,\n map,\n merge,\n tap\n} from \"rxjs\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Details\n */\nexport interface Details {\n action: \"open\" | \"close\" /* Details state */\n reveal?: boolean /* Details is revealed */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Media print observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Media print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch details\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details observable\n */\nexport function watchDetails(\n el: HTMLDetailsElement, { target$, print$ }: WatchOptions\n): Observable
    {\n let open = true\n return merge(\n\n /* Open and focus details on location target */\n target$\n .pipe(\n map(target => target.closest(\"details:not([open])\")!),\n filter(details => el === details),\n map(() => ({\n action: \"open\", reveal: true\n }) as Details)\n ),\n\n /* Open details on print and close afterwards */\n print$\n .pipe(\n filter(active => active || !open),\n tap(() => open = el.open),\n map(active => ({\n action: active ? \"open\" : \"close\"\n }) as Details)\n )\n )\n}\n\n/**\n * Mount details\n *\n * This function ensures that `details` tags are opened on anchor jumps and\n * prior to printing, so the whole content of the page is visible.\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details component observable\n */\nexport function mountDetails(\n el: HTMLDetailsElement, options: MountOptions\n): Observable> {\n return defer(() => {\n const push$ = new Subject
    ()\n push$.subscribe(({ action, reveal }) => {\n el.toggleAttribute(\"open\", action === \"open\")\n if (reveal)\n el.scrollIntoView()\n })\n\n /* Create and return component */\n return watchDetails(el, options)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, of } from \"rxjs\"\n\nimport { renderTable } from \"~/templates\"\nimport { h } from \"~/utilities\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Data table\n */\nexport interface DataTable {}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Sentinel for replacement\n */\nconst sentinel = h(\"table\")\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount data table\n *\n * This function wraps a data table in another scrollable container, so it can\n * be smoothly scrolled on smaller screen sizes and won't break the layout.\n *\n * @param el - Data table element\n *\n * @returns Data table component observable\n */\nexport function mountDataTable(\n el: HTMLElement\n): Observable> {\n el.replaceWith(sentinel)\n sentinel.replaceWith(renderTable(el))\n\n /* Create and return component */\n return of({ ref: el })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n asyncScheduler,\n auditTime,\n combineLatest,\n defer,\n finalize,\n fromEvent,\n map,\n merge,\n skip,\n startWith,\n subscribeOn,\n takeLast,\n takeUntil,\n tap,\n withLatestFrom\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport {\n Viewport,\n getElement,\n getElementContentOffset,\n getElementContentSize,\n getElementOffset,\n getElementSize,\n getElements,\n watchElementContentOffset,\n watchElementSize\n} from \"~/browser\"\nimport { renderTabbedControl } from \"~/templates\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Content tabs\n */\nexport interface ContentTabs {\n active: HTMLLabelElement /* Active tab label */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch content tabs\n *\n * @param el - Content tabs element\n *\n * @returns Content tabs observable\n */\nexport function watchContentTabs(\n el: HTMLElement\n): Observable {\n const inputs = getElements(\":scope > input\", el)\n const initial = inputs.find(input => input.checked) || inputs[0]\n return merge(...inputs.map(input => fromEvent(input, \"change\")\n .pipe(\n map(() => getElement(`label[for=\"${input.id}\"]`))\n )\n ))\n .pipe(\n startWith(getElement(`label[for=\"${initial.id}\"]`)),\n map(active => ({ active }))\n )\n}\n\n/**\n * Mount content tabs\n *\n * This function scrolls the active tab into view. While this functionality is\n * provided by browsers as part of `scrollInfoView`, browsers will always also\n * scroll the vertical axis, which we do not want. Thus, we decided to provide\n * this functionality ourselves.\n *\n * @param el - Content tabs element\n * @param options - Options\n *\n * @returns Content tabs component observable\n */\nexport function mountContentTabs(\n el: HTMLElement, { viewport$ }: MountOptions\n): Observable> {\n\n /* Render content tab previous button for pagination */\n const prev = renderTabbedControl(\"prev\")\n el.append(prev)\n\n /* Render content tab next button for pagination */\n const next = renderTabbedControl(\"next\")\n el.append(next)\n\n /* Mount component on subscription */\n const container = getElement(\".tabbed-labels\", el)\n return defer(() => {\n const push$ = new Subject()\n const done$ = push$.pipe(takeLast(1))\n combineLatest([push$, watchElementSize(el)])\n .pipe(\n auditTime(1, animationFrameScheduler),\n takeUntil(done$)\n )\n .subscribe({\n\n /* Handle emission */\n next([{ active }, size]) {\n const offset = getElementOffset(active)\n const { width } = getElementSize(active)\n\n /* Set tab indicator offset and width */\n el.style.setProperty(\"--md-indicator-x\", `${offset.x}px`)\n el.style.setProperty(\"--md-indicator-width\", `${width}px`)\n\n /* Scroll container to active content tab */\n const content = getElementContentOffset(container)\n if (\n offset.x < content.x ||\n offset.x + width > content.x + size.width\n )\n container.scrollTo({\n left: Math.max(0, offset.x - 16),\n behavior: \"smooth\"\n })\n },\n\n /* Handle complete */\n complete() {\n el.style.removeProperty(\"--md-indicator-x\")\n el.style.removeProperty(\"--md-indicator-width\")\n }\n })\n\n /* Hide content tab buttons on borders */\n combineLatest([\n watchElementContentOffset(container),\n watchElementSize(container)\n ])\n .pipe(\n takeUntil(done$)\n )\n .subscribe(([offset, size]) => {\n const content = getElementContentSize(container)\n prev.hidden = offset.x < 16\n next.hidden = offset.x > content.width - size.width - 16\n })\n\n /* Paginate content tab container on click */\n merge(\n fromEvent(prev, \"click\").pipe(map(() => -1)),\n fromEvent(next, \"click\").pipe(map(() => +1))\n )\n .pipe(\n takeUntil(done$)\n )\n .subscribe(direction => {\n const { width } = getElementSize(container)\n container.scrollBy({\n left: width * direction,\n behavior: \"smooth\"\n })\n })\n\n /* Set up linking of content tabs, if enabled */\n if (feature(\"content.tabs.link\"))\n push$.pipe(\n skip(1),\n withLatestFrom(viewport$)\n )\n .subscribe(([{ active }, { offset }]) => {\n const tab = active.innerText.trim()\n if (active.hasAttribute(\"data-md-switching\")) {\n active.removeAttribute(\"data-md-switching\")\n\n /* Determine viewport offset of active tab */\n } else {\n const y = el.offsetTop - offset.y\n\n /* Passively activate other tabs */\n for (const set of getElements(\"[data-tabs]\"))\n for (const input of getElements(\n \":scope > input\", set\n )) {\n const label = getElement(`label[for=\"${input.id}\"]`)\n if (\n label !== active &&\n label.innerText.trim() === tab\n ) {\n label.setAttribute(\"data-md-switching\", \"\")\n input.click()\n break\n }\n }\n\n /* Bring active tab into view */\n window.scrollTo({\n top: el.offsetTop - y\n })\n\n /* Persist active tabs in local storage */\n const tabs = __md_get(\"__tabs\") || []\n __md_set(\"__tabs\", [...new Set([tab, ...tabs])])\n }\n })\n\n /* Create and return component */\n return watchContentTabs(el)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n .pipe(\n subscribeOn(asyncScheduler)\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, merge } from \"rxjs\"\n\nimport { Viewport, getElements } from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Annotation } from \"../annotation\"\nimport {\n CodeBlock,\n Mermaid,\n mountCodeBlock,\n mountMermaid\n} from \"../code\"\nimport {\n Details,\n mountDetails\n} from \"../details\"\nimport {\n DataTable,\n mountDataTable\n} from \"../table\"\nimport {\n ContentTabs,\n mountContentTabs\n} from \"../tabs\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Content\n */\nexport type Content =\n | Annotation\n | ContentTabs\n | CodeBlock\n | Mermaid\n | DataTable\n | Details\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n target$: Observable /* Location target observable */\n print$: Observable /* Media print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount content\n *\n * This function mounts all components that are found in the content of the\n * actual article, including code blocks, data tables and details.\n *\n * @param el - Content element\n * @param options - Options\n *\n * @returns Content component observable\n */\nexport function mountContent(\n el: HTMLElement, { viewport$, target$, print$ }: MountOptions\n): Observable> {\n return merge(\n\n /* Code blocks */\n ...getElements(\"pre:not(.mermaid) > code\", el)\n .map(child => mountCodeBlock(child, { target$, print$ })),\n\n /* Mermaid diagrams */\n ...getElements(\"pre.mermaid\", el)\n .map(child => mountMermaid(child)),\n\n /* Data tables */\n ...getElements(\"table:not([class])\", el)\n .map(child => mountDataTable(child)),\n\n /* Details */\n ...getElements(\"details\", el)\n .map(child => mountDetails(child, { target$, print$ })),\n\n /* Content tabs */\n ...getElements(\"[data-tabs]\", el)\n .map(child => mountContentTabs(child, { viewport$ }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n defer,\n delay,\n finalize,\n map,\n merge,\n of,\n switchMap,\n tap\n} from \"rxjs\"\n\nimport { getElement } from \"~/browser\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Dialog\n */\nexport interface Dialog {\n message: string /* Dialog message */\n active: boolean /* Dialog is active */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n alert$: Subject /* Alert subject */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch dialog\n *\n * @param _el - Dialog element\n * @param options - Options\n *\n * @returns Dialog observable\n */\nexport function watchDialog(\n _el: HTMLElement, { alert$ }: WatchOptions\n): Observable {\n return alert$\n .pipe(\n switchMap(message => merge(\n of(true),\n of(false).pipe(delay(2000))\n )\n .pipe(\n map(active => ({ message, active }))\n )\n )\n )\n}\n\n/**\n * Mount dialog\n *\n * This function reveals the dialog in the right corner when a new alert is\n * emitted through the subject that is passed as part of the options.\n *\n * @param el - Dialog element\n * @param options - Options\n *\n * @returns Dialog component observable\n */\nexport function mountDialog(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const inner = getElement(\".md-typeset\", el)\n return defer(() => {\n const push$ = new Subject()\n push$.subscribe(({ message, active }) => {\n el.classList.toggle(\"md-dialog--active\", active)\n inner.textContent = message\n })\n\n /* Create and return component */\n return watchDialog(el, options)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n bufferCount,\n combineLatest,\n combineLatestWith,\n defer,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n of,\n shareReplay,\n startWith,\n switchMap,\n takeLast,\n takeUntil\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport {\n Viewport,\n watchElementSize,\n watchToggle\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Main } from \"../../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface Header {\n height: number /* Header visible height */\n hidden: boolean /* Header is hidden */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute whether the header is hidden\n *\n * If the user scrolls past a certain threshold, the header can be hidden when\n * scrolling down, and shown when scrolling up.\n *\n * @param options - Options\n *\n * @returns Toggle observable\n */\nfunction isHidden({ viewport$ }: WatchOptions): Observable {\n if (!feature(\"header.autohide\"))\n return of(false)\n\n /* Compute direction and turning point */\n const direction$ = viewport$\n .pipe(\n map(({ offset: { y } }) => y),\n bufferCount(2, 1),\n map(([a, b]) => [a < b, b] as const),\n distinctUntilKeyChanged(0)\n )\n\n /* Compute whether header should be hidden */\n const hidden$ = combineLatest([viewport$, direction$])\n .pipe(\n filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100),\n map(([, [direction]]) => direction),\n distinctUntilChanged()\n )\n\n /* Compute threshold for hiding */\n const search$ = watchToggle(\"search\")\n return combineLatest([viewport$, search$])\n .pipe(\n map(([{ offset }, search]) => offset.y > 400 && !search),\n distinctUntilChanged(),\n switchMap(active => active ? hidden$ : of(false)),\n startWith(false)\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header observable\n */\nexport function watchHeader(\n el: HTMLElement, options: WatchOptions\n): Observable
    {\n return defer(() => combineLatest([\n watchElementSize(el),\n isHidden(options)\n ]))\n .pipe(\n map(([{ height }, hidden]) => ({\n height,\n hidden\n })),\n distinctUntilChanged((a, b) => (\n a.height === b.height &&\n a.hidden === b.hidden\n )),\n shareReplay(1)\n )\n}\n\n/**\n * Mount header\n *\n * This function manages the different states of the header, i.e. whether it's\n * hidden or rendered with a shadow. This depends heavily on the main area.\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header component observable\n */\nexport function mountHeader(\n el: HTMLElement, { header$, main$ }: MountOptions\n): Observable> {\n return defer(() => {\n const push$ = new Subject
    ()\n const done$ = push$.pipe(takeLast(1))\n push$\n .pipe(\n distinctUntilKeyChanged(\"active\"),\n combineLatestWith(header$)\n )\n .subscribe(([{ active }, { hidden }]) => {\n el.classList.toggle(\"md-header--shadow\", active && !hidden)\n el.hidden = hidden\n })\n\n /* Link to main area */\n main$.subscribe(push$)\n\n /* Create and return component */\n return header$\n .pipe(\n takeUntil(done$),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n Subject,\n defer,\n distinctUntilKeyChanged,\n finalize,\n map,\n tap\n} from \"rxjs\"\n\nimport {\n Viewport,\n getElementSize,\n getOptionalElement,\n watchViewportAt\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Header } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface HeaderTitle {\n active: boolean /* Header title is active */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header title\n *\n * @param el - Heading element\n * @param options - Options\n *\n * @returns Header title observable\n */\nexport function watchHeaderTitle(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchViewportAt(el, { viewport$, header$ })\n .pipe(\n map(({ offset: { y } }) => {\n const { height } = getElementSize(el)\n return {\n active: y >= height\n }\n }),\n distinctUntilKeyChanged(\"active\")\n )\n}\n\n/**\n * Mount header title\n *\n * This function swaps the header title from the site title to the title of the\n * current page when the user scrolls past the first headline.\n *\n * @param el - Header title element\n * @param options - Options\n *\n * @returns Header title component observable\n */\nexport function mountHeaderTitle(\n el: HTMLElement, options: MountOptions\n): Observable> {\n return defer(() => {\n const push$ = new Subject()\n push$.subscribe(({ active }) => {\n el.classList.toggle(\"md-header__title--active\", active)\n })\n\n /* Obtain headline, if any */\n const heading = getOptionalElement(\"article h1\")\n if (typeof heading === \"undefined\")\n return EMPTY\n\n /* Create and return component */\n return watchHeaderTitle(heading, options)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs\"\n\nimport {\n Viewport,\n watchElementSize\n} from \"~/browser\"\n\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Main area\n */\nexport interface Main {\n offset: number /* Main area top offset */\n height: number /* Main area visible height */\n active: boolean /* Main area is active */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch main area\n *\n * This function returns an observable that computes the visual parameters of\n * the main area which depends on the viewport vertical offset and height, as\n * well as the height of the header element, if the header is fixed.\n *\n * @param el - Main area element\n * @param options - Options\n *\n * @returns Main area observable\n */\nexport function watchMain(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable
    {\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(({ height }) => height),\n distinctUntilChanged()\n )\n\n /* Compute the main area's top and bottom borders */\n const border$ = adjust$\n .pipe(\n switchMap(() => watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n top: el.offsetTop,\n bottom: el.offsetTop + height\n })),\n distinctUntilKeyChanged(\"bottom\")\n )\n )\n )\n\n /* Compute the main area's offset, visible height and if we scrolled past */\n return combineLatest([adjust$, border$, viewport$])\n .pipe(\n map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => {\n height = Math.max(0, height\n - Math.max(0, top - y, header)\n - Math.max(0, height + y - bottom)\n )\n return {\n offset: top - header,\n height,\n active: top - header <= y\n }\n }),\n distinctUntilChanged((a, b) => (\n a.offset === b.offset &&\n a.height === b.height &&\n a.active === b.active\n ))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n asyncScheduler,\n defer,\n finalize,\n fromEvent,\n map,\n mergeMap,\n observeOn,\n of,\n shareReplay,\n startWith,\n tap\n} from \"rxjs\"\n\nimport { getElements } from \"~/browser\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Palette colors\n */\nexport interface PaletteColor {\n scheme?: string /* Color scheme */\n primary?: string /* Primary color */\n accent?: string /* Accent color */\n}\n\n/**\n * Palette\n */\nexport interface Palette {\n index: number /* Palette index */\n color: PaletteColor /* Palette colors */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch color palette\n *\n * @param inputs - Color palette element\n *\n * @returns Color palette observable\n */\nexport function watchPalette(\n inputs: HTMLInputElement[]\n): Observable {\n const current = __md_get(\"__palette\") || {\n index: inputs.findIndex(input => matchMedia(\n input.getAttribute(\"data-md-color-media\")!\n ).matches)\n }\n\n /* Emit changes in color palette */\n return of(...inputs)\n .pipe(\n mergeMap(input => fromEvent(input, \"change\")\n .pipe(\n map(() => input)\n )\n ),\n startWith(inputs[Math.max(0, current.index)]),\n map(input => ({\n index: inputs.indexOf(input),\n color: {\n scheme: input.getAttribute(\"data-md-color-scheme\"),\n primary: input.getAttribute(\"data-md-color-primary\"),\n accent: input.getAttribute(\"data-md-color-accent\")\n }\n } as Palette)),\n shareReplay(1)\n )\n}\n\n/**\n * Mount color palette\n *\n * @param el - Color palette element\n *\n * @returns Color palette component observable\n */\nexport function mountPalette(\n el: HTMLElement\n): Observable> {\n return defer(() => {\n const push$ = new Subject()\n push$.subscribe(palette => {\n document.body.setAttribute(\"data-md-color-switching\", \"\")\n\n /* Set color palette */\n for (const [key, value] of Object.entries(palette.color))\n document.body.setAttribute(`data-md-color-${key}`, value)\n\n /* Toggle visibility */\n for (let index = 0; index < inputs.length; index++) {\n const label = inputs[index].nextElementSibling\n if (label instanceof HTMLElement)\n label.hidden = palette.index !== index\n }\n\n /* Persist preference in local storage */\n __md_set(\"__palette\", palette)\n })\n\n /* Revert transition durations after color switch */\n push$.pipe(observeOn(asyncScheduler))\n .subscribe(() => {\n document.body.removeAttribute(\"data-md-color-switching\")\n })\n\n /* Create and return component */\n const inputs = getElements(\"input\", el)\n return watchPalette(inputs)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport {\n Observable,\n Subject,\n map,\n tap\n} from \"rxjs\"\n\nimport { translation } from \"~/_\"\nimport { getElement } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Extract text to copy\n *\n * @param el - HTML element\n *\n * @returns Extracted text\n */\nfunction extract(el: HTMLElement): string {\n el.setAttribute(\"data-md-copying\", \"\")\n const text = el.innerText\n el.removeAttribute(\"data-md-copying\")\n return text\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up Clipboard.js integration\n *\n * @param options - Options\n */\nexport function setupClipboardJS(\n { alert$ }: SetupOptions\n): void {\n if (ClipboardJS.isSupported()) {\n new Observable(subscriber => {\n new ClipboardJS(\"[data-clipboard-target], [data-clipboard-text]\", {\n text: el => (\n el.getAttribute(\"data-clipboard-text\")! ||\n extract(getElement(\n el.getAttribute(\"data-clipboard-target\")!\n ))\n )\n })\n .on(\"success\", ev => subscriber.next(ev))\n })\n .pipe(\n tap(ev => {\n const trigger = ev.trigger as HTMLElement\n trigger.focus()\n }),\n map(() => translation(\"clipboard.copied\"))\n )\n .subscribe(alert$)\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n catchError,\n defaultIfEmpty,\n map,\n of,\n tap\n} from \"rxjs\"\n\nimport { configuration } from \"~/_\"\nimport { getElements, requestXML } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Sitemap, i.e. a list of URLs\n */\nexport type Sitemap = string[]\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Preprocess a list of URLs\n *\n * This function replaces the `site_url` in the sitemap with the actual base\n * URL, to allow instant loading to work in occasions like Netlify previews.\n *\n * @param urls - URLs\n *\n * @returns URL path parts\n */\nfunction preprocess(urls: Sitemap): Sitemap {\n if (urls.length < 2)\n return [\"\"]\n\n /* Take the first two URLs and remove everything after the last slash */\n const [root, next] = [...urls]\n .sort((a, b) => a.length - b.length)\n .map(url => url.replace(/[^/]+$/, \"\"))\n\n /* Compute common prefix */\n let index = 0\n if (root === next)\n index = root.length\n else\n while (root.charCodeAt(index) === next.charCodeAt(index))\n index++\n\n /* Remove common prefix and return in original order */\n return urls.map(url => url.replace(root.slice(0, index), \"\"))\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch the sitemap for the given base URL\n *\n * @param base - Base URL\n *\n * @returns Sitemap observable\n */\nexport function fetchSitemap(base?: URL): Observable {\n const cached = __md_get(\"__sitemap\", sessionStorage, base)\n if (cached) {\n return of(cached)\n } else {\n const config = configuration()\n return requestXML(new URL(\"sitemap.xml\", base || config.base))\n .pipe(\n map(sitemap => preprocess(getElements(\"loc\", sitemap)\n .map(node => node.textContent!)\n )),\n catchError(() => EMPTY), // @todo refactor instant loading\n defaultIfEmpty([]),\n tap(sitemap => __md_set(\"__sitemap\", sitemap, sessionStorage, base))\n )\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n bufferCount,\n catchError,\n concatMap,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n fromEvent,\n map,\n merge,\n of,\n sample,\n share,\n skip,\n skipUntil,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"~/_\"\nimport {\n Viewport,\n ViewportOffset,\n getElements,\n getOptionalElement,\n request,\n setLocation,\n setLocationHash\n} from \"~/browser\"\nimport { getComponentElement } from \"~/components\"\nimport { h } from \"~/utilities\"\n\nimport { fetchSitemap } from \"../sitemap\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\nexport interface HistoryState {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n location$: Subject /* Location subject */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up instant loading\n *\n * When fetching, theoretically, we could use `responseType: \"document\"`, but\n * since all MkDocs links are relative, we need to make sure that the current\n * location matches the document we just loaded. Otherwise any relative links\n * in the document could use the old location.\n *\n * This is the reason why we need to synchronize history events and the process\n * of fetching the document for navigation changes (except `popstate` events):\n *\n * 1. Fetch document via `XMLHTTPRequest`\n * 2. Set new location via `history.pushState`\n * 3. Parse and emit fetched document\n *\n * For `popstate` events, we must not use `history.pushState`, or the forward\n * history will be irreversibly overwritten. In case the request fails, the\n * location change is dispatched regularly.\n *\n * @param options - Options\n */\nexport function setupInstantLoading(\n { document$, location$, viewport$ }: SetupOptions\n): void {\n const config = configuration()\n if (location.protocol === \"file:\")\n return\n\n /* Disable automatic scroll restoration */\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\"\n\n /* Hack: ensure that reloads restore viewport offset */\n fromEvent(window, \"beforeunload\")\n .subscribe(() => {\n history.scrollRestoration = \"auto\"\n })\n }\n\n /* Hack: ensure absolute favicon link to omit 404s when switching */\n const favicon = getOptionalElement(\"link[rel=icon]\")\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href\n\n /* Intercept internal navigation */\n const push$ = fetchSitemap()\n .pipe(\n map(paths => paths.map(path => `${new URL(path, config.base)}`)),\n switchMap(urls => fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !ev.metaKey && !ev.ctrlKey),\n switchMap(ev => {\n if (ev.target instanceof Element) {\n const el = ev.target.closest(\"a\")\n if (el && !el.target) {\n const url = new URL(el.href)\n\n /* Canonicalize URL */\n url.search = \"\"\n url.hash = \"\"\n\n /* Check if URL should be intercepted */\n if (\n url.pathname !== location.pathname &&\n urls.includes(url.toString())\n ) {\n ev.preventDefault()\n return of({\n url: new URL(el.href)\n })\n }\n }\n }\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Intercept history back and forward */\n const pop$ = fromEvent(window, \"popstate\")\n .pipe(\n filter(ev => ev.state !== null),\n map(ev => ({\n url: new URL(location.href),\n offset: ev.state\n })),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((a, b) => a.url.href === b.url.href),\n map(({ url }) => url)\n )\n .subscribe(location$)\n\n /* Fetch document via `XMLHTTPRequest` */\n const response$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n switchMap(url => request(url.href)\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Set new location via `history.pushState` */\n push$\n .pipe(\n sample(response$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", `${url}`)\n })\n\n /* Parse and emit fetched document */\n const dom = new DOMParser()\n response$\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Replace meta tags and components */\n document$\n .pipe(\n skip(1)\n )\n .subscribe(replacement => {\n for (const selector of [\n\n /* Meta tags */\n \"title\",\n \"link[rel=canonical]\",\n \"meta[name=author]\",\n \"meta[name=description]\",\n\n /* Components */\n \"[data-md-component=announce]\",\n \"[data-md-component=container]\",\n \"[data-md-component=header-topic]\",\n \"[data-md-component=outdated]\",\n \"[data-md-component=logo]\",\n \"[data-md-component=skip]\",\n ...feature(\"navigation.tabs.sticky\")\n ? [\"[data-md-component=tabs]\"]\n : []\n ]) {\n const source = getOptionalElement(selector)\n const target = getOptionalElement(selector, replacement)\n if (\n typeof source !== \"undefined\" &&\n typeof target !== \"undefined\"\n ) {\n source.replaceWith(target)\n }\n }\n })\n\n /* Re-evaluate scripts */\n document$\n .pipe(\n skip(1),\n map(() => getComponentElement(\"container\")),\n switchMap(el => getElements(\"script\", el)),\n concatMap(el => {\n const script = h(\"script\")\n if (el.src) {\n for (const name of el.getAttributeNames())\n script.setAttribute(name, el.getAttribute(name)!)\n el.replaceWith(script)\n\n /* Complete when script is loaded */\n return new Observable(observer => {\n script.onload = () => observer.complete()\n })\n\n /* Complete immediately */\n } else {\n script.textContent = el.textContent\n el.replaceWith(script)\n return EMPTY\n }\n })\n )\n .subscribe()\n\n /* Emit history state change */\n merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n .subscribe(({ url, offset }) => {\n if (url.hash && !offset) {\n setLocationHash(url.hash)\n } else {\n window.scrollTo(0, offset?.y || 0)\n }\n })\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n skipUntil(push$),\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(push$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([a, b]) => a.url.pathname === b.url.pathname),\n map(([, state]) => state)\n )\n .subscribe(({ offset }) => {\n window.scrollTo(0, offset?.y || 0)\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport escapeHTML from \"escape-html\"\n\nimport { SearchIndexDocument } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search document\n */\nexport interface SearchDocument extends SearchIndexDocument {\n parent?: SearchIndexDocument /* Parent article */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search document mapping\n */\nexport type SearchDocumentMap = Map\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search document mapping\n *\n * @param docs - Search index documents\n *\n * @returns Search document map\n */\nexport function setupSearchDocumentMap(\n docs: SearchIndexDocument[]\n): SearchDocumentMap {\n const documents = new Map()\n const parents = new Set()\n for (const doc of docs) {\n const [path, hash] = doc.location.split(\"#\")\n\n /* Extract location, title and tags */\n const location = doc.location\n const title = doc.title\n const tags = doc.tags\n\n /* Escape and cleanup text */\n const text = escapeHTML(doc.text)\n .replace(/\\s+(?=[,.:;!?])/g, \"\")\n .replace(/\\s+/g, \" \")\n\n /* Handle section */\n if (hash) {\n const parent = documents.get(path)!\n\n /* Ignore first section, override article */\n if (!parents.has(parent)) {\n parent.title = doc.title\n parent.text = text\n\n /* Remember that we processed the article */\n parents.add(parent)\n\n /* Add subsequent section */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n parent\n })\n }\n\n /* Add article */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n ...tags && { tags }\n })\n }\n }\n return documents\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport escapeHTML from \"escape-html\"\n\nimport { SearchIndexConfig } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search highlight function\n *\n * @param value - Value\n *\n * @returns Highlighted value\n */\nexport type SearchHighlightFn = (value: string) => string\n\n/**\n * Search highlight factory function\n *\n * @param query - Query value\n *\n * @returns Search highlight function\n */\nexport type SearchHighlightFactoryFn = (query: string) => SearchHighlightFn\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search highlighter\n *\n * @param config - Search index configuration\n * @param escape - Whether to escape HTML\n *\n * @returns Search highlight factory function\n */\nexport function setupSearchHighlighter(\n config: SearchIndexConfig, escape: boolean\n): SearchHighlightFactoryFn {\n const separator = new RegExp(config.separator, \"img\")\n const highlight = (_: unknown, data: string, term: string) => {\n return `${data}${term}`\n }\n\n /* Return factory function */\n return (query: string) => {\n query = query\n .replace(/[\\s*+\\-:~^]+/g, \" \")\n .trim()\n\n /* Create search term match expression */\n const match = new RegExp(`(^|${config.separator})(${\n query\n .replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\")\n .replace(separator, \"|\")\n })`, \"img\")\n\n /* Highlight string value */\n return value => (\n escape\n ? escapeHTML(value)\n : value\n )\n .replace(match, highlight)\n .replace(/<\\/mark>(\\s+)]*>/img, \"$1\")\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search transformation function\n *\n * @param value - Query value\n *\n * @returns Transformed query value\n */\nexport type SearchTransformFn = (value: string) => string\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Default transformation function\n *\n * 1. Search for terms in quotation marks and prepend a `+` modifier to denote\n * that the resulting document must contain all terms, converting the query\n * to an `AND` query (as opposed to the default `OR` behavior). While users\n * may expect terms enclosed in quotation marks to map to span queries, i.e.\n * for which order is important, Lunr.js doesn't support them, so the best\n * we can do is to convert the terms to an `AND` query.\n *\n * 2. Replace control characters which are not located at the beginning of the\n * query or preceded by white space, or are not followed by a non-whitespace\n * character or are at the end of the query string. Furthermore, filter\n * unmatched quotation marks.\n *\n * 3. Trim excess whitespace from left and right.\n *\n * @param query - Query value\n *\n * @returns Transformed query value\n */\nexport function defaultTransform(query: string): string {\n return query\n .split(/\"([^\"]+)\"/g) /* => 1 */\n .map((terms, index) => index & 1\n ? terms.replace(/^\\b|^(?![^\\x00-\\x7F]|$)|\\s+/g, \" +\")\n : terms\n )\n .join(\"\")\n .replace(/\"|(?:^|\\s+)[*+\\-:^~]+(?=\\s+|$)/g, \"\") /* => 2 */\n .trim() /* => 3 */\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * Message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * Message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * Message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n ObservableInput,\n Subject,\n from,\n map,\n share\n} from \"rxjs\"\n\nimport { configuration, feature, translation } from \"~/_\"\nimport { WorkerHandler, watchWorker } from \"~/browser\"\n\nimport { SearchIndex } from \"../../_\"\nimport {\n SearchOptions,\n SearchPipeline\n} from \"../../options\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchSetupMessage,\n isSearchResultMessage\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search worker\n */\nexport type SearchWorker = WorkerHandler\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search index\n *\n * @param data - Search index\n *\n * @returns Search index\n */\nfunction setupSearchIndex({ config, docs }: SearchIndex): SearchIndex {\n\n /* Override default language with value from translation */\n if (config.lang.length === 1 && config.lang[0] === \"en\")\n config.lang = [\n translation(\"search.config.lang\")\n ]\n\n /* Override default separator with value from translation */\n if (config.separator === \"[\\\\s\\\\-]+\")\n config.separator = translation(\"search.config.separator\")\n\n /* Set pipeline from translation */\n const pipeline = translation(\"search.config.pipeline\")\n .split(/\\s*,\\s*/)\n .filter(Boolean) as SearchPipeline\n\n /* Determine search options */\n const options: SearchOptions = {\n pipeline,\n suggestions: feature(\"search.suggest\")\n }\n\n /* Return search index after defaulting */\n return { config, docs, options }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search worker\n *\n * This function creates a web worker to set up and query the search index,\n * which is done using Lunr.js. The index must be passed as an observable to\n * enable hacks like _localsearch_ via search index embedding as JSON.\n *\n * @param url - Worker URL\n * @param index - Search index observable input\n *\n * @returns Search worker\n */\nexport function setupSearchWorker(\n url: string, index: ObservableInput\n): SearchWorker {\n const config = configuration()\n const worker = new Worker(url)\n\n /* Create communication channels and resolve relative links */\n const tx$ = new Subject()\n const rx$ = watchWorker(worker, { tx$ })\n .pipe(\n map(message => {\n if (isSearchResultMessage(message)) {\n for (const result of message.data.items)\n for (const document of result)\n document.location = `${new URL(document.location, config.base)}`\n }\n return message\n }),\n share()\n )\n\n /* Set up search index */\n from(index)\n .pipe(\n map(data => ({\n type: SearchMessageType.SETUP,\n data: setupSearchIndex(data)\n } as SearchSetupMessage))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Return search worker */\n return { tx$, rx$ }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Subject,\n catchError,\n combineLatest,\n filter,\n fromEvent,\n map,\n of,\n switchMap,\n withLatestFrom\n} from \"rxjs\"\n\nimport { configuration } from \"~/_\"\nimport {\n getElement,\n getLocation,\n requestJSON,\n setLocation\n} from \"~/browser\"\nimport { getComponentElements } from \"~/components\"\nimport {\n Version,\n renderVersionSelector\n} from \"~/templates\"\n\nimport { fetchSitemap } from \"../sitemap\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up version selector\n *\n * @param options - Options\n */\nexport function setupVersionSelector(\n { document$ }: SetupOptions\n): void {\n const config = configuration()\n const versions$ = requestJSON(\n new URL(\"../versions.json\", config.base)\n )\n .pipe(\n catchError(() => EMPTY) // @todo refactor instant loading\n )\n\n /* Determine current version */\n const current$ = versions$\n .pipe(\n map(versions => {\n const [, current] = config.base.match(/([^/]+)\\/?$/)!\n return versions.find(({ version, aliases }) => (\n version === current || aliases.includes(current)\n )) || versions[0]\n })\n )\n\n /* Intercept inter-version navigation */\n versions$\n .pipe(\n map(versions => new Map(versions.map(version => [\n `${new URL(`../${version.version}/`, config.base)}`,\n version\n ]))),\n switchMap(urls => fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !ev.metaKey && !ev.ctrlKey),\n withLatestFrom(current$),\n switchMap(([ev, current]) => {\n if (ev.target instanceof Element) {\n const el = ev.target.closest(\"a\")\n if (el && !el.target && urls.has(el.href)) {\n const url = el.href\n // This is a temporary hack to detect if a version inside the\n // version selector or on another part of the site was clicked.\n // If we're inside the version selector, we definitely want to\n // find the same page, as we might have different deployments\n // due to aliases. However, if we're outside the version\n // selector, we must abort here, because we might otherwise\n // interfere with instant loading. We need to refactor this\n // at some point together with instant loading.\n //\n // See https://github.com/squidfunk/mkdocs-material/issues/4012\n if (!ev.target.closest(\".md-version\")) {\n const version = urls.get(url)!\n if (version === current)\n return EMPTY\n }\n ev.preventDefault()\n return of(url)\n }\n }\n return EMPTY\n }),\n switchMap(url => {\n const { version } = urls.get(url)!\n return fetchSitemap(new URL(url))\n .pipe(\n map(sitemap => {\n const location = getLocation()\n const path = location.href.replace(config.base, \"\")\n return sitemap.includes(path.split(\"#\")[0])\n ? new URL(`../${version}/${path}`, config.base)\n : new URL(url)\n })\n )\n })\n )\n )\n )\n .subscribe(url => setLocation(url))\n\n /* Render version selector and warning */\n combineLatest([versions$, current$])\n .subscribe(([versions, current]) => {\n const topic = getElement(\".md-header__topic\")\n topic.appendChild(renderVersionSelector(versions, current))\n })\n\n /* Integrate outdated version banner with instant loading */\n document$.pipe(switchMap(() => current$))\n .subscribe(current => {\n\n /* Check if version state was already determined */\n let outdated = __md_get(\"__outdated\", sessionStorage)\n if (outdated === null) {\n const latest = config.version?.default || \"latest\"\n outdated = !current.aliases.includes(latest)\n\n /* Persist version state in session storage */\n __md_set(\"__outdated\", outdated, sessionStorage)\n }\n\n /* Unhide outdated version banner */\n if (outdated)\n for (const warning of getComponentElements(\"outdated\"))\n warning.hidden = false\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n combineLatest,\n delay,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n finalize,\n fromEvent,\n map,\n merge,\n share,\n shareReplay,\n startWith,\n take,\n takeLast,\n takeUntil,\n tap\n} from \"rxjs\"\n\nimport { translation } from \"~/_\"\nimport {\n getLocation,\n setToggle,\n watchElementFocus,\n watchToggle\n} from \"~/browser\"\nimport {\n SearchMessageType,\n SearchQueryMessage,\n SearchWorker,\n defaultTransform,\n isSearchReadyMessage\n} from \"~/integrations\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query\n */\nexport interface SearchQuery {\n value: string /* Query value */\n focus: boolean /* Query focus */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search query\n *\n * Note that the focus event which triggers re-reading the current query value\n * is delayed by `1ms` so the input's empty state is allowed to propagate.\n *\n * @param el - Search query element\n * @param worker - Search worker\n *\n * @returns Search query observable\n */\nexport function watchSearchQuery(\n el: HTMLInputElement, { rx$ }: SearchWorker\n): Observable {\n const fn = __search?.transform || defaultTransform\n\n /* Immediately show search dialog */\n const { searchParams } = getLocation()\n if (searchParams.has(\"q\"))\n setToggle(\"search\", true)\n\n /* Intercept query parameter (deep link) */\n const param$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n take(1),\n map(() => searchParams.get(\"q\") || \"\")\n )\n\n /* Remove query parameter when search is closed */\n watchToggle(\"search\")\n .pipe(\n filter(active => !active),\n take(1)\n )\n .subscribe(() => {\n const url = new URL(location.href)\n url.searchParams.delete(\"q\")\n history.replaceState({}, \"\", `${url}`)\n })\n\n /* Set query from parameter */\n param$.subscribe(value => { // TODO: not ideal - find a better way\n if (value) {\n el.value = value\n el.focus()\n }\n })\n\n /* Intercept focus and input events */\n const focus$ = watchElementFocus(el)\n const value$ = merge(\n fromEvent(el, \"keyup\"),\n fromEvent(el, \"focus\").pipe(delay(1)),\n param$\n )\n .pipe(\n map(() => fn(el.value)),\n startWith(\"\"),\n distinctUntilChanged(),\n )\n\n /* Combine into single observable */\n return combineLatest([value$, focus$])\n .pipe(\n map(([value, focus]) => ({ value, focus })),\n shareReplay(1)\n )\n}\n\n/**\n * Mount search query\n *\n * @param el - Search query element\n * @param worker - Search worker\n *\n * @returns Search query component observable\n */\nexport function mountSearchQuery(\n el: HTMLInputElement, { tx$, rx$ }: SearchWorker\n): Observable> {\n const push$ = new Subject()\n const done$ = push$.pipe(takeLast(1))\n\n /* Handle value changes */\n push$\n .pipe(\n distinctUntilKeyChanged(\"value\"),\n map(({ value }): SearchQueryMessage => ({\n type: SearchMessageType.QUERY,\n data: value\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Handle focus changes */\n push$\n .pipe(\n distinctUntilKeyChanged(\"focus\")\n )\n .subscribe(({ focus }) => {\n if (focus) {\n setToggle(\"search\", focus)\n el.placeholder = \"\"\n } else {\n el.placeholder = translation(\"search.placeholder\")\n }\n })\n\n /* Handle reset */\n fromEvent(el.form!, \"reset\")\n .pipe(\n takeUntil(done$)\n )\n .subscribe(() => el.focus())\n\n /* Create and return component */\n return watchSearchQuery(el, { tx$, rx$ })\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state })),\n share()\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n bufferCount,\n filter,\n finalize,\n map,\n merge,\n of,\n skipUntil,\n switchMap,\n take,\n tap,\n withLatestFrom,\n zipWith\n} from \"rxjs\"\n\nimport { translation } from \"~/_\"\nimport {\n getElement,\n watchElementBoundary\n} from \"~/browser\"\nimport {\n SearchResult,\n SearchWorker,\n isSearchReadyMessage,\n isSearchResultMessage\n} from \"~/integrations\"\nimport { renderSearchResultItem } from \"~/templates\"\nimport { round } from \"~/utilities\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search result list\n *\n * This function performs a lazy rendering of the search results, depending on\n * the vertical offset of the search result container.\n *\n * @param el - Search result list element\n * @param worker - Search worker\n * @param options - Options\n *\n * @returns Search result list component observable\n */\nexport function mountSearchResult(\n el: HTMLElement, { rx$ }: SearchWorker, { query$ }: MountOptions\n): Observable> {\n const push$ = new Subject()\n const boundary$ = watchElementBoundary(el.parentElement!)\n .pipe(\n filter(Boolean)\n )\n\n /* Retrieve nested components */\n const meta = getElement(\":scope > :first-child\", el)\n const list = getElement(\":scope > :last-child\", el)\n\n /* Wait until search is ready */\n const ready$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n take(1)\n )\n\n /* Update search result metadata */\n push$\n .pipe(\n withLatestFrom(query$),\n skipUntil(ready$)\n )\n .subscribe(([{ items }, { value }]) => {\n if (value) {\n switch (items.length) {\n\n /* No results */\n case 0:\n meta.textContent = translation(\"search.result.none\")\n break\n\n /* One result */\n case 1:\n meta.textContent = translation(\"search.result.one\")\n break\n\n /* Multiple result */\n default:\n meta.textContent = translation(\n \"search.result.other\",\n round(items.length)\n )\n }\n } else {\n meta.textContent = translation(\"search.result.placeholder\")\n }\n })\n\n /* Update search result list */\n push$\n .pipe(\n tap(() => list.innerHTML = \"\"),\n switchMap(({ items }) => merge(\n of(...items.slice(0, 10)),\n of(...items.slice(10))\n .pipe(\n bufferCount(4),\n zipWith(boundary$),\n switchMap(([chunk]) => chunk)\n )\n ))\n )\n .subscribe(result => list.appendChild(\n renderSearchResultItem(result)\n ))\n\n /* Filter search result message */\n const result$ = rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => data)\n )\n\n /* Create and return component */\n return result$\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n finalize,\n fromEvent,\n map,\n tap\n} from \"rxjs\"\n\nimport { getLocation } from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search sharing\n */\nexport interface SearchShare {\n url: URL /* Deep link for sharing */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n query$: Observable /* Search query observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search sharing\n *\n * @param _el - Search sharing element\n * @param options - Options\n *\n * @returns Search sharing observable\n */\nexport function watchSearchShare(\n _el: HTMLElement, { query$ }: WatchOptions\n): Observable {\n return query$\n .pipe(\n map(({ value }) => {\n const url = getLocation()\n url.hash = \"\"\n url.searchParams.delete(\"h\")\n url.searchParams.set(\"q\", value)\n return { url }\n })\n )\n}\n\n/**\n * Mount search sharing\n *\n * @param el - Search sharing element\n * @param options - Options\n *\n * @returns Search sharing component observable\n */\nexport function mountSearchShare(\n el: HTMLAnchorElement, options: MountOptions\n): Observable> {\n const push$ = new Subject()\n push$.subscribe(({ url }) => {\n el.setAttribute(\"data-clipboard-text\", el.href)\n el.href = `${url}`\n })\n\n /* Prevent following of link */\n fromEvent(el, \"click\")\n .subscribe(ev => ev.preventDefault())\n\n /* Create and return component */\n return watchSearchShare(el, options)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n asyncScheduler,\n combineLatestWith,\n distinctUntilChanged,\n filter,\n finalize,\n fromEvent,\n map,\n merge,\n observeOn,\n tap\n} from \"rxjs\"\n\nimport { Keyboard } from \"~/browser\"\nimport {\n SearchResult,\n SearchWorker,\n isSearchResultMessage\n} from \"~/integrations\"\n\nimport { Component, getComponentElement } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search suggestions\n */\nexport interface SearchSuggest {}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n keyboard$: Observable /* Keyboard observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search suggestions\n *\n * This function will perform a lazy rendering of the search results, depending\n * on the vertical offset of the search result container.\n *\n * @param el - Search result list element\n * @param worker - Search worker\n * @param options - Options\n *\n * @returns Search result list component observable\n */\nexport function mountSearchSuggest(\n el: HTMLElement, { rx$ }: SearchWorker, { keyboard$ }: MountOptions\n): Observable> {\n const push$ = new Subject()\n\n /* Retrieve query component and track all changes */\n const query = getComponentElement(\"search-query\")\n const query$ = merge(\n fromEvent(query, \"keydown\"),\n fromEvent(query, \"focus\")\n )\n .pipe(\n observeOn(asyncScheduler),\n map(() => query.value),\n distinctUntilChanged(),\n )\n\n /* Update search suggestions */\n push$\n .pipe(\n combineLatestWith(query$),\n map(([{ suggestions }, value]) => {\n const words = value.split(/([\\s-]+)/)\n if (suggestions?.length && words[words.length - 1]) {\n const last = suggestions[suggestions.length - 1]\n if (last.startsWith(words[words.length - 1]))\n words[words.length - 1] = last\n } else {\n words.length = 0\n }\n return words\n })\n )\n .subscribe(words => el.innerHTML = words\n .join(\"\")\n .replace(/\\s/g, \" \")\n )\n\n /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Right arrow: accept current suggestion */\n case \"ArrowRight\":\n if (\n el.innerText.length &&\n query.selectionStart === query.value.length\n )\n query.value = el.innerText\n break\n }\n })\n\n /* Filter search result message */\n const result$ = rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => data)\n )\n\n /* Create and return component */\n return result$\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(() => ({ ref: el }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n ObservableInput,\n filter,\n merge,\n mergeWith,\n sample,\n take\n} from \"rxjs\"\n\nimport { configuration } from \"~/_\"\nimport {\n Keyboard,\n getActiveElement,\n getElements,\n setToggle\n} from \"~/browser\"\nimport {\n SearchIndex,\n SearchResult,\n isSearchQueryMessage,\n isSearchReadyMessage,\n setupSearchWorker\n} from \"~/integrations\"\n\nimport {\n Component,\n getComponentElement,\n getComponentElements\n} from \"../../_\"\nimport {\n SearchQuery,\n mountSearchQuery\n} from \"../query\"\nimport { mountSearchResult } from \"../result\"\nimport {\n SearchShare,\n mountSearchShare\n} from \"../share\"\nimport {\n SearchSuggest,\n mountSearchSuggest\n} from \"../suggest\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search\n */\nexport type Search =\n | SearchQuery\n | SearchResult\n | SearchShare\n | SearchSuggest\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n index$: ObservableInput /* Search index observable */\n keyboard$: Observable /* Keyboard observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search\n *\n * This function sets up the search functionality, including the underlying\n * web worker and all keyboard bindings.\n *\n * @param el - Search element\n * @param options - Options\n *\n * @returns Search component observable\n */\nexport function mountSearch(\n el: HTMLElement, { index$, keyboard$ }: MountOptions\n): Observable> {\n const config = configuration()\n try {\n const url = __search?.worker || config.search\n const worker = setupSearchWorker(url, index$)\n\n /* Retrieve query and result components */\n const query = getComponentElement(\"search-query\", el)\n const result = getComponentElement(\"search-result\", el)\n\n /* Re-emit query when search is ready */\n const { tx$, rx$ } = worker\n tx$\n .pipe(\n filter(isSearchQueryMessage),\n sample(rx$.pipe(filter(isSearchReadyMessage))),\n take(1)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\")\n )\n .subscribe(key => {\n const active = getActiveElement()\n switch (key.type) {\n\n /* Enter: go to first (best) result */\n case \"Enter\":\n if (active === query) {\n const anchors = new Map()\n for (const anchor of getElements(\n \":first-child [href]\", result\n )) {\n const article = anchor.firstElementChild!\n anchors.set(anchor, parseFloat(\n article.getAttribute(\"data-md-score\")!\n ))\n }\n\n /* Go to result with highest score, if any */\n if (anchors.size) {\n const [[best]] = [...anchors].sort(([, a], [, b]) => b - a)\n best.click()\n }\n\n /* Otherwise omit form submission */\n key.claim()\n }\n break\n\n /* Escape or Tab: close search */\n case \"Escape\":\n case \"Tab\":\n setToggle(\"search\", false)\n query.blur()\n break\n\n /* Vertical arrows: select previous or next search result */\n case \"ArrowUp\":\n case \"ArrowDown\":\n if (typeof active === \"undefined\") {\n query.focus()\n } else {\n const els = [query, ...getElements(\n \":not(details) > [href], summary, details[open] [href]\",\n result\n )]\n const i = Math.max(0, (\n Math.max(0, els.indexOf(active)) + els.length + (\n key.type === \"ArrowUp\" ? -1 : +1\n )\n ) % els.length)\n els[i].focus()\n }\n\n /* Prevent scrolling of page */\n key.claim()\n break\n\n /* All other keys: hand to search query */\n default:\n if (query !== getActiveElement())\n query.focus()\n }\n })\n\n /* Set up global keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\"),\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Open search and select query */\n case \"f\":\n case \"s\":\n case \"/\":\n query.focus()\n query.select()\n\n /* Prevent scrolling of page */\n key.claim()\n break\n }\n })\n\n /* Create and return component */\n const query$ = mountSearchQuery(query, worker)\n const result$ = mountSearchResult(result, worker, { query$ })\n return merge(query$, result$)\n .pipe(\n mergeWith(\n\n /* Search sharing */\n ...getComponentElements(\"search-share\", el)\n .map(child => mountSearchShare(child, { query$ })),\n\n /* Search suggestions */\n ...getComponentElements(\"search-suggest\", el)\n .map(child => mountSearchSuggest(child, worker, { keyboard$ }))\n )\n )\n\n /* Gracefully handle broken search */\n } catch (err) {\n el.hidden = true\n return NEVER\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n ObservableInput,\n combineLatest,\n filter,\n map,\n startWith\n} from \"rxjs\"\n\nimport { getLocation } from \"~/browser\"\nimport {\n SearchIndex,\n setupSearchHighlighter\n} from \"~/integrations\"\nimport { h } from \"~/utilities\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search highlighting\n */\nexport interface SearchHighlight {\n nodes: Map /* Map of replacements */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n index$: ObservableInput /* Search index observable */\n location$: Observable /* Location observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search highlighting\n *\n * @param el - Content element\n * @param options - Options\n *\n * @returns Search highlighting component observable\n */\nexport function mountSearchHiglight(\n el: HTMLElement, { index$, location$ }: MountOptions\n): Observable> {\n return combineLatest([\n index$,\n location$\n .pipe(\n startWith(getLocation()),\n filter(url => !!url.searchParams.get(\"h\"))\n )\n ])\n .pipe(\n map(([index, url]) => setupSearchHighlighter(index.config, true)(\n url.searchParams.get(\"h\")!\n )),\n map(fn => {\n const nodes = new Map()\n\n /* Traverse text nodes and collect matches */\n const it = document.createNodeIterator(el, NodeFilter.SHOW_TEXT)\n for (let node = it.nextNode(); node; node = it.nextNode()) {\n if (node.parentElement?.offsetHeight) {\n const original = node.textContent!\n const replaced = fn(original)\n if (replaced.length > original.length)\n nodes.set(node as ChildNode, replaced)\n }\n }\n\n /* Replace original nodes with matches */\n for (const [node, text] of nodes) {\n const { childNodes } = h(\"span\", null, text)\n node.replaceWith(...Array.from(childNodes))\n }\n\n /* Return component */\n return { ref: el, nodes }\n })\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n auditTime,\n combineLatest,\n defer,\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n take,\n tap,\n withLatestFrom\n} from \"rxjs\"\n\nimport {\n Viewport,\n getElement,\n getElementContainer,\n getElementOffset,\n getElementSize,\n getElements\n} from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Sidebar\n */\nexport interface Sidebar {\n height: number /* Sidebar height */\n locked: boolean /* Sidebar is locked */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n main$: Observable
    /* Main area observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch sidebar\n *\n * This function returns an observable that computes the visual parameters of\n * the sidebar which depends on the vertical viewport offset, as well as the\n * height of the main area. When the page is scrolled beyond the header, the\n * sidebar is locked and fills the remaining space.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar observable\n */\nexport function watchSidebar(\n el: HTMLElement, { viewport$, main$ }: WatchOptions\n): Observable {\n const parent = el.parentElement!\n const adjust =\n parent.offsetTop -\n parent.parentElement!.offsetTop\n\n /* Compute the sidebar's available height and if it should be locked */\n return combineLatest([main$, viewport$])\n .pipe(\n map(([{ offset, height }, { offset: { y } }]) => {\n height = height\n + Math.min(adjust, Math.max(0, y - offset))\n - adjust\n return {\n height,\n locked: y >= offset + adjust\n }\n }),\n distinctUntilChanged((a, b) => (\n a.height === b.height &&\n a.locked === b.locked\n ))\n )\n}\n\n/**\n * Mount sidebar\n *\n * This function doesn't set the height of the actual sidebar, but of its first\n * child \u2013 the `.md-sidebar__scrollwrap` element in order to mitigiate jittery\n * sidebars when the footer is scrolled into view. At some point we switched\n * from `absolute` / `fixed` positioning to `sticky` positioning, significantly\n * reducing jitter in some browsers (respectively Firefox and Safari) when\n * scrolling from the top. However, top-aligned sticky positioning means that\n * the sidebar snaps to the bottom when the end of the container is reached.\n * This is what leads to the mentioned jitter, as the sidebar's height may be\n * updated too slowly.\n *\n * This behaviour can be mitigiated by setting the height of the sidebar to `0`\n * while preserving the padding, and the height on its first element.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar component observable\n */\nexport function mountSidebar(\n el: HTMLElement, { header$, ...options }: MountOptions\n): Observable> {\n const inner = getElement(\".md-sidebar__scrollwrap\", el)\n const { y } = getElementOffset(inner)\n return defer(() => {\n const push$ = new Subject()\n push$\n .pipe(\n auditTime(0, animationFrameScheduler),\n withLatestFrom(header$)\n )\n .subscribe({\n\n /* Handle emission */\n next([{ height }, { height: offset }]) {\n inner.style.height = `${height - 2 * y}px`\n el.style.top = `${offset}px`\n },\n\n /* Handle complete */\n complete() {\n inner.style.height = \"\"\n el.style.top = \"\"\n }\n })\n\n /* Bring active item into view on initial load */\n push$\n .pipe(\n observeOn(animationFrameScheduler),\n take(1)\n )\n .subscribe(() => {\n for (const item of getElements(\".md-nav__link--active[href]\", el)) {\n const container = getElementContainer(item)\n if (typeof container !== \"undefined\") {\n const offset = item.offsetTop - container.offsetTop\n const { height } = getElementSize(container)\n container.scrollTo({\n top: offset - height / 2\n })\n }\n }\n })\n\n /* Create and return component */\n return watchSidebar(el, options)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Repo, User } from \"github-types\"\nimport {\n EMPTY,\n Observable,\n catchError,\n defaultIfEmpty,\n map,\n zip\n} from \"rxjs\"\n\nimport { requestJSON } from \"~/browser\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * GitHub release (partial)\n */\ninterface Release {\n tag_name: string /* Tag name */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitHub repository facts\n *\n * @param user - GitHub user or organization\n * @param repo - GitHub repository\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitHub(\n user: string, repo?: string\n): Observable {\n if (typeof repo !== \"undefined\") {\n const url = `https://api.github.com/repos/${user}/${repo}`\n return zip(\n\n /* Fetch version */\n requestJSON(`${url}/releases/latest`)\n .pipe(\n catchError(() => EMPTY), // @todo refactor instant loading\n map(release => ({\n version: release.tag_name\n })),\n defaultIfEmpty({})\n ),\n\n /* Fetch stars and forks */\n requestJSON(url)\n .pipe(\n catchError(() => EMPTY), // @todo refactor instant loading\n map(info => ({\n stars: info.stargazers_count,\n forks: info.forks_count\n })),\n defaultIfEmpty({})\n )\n )\n .pipe(\n map(([release, info]) => ({ ...release, ...info }))\n )\n\n /* User or organization */\n } else {\n const url = `https://api.github.com/users/${user}`\n return requestJSON(url)\n .pipe(\n map(info => ({\n repositories: info.public_repos\n })),\n defaultIfEmpty({})\n )\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ProjectSchema } from \"gitlab\"\nimport {\n EMPTY,\n Observable,\n catchError,\n defaultIfEmpty,\n map\n} from \"rxjs\"\n\nimport { requestJSON } from \"~/browser\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitLab repository facts\n *\n * @param base - GitLab base\n * @param project - GitLab project\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitLab(\n base: string, project: string\n): Observable {\n const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`\n return requestJSON(url)\n .pipe(\n catchError(() => EMPTY), // @todo refactor instant loading\n map(({ star_count, forks_count }) => ({\n stars: star_count,\n forks: forks_count\n })),\n defaultIfEmpty({})\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { EMPTY, Observable } from \"rxjs\"\n\nimport { fetchSourceFactsFromGitHub } from \"../github\"\nimport { fetchSourceFactsFromGitLab } from \"../gitlab\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository facts for repositories\n */\nexport interface RepositoryFacts {\n stars?: number /* Number of stars */\n forks?: number /* Number of forks */\n version?: string /* Latest version */\n}\n\n/**\n * Repository facts for organizations\n */\nexport interface OrganizationFacts {\n repositories?: number /* Number of repositories */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Repository facts\n */\nexport type SourceFacts =\n | RepositoryFacts\n | OrganizationFacts\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch repository facts\n *\n * @param url - Repository URL\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFacts(\n url: string\n): Observable {\n const [type] = url.match(/(git(?:hub|lab))/i) || []\n switch (type.toLowerCase()) {\n\n /* GitHub repository */\n case \"github\":\n const [, user, repo] = url.match(/^.+github\\.com\\/([^/]+)\\/?([^/]+)?/i)!\n return fetchSourceFactsFromGitHub(user, repo)\n\n /* GitLab repository */\n case \"gitlab\":\n const [, base, slug] = url.match(/^.+?([^/]*gitlab[^/]+)\\/(.+?)\\/?$/i)!\n return fetchSourceFactsFromGitLab(base, slug)\n\n /* Everything else */\n default:\n return EMPTY\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n Observable,\n Subject,\n catchError,\n defer,\n filter,\n finalize,\n map,\n of,\n shareReplay,\n tap\n} from \"rxjs\"\n\nimport { getElement } from \"~/browser\"\nimport { ConsentDefaults } from \"~/components/consent\"\nimport { renderSourceFacts } from \"~/templates\"\n\nimport {\n Component,\n getComponentElements\n} from \"../../_\"\nimport {\n SourceFacts,\n fetchSourceFacts\n} from \"../facts\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository information\n */\nexport interface Source {\n facts: SourceFacts /* Repository facts */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository information observable\n */\nlet fetch$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch repository information\n *\n * This function tries to read the repository facts from session storage, and\n * if unsuccessful, fetches them from the underlying provider.\n *\n * @param el - Repository information element\n *\n * @returns Repository information observable\n */\nexport function watchSource(\n el: HTMLAnchorElement\n): Observable {\n return fetch$ ||= defer(() => {\n const cached = __md_get(\"__source\", sessionStorage)\n if (cached) {\n return of(cached)\n } else {\n\n /* Check if consent is configured and was given */\n const els = getComponentElements(\"consent\")\n if (els.length) {\n const consent = __md_get(\"__consent\")\n if (!(consent && consent.github))\n return EMPTY\n }\n\n /* Fetch repository facts */\n return fetchSourceFacts(el.href)\n .pipe(\n tap(facts => __md_set(\"__source\", facts, sessionStorage))\n )\n }\n })\n .pipe(\n catchError(() => EMPTY),\n filter(facts => Object.keys(facts).length > 0),\n map(facts => ({ facts })),\n shareReplay(1)\n )\n}\n\n/**\n * Mount repository information\n *\n * @param el - Repository information element\n *\n * @returns Repository information component observable\n */\nexport function mountSource(\n el: HTMLAnchorElement\n): Observable> {\n const inner = getElement(\":scope > :last-child\", el)\n return defer(() => {\n const push$ = new Subject()\n push$.subscribe(({ facts }) => {\n inner.appendChild(renderSourceFacts(facts))\n inner.classList.add(\"md-source__repository--active\")\n })\n\n /* Create and return component */\n return watchSource(el)\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n defer,\n distinctUntilKeyChanged,\n finalize,\n map,\n of,\n switchMap,\n tap\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport {\n Viewport,\n watchElementSize,\n watchViewportAt\n} from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Navigation tabs\n */\nexport interface Tabs {\n hidden: boolean /* Navigation tabs are hidden */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch navigation tabs\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs observable\n */\nexport function watchTabs(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchElementSize(document.body)\n .pipe(\n switchMap(() => watchViewportAt(el, { header$, viewport$ })),\n map(({ offset: { y } }) => {\n return {\n hidden: y >= 10\n }\n }),\n distinctUntilKeyChanged(\"hidden\")\n )\n}\n\n/**\n * Mount navigation tabs\n *\n * This function hides the navigation tabs when scrolling past the threshold\n * and makes them reappear in a nice CSS animation when scrolling back up.\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs component observable\n */\nexport function mountTabs(\n el: HTMLElement, options: MountOptions\n): Observable> {\n return defer(() => {\n const push$ = new Subject()\n push$.subscribe({\n\n /* Handle emission */\n next({ hidden }) {\n el.hidden = hidden\n },\n\n /* Handle complete */\n complete() {\n el.hidden = false\n }\n })\n\n /* Create and return component */\n return (\n feature(\"navigation.tabs.sticky\")\n ? of({ hidden: false })\n : watchTabs(el, options)\n )\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n bufferCount,\n combineLatestWith,\n debounceTime,\n defer,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n finalize,\n map,\n merge,\n of,\n repeat,\n scan,\n share,\n skip,\n startWith,\n switchMap,\n takeLast,\n takeUntil,\n tap,\n withLatestFrom\n} from \"rxjs\"\n\nimport { feature } from \"~/_\"\nimport {\n Viewport,\n getElement,\n getElementContainer,\n getElementSize,\n getElements,\n getLocation,\n getOptionalElement,\n watchElementSize\n} from \"~/browser\"\n\nimport {\n Component,\n getComponentElement\n} from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Table of contents\n */\nexport interface TableOfContents {\n prev: HTMLAnchorElement[][] /* Anchors (previous) */\n next: HTMLAnchorElement[][] /* Anchors (next) */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n target$: Observable /* Location target observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch table of contents\n *\n * This is effectively a scroll spy implementation which will account for the\n * fixed header and automatically re-calculate anchor offsets when the viewport\n * is resized. The returned observable will only emit if the table of contents\n * needs to be repainted.\n *\n * This implementation tracks an anchor element's entire path starting from its\n * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the\n * Material theme currently doesn't make use of this information, it enables\n * the styling of the entire hierarchy through customization.\n *\n * Note that the current anchor is the last item of the `prev` anchor list.\n *\n * @param el - Table of contents element\n * @param options - Options\n *\n * @returns Table of contents observable\n */\nexport function watchTableOfContents(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n const table = new Map()\n\n /* Compute anchor-to-target mapping */\n const anchors = getElements(\"[href^=\\\\#]\", el)\n for (const anchor of anchors) {\n const id = decodeURIComponent(anchor.hash.substring(1))\n const target = getOptionalElement(`[id=\"${id}\"]`)\n if (typeof target !== \"undefined\")\n table.set(anchor, target)\n }\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n map(({ height }) => {\n const main = getComponentElement(\"main\")\n const grid = getElement(\":scope > :first-child\", main)\n return height + 0.8 * (\n grid.offsetTop -\n main.offsetTop\n )\n }),\n share()\n )\n\n /* Compute partition of previous and next anchors */\n const partition$ = watchElementSize(document.body)\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n\n /* Build index to map anchor paths to vertical offsets */\n switchMap(body => defer(() => {\n let path: HTMLAnchorElement[] = []\n return of([...table].reduce((index, [anchor, target]) => {\n while (path.length) {\n const last = table.get(path[path.length - 1])!\n if (last.tagName >= target.tagName) {\n path.pop()\n } else {\n break\n }\n }\n\n /* If the current anchor is hidden, continue with its parent */\n let offset = target.offsetTop\n while (!offset && target.parentElement) {\n target = target.parentElement\n offset = target.offsetTop\n }\n\n /* Map reversed anchor path to vertical offset */\n return index.set(\n [...path = [...path, anchor]].reverse(),\n offset\n )\n }, new Map()))\n })\n .pipe(\n\n /* Sort index by vertical offset (see https://bit.ly/30z6QSO) */\n map(index => new Map([...index].sort(([, a], [, b]) => a - b))),\n combineLatestWith(adjust$),\n\n /* Re-compute partition when viewport offset changes */\n switchMap(([index, adjust]) => viewport$\n .pipe(\n scan(([prev, next], { offset: { y }, size }) => {\n const last = y + size.height >= Math.floor(body.height)\n\n /* Look forward */\n while (next.length) {\n const [, offset] = next[0]\n if (offset - adjust < y || last) {\n prev = [...prev, next.shift()!]\n } else {\n break\n }\n }\n\n /* Look backward */\n while (prev.length) {\n const [, offset] = prev[prev.length - 1]\n if (offset - adjust >= y && !last) {\n next = [prev.pop()!, ...next]\n } else {\n break\n }\n }\n\n /* Return partition */\n return [prev, next]\n }, [[], [...index]]),\n distinctUntilChanged((a, b) => (\n a[0] === b[0] &&\n a[1] === b[1]\n ))\n )\n )\n )\n )\n )\n\n /* Compute and return anchor list migrations */\n return partition$\n .pipe(\n map(([prev, next]) => ({\n prev: prev.map(([path]) => path),\n next: next.map(([path]) => path)\n })),\n\n /* Extract anchor list migrations */\n startWith({ prev: [], next: [] }),\n bufferCount(2, 1),\n map(([a, b]) => {\n\n /* Moving down */\n if (a.prev.length < b.prev.length) {\n return {\n prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length),\n next: []\n }\n\n /* Moving up */\n } else {\n return {\n prev: b.prev.slice(-1),\n next: b.next.slice(0, b.next.length - a.next.length)\n }\n }\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Mount table of contents\n *\n * @param el - Table of contents element\n * @param options - Options\n *\n * @returns Table of contents component observable\n */\nexport function mountTableOfContents(\n el: HTMLElement, { viewport$, header$, target$ }: MountOptions\n): Observable> {\n return defer(() => {\n const push$ = new Subject()\n const done$ = push$.pipe(takeLast(1))\n push$.subscribe(({ prev, next }) => {\n\n /* Look forward */\n for (const [anchor] of next) {\n anchor.classList.remove(\"md-nav__link--passed\")\n anchor.classList.remove(\"md-nav__link--active\")\n }\n\n /* Look backward */\n for (const [index, [anchor]] of prev.entries()) {\n anchor.classList.add(\"md-nav__link--passed\")\n anchor.classList.toggle(\n \"md-nav__link--active\",\n index === prev.length - 1\n )\n }\n })\n\n /* Set up following, if enabled */\n if (feature(\"toc.follow\")) {\n\n /* Toggle smooth scrolling only for anchor clicks */\n const smooth$ = merge(\n viewport$.pipe(debounceTime(1), map(() => undefined)),\n viewport$.pipe(debounceTime(250), map(() => \"smooth\" as const))\n )\n\n /* Bring active anchor into view */\n push$\n .pipe(\n filter(({ prev }) => prev.length > 0),\n withLatestFrom(smooth$)\n )\n .subscribe(([{ prev }, behavior]) => {\n const [anchor] = prev[prev.length - 1]\n if (anchor.offsetHeight) {\n\n /* Retrieve overflowing container and scroll */\n const container = getElementContainer(anchor)\n if (typeof container !== \"undefined\") {\n const offset = anchor.offsetTop - container.offsetTop\n const { height } = getElementSize(container)\n container.scrollTo({\n top: offset - height / 2,\n behavior\n })\n }\n }\n })\n }\n\n /* Set up anchor tracking, if enabled */\n if (feature(\"navigation.tracking\"))\n viewport$\n .pipe(\n takeUntil(done$),\n distinctUntilKeyChanged(\"offset\"),\n debounceTime(250),\n skip(1),\n takeUntil(target$.pipe(skip(1))),\n repeat({ delay: 250 }),\n withLatestFrom(push$)\n )\n .subscribe(([, { prev }]) => {\n const url = getLocation()\n\n /* Set hash fragment to active anchor */\n const anchor = prev[prev.length - 1]\n if (anchor && anchor.length) {\n const [active] = anchor\n const { hash } = new URL(active.href)\n if (url.hash !== hash) {\n url.hash = hash\n history.replaceState({}, \"\", `${url}`)\n }\n\n /* Reset anchor when at the top */\n } else {\n url.hash = \"\"\n history.replaceState({}, \"\", `${url}`)\n }\n })\n\n /* Create and return component */\n return watchTableOfContents(el, { viewport$, header$ })\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n bufferCount,\n combineLatest,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n endWith,\n finalize,\n map,\n repeat,\n skip,\n takeLast,\n takeUntil,\n tap\n} from \"rxjs\"\n\nimport { Viewport } from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Back-to-top button\n */\nexport interface BackToTop {\n hidden: boolean /* Back-to-top button is hidden */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n main$: Observable
    /* Main area observable */\n target$: Observable /* Location target observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n target$: Observable /* Location target observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch back-to-top\n *\n * @param _el - Back-to-top element\n * @param options - Options\n *\n * @returns Back-to-top observable\n */\nexport function watchBackToTop(\n _el: HTMLElement, { viewport$, main$, target$ }: WatchOptions\n): Observable {\n\n /* Compute direction */\n const direction$ = viewport$\n .pipe(\n map(({ offset: { y } }) => y),\n bufferCount(2, 1),\n map(([a, b]) => a > b && b > 0),\n distinctUntilChanged()\n )\n\n /* Compute whether main area is active */\n const active$ = main$\n .pipe(\n map(({ active }) => active)\n )\n\n /* Compute threshold for hiding */\n return combineLatest([active$, direction$])\n .pipe(\n map(([active, direction]) => !(active && direction)),\n distinctUntilChanged(),\n takeUntil(target$.pipe(skip(1))),\n endWith(true),\n repeat({ delay: 250 }),\n map(hidden => ({ hidden }))\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Mount back-to-top\n *\n * @param el - Back-to-top element\n * @param options - Options\n *\n * @returns Back-to-top component observable\n */\nexport function mountBackToTop(\n el: HTMLElement, { viewport$, header$, main$, target$ }: MountOptions\n): Observable> {\n const push$ = new Subject()\n const done$ = push$.pipe(takeLast(1))\n push$.subscribe({\n\n /* Handle emission */\n next({ hidden }) {\n el.hidden = hidden\n if (hidden) {\n el.setAttribute(\"tabindex\", \"-1\")\n el.blur()\n } else {\n el.removeAttribute(\"tabindex\")\n }\n },\n\n /* Handle complete */\n complete() {\n el.style.top = \"\"\n el.hidden = true\n el.removeAttribute(\"tabindex\")\n }\n })\n\n /* Watch header height */\n header$\n .pipe(\n takeUntil(done$),\n distinctUntilKeyChanged(\"height\")\n )\n .subscribe(({ height }) => {\n el.style.top = `${height + 16}px`\n })\n\n /* Create and return component */\n return watchBackToTop(el, { viewport$, main$, target$ })\n .pipe(\n tap(state => push$.next(state)),\n finalize(() => push$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n fromEvent,\n map,\n mergeMap,\n switchMap,\n takeWhile,\n tap,\n withLatestFrom\n} from \"rxjs\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n tablet$: Observable /* Media tablet observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch indeterminate checkboxes\n *\n * This function replaces the indeterminate \"pseudo state\" with the actual\n * indeterminate state, which is used to keep navigation always expanded.\n *\n * @param options - Options\n */\nexport function patchIndeterminate(\n { document$, tablet$ }: PatchOptions\n): void {\n document$\n .pipe(\n switchMap(() => getElements(\n // @todo `data-md-state` is deprecated and removed in v9\n \".md-toggle--indeterminate, [data-md-state=indeterminate]\"\n )),\n tap(el => {\n el.indeterminate = true\n el.checked = false\n }),\n mergeMap(el => fromEvent(el, \"change\")\n .pipe(\n takeWhile(() => el.classList.contains(\"md-toggle--indeterminate\")),\n map(() => el)\n )\n ),\n withLatestFrom(tablet$)\n )\n .subscribe(([el, tablet]) => {\n el.classList.remove(\"md-toggle--indeterminate\")\n if (tablet)\n el.checked = false\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n filter,\n fromEvent,\n map,\n mergeMap,\n switchMap,\n tap\n} from \"rxjs\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether the given device is an Apple device\n *\n * @returns Test result\n */\nfunction isAppleDevice(): boolean {\n return /(iPad|iPhone|iPod)/.test(navigator.userAgent)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all elements with `data-md-scrollfix` attributes\n *\n * This is a year-old patch which ensures that overflow scrolling works at the\n * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon\n * the start of a touch event.\n *\n * @see https://bit.ly/2SCtAOO - Original source\n *\n * @param options - Options\n */\nexport function patchScrollfix(\n { document$ }: PatchOptions\n): void {\n document$\n .pipe(\n switchMap(() => getElements(\"[data-md-scrollfix]\")),\n tap(el => el.removeAttribute(\"data-md-scrollfix\")),\n filter(isAppleDevice),\n mergeMap(el => fromEvent(el, \"touchstart\")\n .pipe(\n map(() => el)\n )\n )\n )\n .subscribe(el => {\n const top = el.scrollTop\n\n /* We're at the top of the container */\n if (top === 0) {\n el.scrollTop = 1\n\n /* We're at the bottom of the container */\n } else if (top + el.offsetHeight === el.scrollHeight) {\n el.scrollTop = top - 1\n }\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest,\n delay,\n map,\n of,\n switchMap,\n withLatestFrom\n} from \"rxjs\"\n\nimport {\n Viewport,\n watchToggle\n} from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n viewport$: Observable /* Viewport observable */\n tablet$: Observable /* Media tablet observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch the document body to lock when search is open\n *\n * For mobile and tablet viewports, the search is rendered full screen, which\n * leads to scroll leaking when at the top or bottom of the search result. This\n * function locks the body when the search is in full screen mode, and restores\n * the scroll position when leaving.\n *\n * @param options - Options\n */\nexport function patchScrolllock(\n { viewport$, tablet$ }: PatchOptions\n): void {\n combineLatest([watchToggle(\"search\"), tablet$])\n .pipe(\n map(([active, tablet]) => active && !tablet),\n switchMap(active => of(active)\n .pipe(\n delay(active ? 400 : 100)\n )\n ),\n withLatestFrom(viewport$)\n )\n .subscribe(([active, { offset: { y }}]) => {\n if (active) {\n document.body.setAttribute(\"data-md-scrolllock\", \"\")\n document.body.style.top = `-${y}px`\n } else {\n const value = -1 * parseInt(document.body.style.top, 10)\n document.body.removeAttribute(\"data-md-scrolllock\")\n document.body.style.top = \"\"\n if (value)\n window.scrollTo(0, value)\n }\n })\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Polyfills\n * ------------------------------------------------------------------------- */\n\n/* Polyfill `Object.entries` */\nif (!Object.entries)\n Object.entries = function (obj: object) {\n const data: [string, string][] = []\n for (const key of Object.keys(obj))\n // @ts-expect-error - ignore property access warning\n data.push([key, obj[key]])\n\n /* Return entries */\n return data\n }\n\n/* Polyfill `Object.values` */\nif (!Object.values)\n Object.values = function (obj: object) {\n const data: string[] = []\n for (const key of Object.keys(obj))\n // @ts-expect-error - ignore property access warning\n data.push(obj[key])\n\n /* Return values */\n return data\n }\n\n/* ------------------------------------------------------------------------- */\n\n/* Polyfills for `Element` */\nif (typeof Element !== \"undefined\") {\n\n /* Polyfill `Element.scrollTo` */\n if (!Element.prototype.scrollTo)\n Element.prototype.scrollTo = function (\n x?: ScrollToOptions | number, y?: number\n ): void {\n if (typeof x === \"object\") {\n this.scrollLeft = x.left!\n this.scrollTop = x.top!\n } else {\n this.scrollLeft = x!\n this.scrollTop = y!\n }\n }\n\n /* Polyfill `Element.replaceWith` */\n if (!Element.prototype.replaceWith)\n Element.prototype.replaceWith = function (\n ...nodes: Array\n ): void {\n const parent = this.parentNode\n if (parent) {\n if (nodes.length === 0)\n parent.removeChild(this)\n\n /* Replace children and create text nodes */\n for (let i = nodes.length - 1; i >= 0; i--) {\n let node = nodes[i]\n if (typeof node !== \"object\")\n node = document.createTextNode(node)\n else if (node.parentNode)\n node.parentNode.removeChild(node)\n\n /* Replace child or insert before previous sibling */\n if (!i)\n parent.replaceChild(node, this)\n else\n parent.insertBefore(this.previousSibling!, node)\n }\n }\n }\n}\n"], + "mappings": "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", + "names": ["require_focus_visible", "__commonJSMin", "exports", "module", "global", "factory", "applyFocusVisiblePolyfill", "scope", "hadKeyboardEvent", "hadFocusVisibleRecently", "hadFocusVisibleRecentlyTimeout", "inputTypesAllowlist", "isValidFocusTarget", "el", "focusTriggersKeyboardModality", "type", "tagName", "addFocusVisibleClass", "removeFocusVisibleClass", "onKeyDown", "e", "onPointerDown", "onFocus", "onBlur", "onVisibilityChange", "addInitialPointerMoveListeners", "onInitialPointerMove", "removeInitialPointerMoveListeners", "event", "error", "require_url_polyfill", "__commonJSMin", "exports", "global", "checkIfIteratorIsSupported", "error", "iteratorSupported", "createIterator", "items", "iterator", "value", "serializeParam", "deserializeParam", "polyfillURLSearchParams", "URLSearchParams", "searchString", "typeofSearchString", "_this", "name", "i", "entry", "key", "proto", "callback", "thisArg", "entries", "searchArray", "checkIfURLSearchParamsSupported", "e", "a", "b", "keys", "attributes", "attribute", "checkIfURLIsSupported", "u", "polyfillURL", "_URL", "URL", "url", "base", "doc", "baseElement", "err", "anchorElement", "inputElement", "searchParams", "enableSearchUpdate", "enableSearchParamsUpdate", "methodName", "method", "search", "linkURLWithAnchorAttribute", "attributeName", "expectedPort", "addPortToOrigin", "blob", "getOrigin", "require_tslib", "__commonJSMin", "exports", "module", "__extends", "__assign", "__rest", "__decorate", "__param", "__metadata", "__awaiter", "__generator", "__exportStar", "__values", "__read", "__spread", "__spreadArrays", "__spreadArray", "__await", "__asyncGenerator", "__asyncDelegator", "__asyncValues", "__makeTemplateObject", "__importStar", "__importDefault", "__classPrivateFieldGet", "__classPrivateFieldSet", "__createBinding", "factory", "root", "createExporter", "previous", "id", "v", "exporter", "extendStatics", "d", "b", "p", "__", "t", "s", "n", "e", "i", "decorators", "target", "key", "desc", "c", "r", "paramIndex", "decorator", "metadataKey", "metadataValue", "thisArg", "_arguments", "P", "generator", "adopt", "value", "resolve", "reject", "fulfilled", "step", "rejected", "result", "body", "_", "f", "y", "g", "verb", "op", "m", "o", "k", "k2", "ar", "error", "il", "a", "j", "jl", "to", "from", "pack", "l", "q", "resume", "settle", "fulfill", "cooked", "raw", "__setModuleDefault", "mod", "receiver", "state", "kind", "require_clipboard", "__commonJSMin", "exports", "module", "root", "factory", "__webpack_modules__", "__unused_webpack_module", "__webpack_exports__", "__webpack_require__", "clipboard", "tiny_emitter", "tiny_emitter_default", "listen", "listen_default", "src_select", "select_default", "command", "type", "err", "ClipboardActionCut", "target", "selectedText", "actions_cut", "createFakeElement", "value", "isRTL", "fakeElement", "yPosition", "fakeCopyAction", "options", "ClipboardActionCopy", "actions_copy", "_typeof", "obj", "ClipboardActionDefault", "_options$action", "action", "container", "text", "actions_default", "clipboard_typeof", "_classCallCheck", "instance", "Constructor", "_defineProperties", "props", "i", "descriptor", "_createClass", "protoProps", "staticProps", "_inherits", "subClass", "superClass", "_setPrototypeOf", "o", "p", "_createSuper", "Derived", "hasNativeReflectConstruct", "_isNativeReflectConstruct", "Super", "_getPrototypeOf", "result", "NewTarget", "_possibleConstructorReturn", "self", "call", "_assertThisInitialized", "e", "getAttributeValue", "suffix", "element", "attribute", "Clipboard", "_Emitter", "_super", "trigger", "_this", "_this2", "selector", "actions", "support", "DOCUMENT_NODE_TYPE", "proto", "closest", "__unused_webpack_exports", "_delegate", "callback", "useCapture", "listenerFn", "listener", "delegate", "elements", "is", "listenNode", "listenNodeList", "listenSelector", "node", "nodeList", "select", "isReadOnly", "selection", "range", "E", "name", "ctx", "data", "evtArr", "len", "evts", "liveEvents", "__webpack_module_cache__", "moduleId", "getter", "definition", "key", "prop", "require_escape_html", "__commonJSMin", "exports", "module", "matchHtmlRegExp", "escapeHtml", "string", "str", "match", "escape", "html", "index", "lastIndex", "r", "a", "e", "import_focus_visible", "n", "t", "s", "r", "o", "u", "i", "a", "e", "c", "import_url_polyfill", "import_tslib", "__extends", "__assign", "__rest", "__decorate", "__param", "__metadata", "__awaiter", "__generator", "__exportStar", "__createBinding", "__values", "__read", "__spread", "__spreadArrays", "__spreadArray", "__await", "__asyncGenerator", "__asyncDelegator", "__asyncValues", "__makeTemplateObject", "__importStar", "__importDefault", "__classPrivateFieldGet", "__classPrivateFieldSet", "tslib", "isFunction", "value", "createErrorClass", "createImpl", "_super", "instance", "ctorFunc", "UnsubscriptionError", "createErrorClass", "_super", "errors", "err", "i", "arrRemove", "arr", "item", "index", "Subscription", "initialTeardown", "errors", "_parentage", "_parentage_1", "__values", "_parentage_1_1", "parent_1", "initialFinalizer", "isFunction", "e", "UnsubscriptionError", "_finalizers", "_finalizers_1", "_finalizers_1_1", "finalizer", "execFinalizer", "err", "__spreadArray", "__read", "teardown", "_a", "parent", "arrRemove", "empty", "EMPTY_SUBSCRIPTION", "Subscription", "isSubscription", "value", "isFunction", "execFinalizer", "finalizer", "config", "timeoutProvider", "handler", "timeout", "args", "_i", "delegate", "__spreadArray", "__read", "handle", "reportUnhandledError", "err", "timeoutProvider", "onUnhandledError", "config", "noop", "COMPLETE_NOTIFICATION", "createNotification", "errorNotification", "error", "nextNotification", "value", "kind", "context", "errorContext", "cb", "config", "isRoot", "_a", "errorThrown", "error", "captureError", "err", "Subscriber", "_super", "__extends", "destination", "_this", "isSubscription", "EMPTY_OBSERVER", "next", "error", "complete", "SafeSubscriber", "value", "handleStoppedNotification", "nextNotification", "err", "errorNotification", "COMPLETE_NOTIFICATION", "Subscription", "_bind", "bind", "fn", "thisArg", "ConsumerObserver", "partialObserver", "value", "error", "handleUnhandledError", "err", "SafeSubscriber", "_super", "__extends", "observerOrNext", "complete", "_this", "isFunction", "context_1", "config", "Subscriber", "handleUnhandledError", "error", "config", "captureError", "reportUnhandledError", "defaultErrorHandler", "err", "handleStoppedNotification", "notification", "subscriber", "onStoppedNotification", "timeoutProvider", "EMPTY_OBSERVER", "noop", "observable", "identity", "x", "pipe", "fns", "_i", "pipeFromArray", "identity", "input", "prev", "fn", "Observable", "subscribe", "operator", "observable", "observerOrNext", "error", "complete", "_this", "subscriber", "isSubscriber", "SafeSubscriber", "errorContext", "_a", "source", "sink", "err", "next", "promiseCtor", "getPromiseCtor", "resolve", "reject", "value", "operations", "_i", "pipeFromArray", "x", "getPromiseCtor", "promiseCtor", "_a", "config", "isObserver", "value", "isFunction", "isSubscriber", "Subscriber", "isSubscription", "hasLift", "source", "isFunction", "operate", "init", "liftedSource", "err", "createOperatorSubscriber", "destination", "onNext", "onComplete", "onError", "onFinalize", "OperatorSubscriber", "_super", "__extends", "shouldUnsubscribe", "_this", "value", "err", "closed_1", "_a", "Subscriber", "animationFrameProvider", "callback", "request", "cancel", "delegate", "handle", "timestamp", "Subscription", "args", "_i", "__spreadArray", "__read", "ObjectUnsubscribedError", "createErrorClass", "_super", "Subject", "_super", "__extends", "_this", "operator", "subject", "AnonymousSubject", "ObjectUnsubscribedError", "value", "errorContext", "_b", "__values", "_c", "observer", "err", "observers", "_a", "subscriber", "hasError", "isStopped", "EMPTY_SUBSCRIPTION", "Subscription", "arrRemove", "thrownError", "observable", "Observable", "destination", "source", "AnonymousSubject", "_super", "__extends", "destination", "source", "_this", "value", "_b", "_a", "err", "subscriber", "EMPTY_SUBSCRIPTION", "Subject", "dateTimestampProvider", "ReplaySubject", "_super", "__extends", "_bufferSize", "_windowTime", "_timestampProvider", "dateTimestampProvider", "_this", "value", "_a", "isStopped", "_buffer", "_infiniteTimeWindow", "subscriber", "subscription", "copy", "i", "adjustedBufferSize", "now", "last", "Subject", "Action", "_super", "__extends", "scheduler", "work", "state", "delay", "Subscription", "intervalProvider", "handler", "timeout", "args", "_i", "delegate", "__spreadArray", "__read", "handle", "AsyncAction", "_super", "__extends", "scheduler", "work", "_this", "state", "delay", "id", "_a", "_id", "intervalProvider", "_scheduler", "error", "_delay", "errored", "errorValue", "e", "actions", "arrRemove", "Action", "Scheduler", "schedulerActionCtor", "now", "work", "delay", "state", "dateTimestampProvider", "AsyncScheduler", "_super", "__extends", "SchedulerAction", "now", "Scheduler", "_this", "action", "actions", "error", "asyncScheduler", "AsyncScheduler", "AsyncAction", "async", "AnimationFrameAction", "_super", "__extends", "scheduler", "work", "_this", "id", "delay", "animationFrameProvider", "actions", "_a", "AsyncAction", "AnimationFrameScheduler", "_super", "__extends", "action", "flushId", "actions", "error", "AsyncScheduler", "animationFrameScheduler", "AnimationFrameScheduler", "AnimationFrameAction", "EMPTY", "Observable", "subscriber", "isScheduler", "value", "isFunction", "last", "arr", "popResultSelector", "args", "isFunction", "popScheduler", "isScheduler", "popNumber", "defaultValue", "isArrayLike", "x", "isPromise", "value", "isFunction", "isInteropObservable", "input", "isFunction", "observable", "isAsyncIterable", "obj", "isFunction", "createInvalidObservableTypeError", "input", "getSymbolIterator", "iterator", "isIterable", "input", "isFunction", "iterator", "readableStreamLikeToAsyncGenerator", "readableStream", "reader", "__await", "_a", "_b", "value", "done", "isReadableStreamLike", "obj", "isFunction", "innerFrom", "input", "Observable", "isInteropObservable", "fromInteropObservable", "isArrayLike", "fromArrayLike", "isPromise", "fromPromise", "isAsyncIterable", "fromAsyncIterable", "isIterable", "fromIterable", "isReadableStreamLike", "fromReadableStreamLike", "createInvalidObservableTypeError", "obj", "subscriber", "obs", "observable", "isFunction", "array", "i", "promise", "value", "err", "reportUnhandledError", "iterable", "iterable_1", "__values", "iterable_1_1", "asyncIterable", "process", "readableStream", "readableStreamLikeToAsyncGenerator", "asyncIterable_1", "__asyncValues", "asyncIterable_1_1", "executeSchedule", "parentSubscription", "scheduler", "work", "delay", "repeat", "scheduleSubscription", "observeOn", "scheduler", "delay", "operate", "source", "subscriber", "createOperatorSubscriber", "value", "executeSchedule", "err", "subscribeOn", "scheduler", "delay", "operate", "source", "subscriber", "scheduleObservable", "input", "scheduler", "innerFrom", "subscribeOn", "observeOn", "schedulePromise", "input", "scheduler", "innerFrom", "subscribeOn", "observeOn", "scheduleArray", "input", "scheduler", "Observable", "subscriber", "i", "scheduleIterable", "input", "scheduler", "Observable", "subscriber", "iterator", "executeSchedule", "value", "done", "_a", "err", "isFunction", "scheduleAsyncIterable", "input", "scheduler", "Observable", "subscriber", "executeSchedule", "iterator", "result", "scheduleReadableStreamLike", "input", "scheduler", "scheduleAsyncIterable", "readableStreamLikeToAsyncGenerator", "scheduled", "input", "scheduler", "isInteropObservable", "scheduleObservable", "isArrayLike", "scheduleArray", "isPromise", "schedulePromise", "isAsyncIterable", "scheduleAsyncIterable", "isIterable", "scheduleIterable", "isReadableStreamLike", "scheduleReadableStreamLike", "createInvalidObservableTypeError", "from", "input", "scheduler", "scheduled", "innerFrom", "of", "args", "_i", "scheduler", "popScheduler", "from", "throwError", "errorOrErrorFactory", "scheduler", "errorFactory", "isFunction", "init", "subscriber", "Observable", "isValidDate", "value", "map", "project", "thisArg", "operate", "source", "subscriber", "index", "createOperatorSubscriber", "value", "isArray", "callOrApply", "fn", "args", "__spreadArray", "__read", "mapOneOrManyArgs", "map", "isArray", "getPrototypeOf", "objectProto", "getKeys", "argsArgArrayOrObject", "args", "first_1", "isPOJO", "keys", "key", "obj", "createObject", "keys", "values", "result", "key", "i", "combineLatest", "args", "_i", "scheduler", "popScheduler", "resultSelector", "popResultSelector", "_a", "argsArgArrayOrObject", "observables", "keys", "from", "result", "Observable", "combineLatestInit", "values", "createObject", "identity", "mapOneOrManyArgs", "valueTransform", "subscriber", "maybeSchedule", "length", "active", "remainingFirstValues", "i", "source", "hasFirstValue", "createOperatorSubscriber", "value", "execute", "subscription", "executeSchedule", "mergeInternals", "source", "subscriber", "project", "concurrent", "onBeforeNext", "expand", "innerSubScheduler", "additionalFinalizer", "buffer", "active", "index", "isComplete", "checkComplete", "outerNext", "value", "doInnerSub", "innerComplete", "innerFrom", "createOperatorSubscriber", "innerValue", "bufferedValue", "executeSchedule", "err", "mergeMap", "project", "resultSelector", "concurrent", "isFunction", "a", "i", "map", "b", "ii", "innerFrom", "operate", "source", "subscriber", "mergeInternals", "mergeAll", "concurrent", "mergeMap", "identity", "concatAll", "mergeAll", "concat", "args", "_i", "concatAll", "from", "popScheduler", "defer", "observableFactory", "Observable", "subscriber", "innerFrom", "nodeEventEmitterMethods", "eventTargetMethods", "jqueryMethods", "fromEvent", "target", "eventName", "options", "resultSelector", "isFunction", "mapOneOrManyArgs", "_a", "__read", "isEventTarget", "methodName", "handler", "isNodeStyleEventEmitter", "toCommonHandlerRegistry", "isJQueryStyleEventEmitter", "add", "remove", "isArrayLike", "mergeMap", "subTarget", "innerFrom", "Observable", "subscriber", "args", "_i", "fromEventPattern", "addHandler", "removeHandler", "resultSelector", "mapOneOrManyArgs", "Observable", "subscriber", "handler", "e", "_i", "retValue", "isFunction", "timer", "dueTime", "intervalOrScheduler", "scheduler", "async", "intervalDuration", "isScheduler", "Observable", "subscriber", "due", "isValidDate", "n", "merge", "args", "_i", "scheduler", "popScheduler", "concurrent", "popNumber", "sources", "innerFrom", "mergeAll", "from", "EMPTY", "NEVER", "Observable", "noop", "isArray", "argsOrArgArray", "args", "filter", "predicate", "thisArg", "operate", "source", "subscriber", "index", "createOperatorSubscriber", "value", "zip", "args", "_i", "resultSelector", "popResultSelector", "sources", "argsOrArgArray", "Observable", "subscriber", "buffers", "completed", "sourceIndex", "innerFrom", "createOperatorSubscriber", "value", "buffer", "result", "__spreadArray", "__read", "i", "EMPTY", "audit", "durationSelector", "operate", "source", "subscriber", "hasValue", "lastValue", "durationSubscriber", "isComplete", "endDuration", "value", "cleanupDuration", "createOperatorSubscriber", "innerFrom", "auditTime", "duration", "scheduler", "asyncScheduler", "audit", "timer", "bufferCount", "bufferSize", "startBufferEvery", "operate", "source", "subscriber", "buffers", "count", "createOperatorSubscriber", "value", "toEmit", "buffers_1", "__values", "buffers_1_1", "buffer", "toEmit_1", "toEmit_1_1", "arrRemove", "buffers_2", "buffers_2_1", "catchError", "selector", "operate", "source", "subscriber", "innerSub", "syncUnsub", "handledResult", "createOperatorSubscriber", "err", "innerFrom", "scanInternals", "accumulator", "seed", "hasSeed", "emitOnNext", "emitBeforeComplete", "source", "subscriber", "hasState", "state", "index", "createOperatorSubscriber", "value", "i", "combineLatest", "args", "_i", "resultSelector", "popResultSelector", "pipe", "__spreadArray", "__read", "mapOneOrManyArgs", "operate", "source", "subscriber", "combineLatestInit", "argsOrArgArray", "combineLatestWith", "otherSources", "_i", "combineLatest", "__spreadArray", "__read", "concatMap", "project", "resultSelector", "isFunction", "mergeMap", "debounceTime", "dueTime", "scheduler", "asyncScheduler", "operate", "source", "subscriber", "activeTask", "lastValue", "lastTime", "emit", "value", "emitWhenIdle", "targetTime", "now", "createOperatorSubscriber", "defaultIfEmpty", "defaultValue", "operate", "source", "subscriber", "hasValue", "createOperatorSubscriber", "value", "take", "count", "EMPTY", "operate", "source", "subscriber", "seen", "createOperatorSubscriber", "value", "ignoreElements", "operate", "source", "subscriber", "createOperatorSubscriber", "noop", "mapTo", "value", "map", "delayWhen", "delayDurationSelector", "subscriptionDelay", "source", "concat", "take", "ignoreElements", "mergeMap", "value", "index", "mapTo", "delay", "due", "scheduler", "asyncScheduler", "duration", "timer", "delayWhen", "distinctUntilChanged", "comparator", "keySelector", "identity", "defaultCompare", "operate", "source", "subscriber", "previousKey", "first", "createOperatorSubscriber", "value", "currentKey", "a", "b", "distinctUntilKeyChanged", "key", "compare", "distinctUntilChanged", "x", "y", "endWith", "values", "_i", "source", "concat", "of", "__spreadArray", "__read", "finalize", "callback", "operate", "source", "subscriber", "takeLast", "count", "EMPTY", "operate", "source", "subscriber", "buffer", "createOperatorSubscriber", "value", "buffer_1", "__values", "buffer_1_1", "merge", "args", "_i", "scheduler", "popScheduler", "concurrent", "popNumber", "argsOrArgArray", "operate", "source", "subscriber", "mergeAll", "from", "__spreadArray", "__read", "mergeWith", "otherSources", "_i", "merge", "__spreadArray", "__read", "repeat", "countOrConfig", "count", "delay", "_a", "EMPTY", "operate", "source", "subscriber", "soFar", "sourceSub", "resubscribe", "notifier", "timer", "innerFrom", "notifierSubscriber_1", "createOperatorSubscriber", "subscribeToSource", "syncUnsub", "sample", "notifier", "operate", "source", "subscriber", "hasValue", "lastValue", "createOperatorSubscriber", "value", "noop", "scan", "accumulator", "seed", "operate", "scanInternals", "share", "options", "_a", "connector", "Subject", "_b", "resetOnError", "_c", "resetOnComplete", "_d", "resetOnRefCountZero", "wrapperSource", "connection", "resetConnection", "subject", "refCount", "hasCompleted", "hasErrored", "cancelReset", "reset", "resetAndUnsubscribe", "conn", "operate", "source", "subscriber", "dest", "handleReset", "SafeSubscriber", "value", "err", "innerFrom", "on", "args", "_i", "onSubscriber", "__spreadArray", "__read", "shareReplay", "configOrBufferSize", "windowTime", "scheduler", "bufferSize", "refCount", "_a", "_b", "_c", "share", "ReplaySubject", "skip", "count", "filter", "_", "index", "skipUntil", "notifier", "operate", "source", "subscriber", "taking", "skipSubscriber", "createOperatorSubscriber", "noop", "innerFrom", "value", "startWith", "values", "_i", "scheduler", "popScheduler", "operate", "source", "subscriber", "concat", "switchMap", "project", "resultSelector", "operate", "source", "subscriber", "innerSubscriber", "index", "isComplete", "checkComplete", "createOperatorSubscriber", "value", "innerIndex", "outerIndex", "innerFrom", "innerValue", "takeUntil", "notifier", "operate", "source", "subscriber", "innerFrom", "createOperatorSubscriber", "noop", "takeWhile", "predicate", "inclusive", "operate", "source", "subscriber", "index", "createOperatorSubscriber", "value", "result", "tap", "observerOrNext", "error", "complete", "tapObserver", "isFunction", "operate", "source", "subscriber", "_a", "isUnsub", "createOperatorSubscriber", "value", "err", "_b", "identity", "defaultThrottleConfig", "throttle", "durationSelector", "config", "operate", "source", "subscriber", "leading", "trailing", "hasValue", "sendValue", "throttled", "isComplete", "endThrottling", "send", "cleanupThrottling", "startThrottle", "value", "innerFrom", "createOperatorSubscriber", "throttleTime", "duration", "scheduler", "config", "asyncScheduler", "defaultThrottleConfig", "duration$", "timer", "throttle", "withLatestFrom", "inputs", "_i", "project", "popResultSelector", "operate", "source", "subscriber", "len", "otherValues", "hasValue", "ready", "i", "innerFrom", "createOperatorSubscriber", "value", "identity", "noop", "values", "__spreadArray", "__read", "zip", "sources", "_i", "operate", "source", "subscriber", "__spreadArray", "__read", "zipWith", "otherInputs", "_i", "zip", "__spreadArray", "__read", "watchDocument", "document$", "ReplaySubject", "fromEvent", "getElements", "selector", "node", "getElement", "el", "getOptionalElement", "getActiveElement", "watchElementFocus", "el", "merge", "fromEvent", "debounceTime", "map", "active", "getActiveElement", "startWith", "distinctUntilChanged", "getElementOffset", "el", "watchElementOffset", "merge", "fromEvent", "auditTime", "animationFrameScheduler", "map", "startWith", "getElementContentOffset", "el", "watchElementContentOffset", "merge", "fromEvent", "auditTime", "animationFrameScheduler", "map", "startWith", "MapShim", "getIndex", "arr", "key", "result", "entry", "index", "class_1", "value", "entries", "callback", "ctx", "_i", "_a", "isBrowser", "global$1", "requestAnimationFrame$1", "trailingTimeout", "throttle", "delay", "leadingCall", "trailingCall", "lastCallTime", "resolvePending", "proxy", "timeoutCallback", "timeStamp", "REFRESH_DELAY", "transitionKeys", "mutationObserverSupported", "ResizeObserverController", "observer", "observers", "changesDetected", "activeObservers", "_b", "propertyName", "isReflowProperty", "defineConfigurable", "target", "props", "getWindowOf", "ownerGlobal", "emptyRect", "createRectInit", "toFloat", "getBordersSize", "styles", "positions", "size", "position", "getPaddings", "paddings", "positions_1", "getSVGContentRect", "bbox", "getHTMLElementContentRect", "clientWidth", "clientHeight", "horizPad", "vertPad", "width", "height", "isDocumentElement", "vertScrollbar", "horizScrollbar", "isSVGGraphicsElement", "getContentRect", "createReadOnlyRect", "x", "y", "Constr", "rect", "ResizeObservation", "ResizeObserverEntry", "rectInit", "contentRect", "ResizeObserverSPI", "controller", "callbackCtx", "observations", "_this", "observation", "ResizeObserver", "method", "ResizeObserver_es_default", "entry$", "Subject", "observer$", "defer", "of", "ResizeObserver_es_default", "entries", "entry", "switchMap", "observer", "merge", "NEVER", "finalize", "shareReplay", "getElementSize", "el", "watchElementSize", "tap", "filter", "target", "map", "startWith", "getElementContentSize", "el", "getElementContainer", "parent", "entry$", "Subject", "observer$", "defer", "of", "entries", "entry", "switchMap", "observer", "merge", "NEVER", "finalize", "shareReplay", "watchElementVisibility", "el", "tap", "filter", "target", "map", "isIntersecting", "watchElementBoundary", "threshold", "watchElementContentOffset", "y", "visible", "getElementSize", "content", "getElementContentSize", "distinctUntilChanged", "toggles", "getElement", "getToggle", "name", "setToggle", "value", "watchToggle", "el", "fromEvent", "map", "startWith", "isSusceptibleToKeyboard", "el", "type", "watchKeyboard", "fromEvent", "filter", "ev", "map", "getToggle", "mode", "active", "getActiveElement", "share", "getLocation", "setLocation", "url", "watchLocation", "Subject", "appendChild", "el", "child", "node", "h", "tag", "attributes", "children", "attr", "truncate", "value", "n", "i", "round", "digits", "getLocationHash", "setLocationHash", "hash", "el", "h", "ev", "watchLocationHash", "fromEvent", "map", "startWith", "filter", "shareReplay", "watchLocationTarget", "id", "getOptionalElement", "watchMedia", "query", "media", "fromEventPattern", "next", "startWith", "watchPrint", "merge", "fromEvent", "map", "at", "query$", "factory", "switchMap", "active", "EMPTY", "request", "url", "options", "from", "catchError", "EMPTY", "switchMap", "res", "throwError", "of", "requestJSON", "shareReplay", "requestXML", "dom", "map", "watchScript", "src", "script", "h", "defer", "merge", "fromEvent", "switchMap", "throwError", "map", "finalize", "take", "getViewportOffset", "watchViewportOffset", "merge", "fromEvent", "map", "startWith", "getViewportSize", "watchViewportSize", "fromEvent", "map", "startWith", "watchViewport", "combineLatest", "watchViewportOffset", "watchViewportSize", "map", "offset", "size", "shareReplay", "watchViewportAt", "el", "viewport$", "header$", "size$", "distinctUntilKeyChanged", "offset$", "combineLatest", "map", "getElementOffset", "height", "offset", "size", "x", "y", "watchWorker", "worker", "tx$", "rx$", "fromEvent", "map", "data", "throttle", "tap", "message", "switchMap", "share", "script", "getElement", "config", "getLocation", "configuration", "feature", "flag", "translation", "key", "value", "getComponentElement", "type", "node", "getElement", "getComponentElements", "getElements", "watchAnnounce", "el", "button", "getElement", "fromEvent", "map", "content", "mountAnnounce", "feature", "EMPTY", "defer", "push$", "Subject", "startWith", "hash", "_a", "tap", "state", "finalize", "__spreadValues", "watchConsent", "el", "target$", "map", "target", "mountConsent", "options", "internal$", "Subject", "hidden", "tap", "state", "finalize", "__spreadValues", "import_clipboard", "renderTooltip", "id", "h", "renderAnnotation", "id", "prefix", "anchor", "h", "renderTooltip", "renderClipboardButton", "id", "h", "translation", "renderSearchDocument", "document", "flag", "parent", "teaser", "missing", "key", "list", "h", "url", "feature", "match", "highlight", "value", "tags", "configuration", "truncate", "tag", "id", "type", "translation", "renderSearchResultItem", "result", "threshold", "docs", "doc", "article", "index", "best", "more", "children", "section", "renderSourceFacts", "facts", "h", "key", "value", "round", "renderTabbedControl", "type", "classes", "h", "renderTable", "table", "h", "renderVersion", "version", "config", "configuration", "url", "h", "renderVersionSelector", "versions", "active", "translation", "watchAnnotation", "el", "container", "offset$", "defer", "combineLatest", "watchElementOffset", "watchElementContentOffset", "map", "x", "y", "scroll", "width", "height", "getElementSize", "watchElementFocus", "switchMap", "active", "offset", "take", "mountAnnotation", "target$", "tooltip", "index", "push$", "Subject", "done$", "takeLast", "watchElementVisibility", "takeUntil", "visible", "merge", "filter", "debounceTime", "auditTime", "animationFrameScheduler", "throttleTime", "origin", "fromEvent", "ev", "withLatestFrom", "_a", "parent", "getActiveElement", "target", "delay", "tap", "state", "finalize", "__spreadValues", "findAnnotationMarkers", "container", "markers", "el", "getElements", "nodes", "it", "node", "text", "match", "id", "force", "marker", "swap", "source", "target", "mountAnnotationList", "target$", "print$", "parent", "prefix", "annotations", "getOptionalElement", "renderAnnotation", "EMPTY", "defer", "done$", "Subject", "pairs", "annotation", "getElement", "takeUntil", "takeLast", "active", "inner", "child", "merge", "mountAnnotation", "finalize", "share", "sequence", "findCandidateList", "el", "sibling", "watchCodeBlock", "watchElementSize", "map", "width", "getElementContentSize", "distinctUntilKeyChanged", "mountCodeBlock", "options", "hover", "factory$", "defer", "push$", "Subject", "scrollable", "ClipboardJS", "parent", "renderClipboardButton", "container", "list", "feature", "annotations$", "mountAnnotationList", "tap", "state", "finalize", "__spreadValues", "mergeWith", "height", "distinctUntilChanged", "switchMap", "active", "EMPTY", "watchElementVisibility", "filter", "visible", "take", "mermaid$", "sequence", "fetchScripts", "watchScript", "of", "mountMermaid", "el", "tap", "mermaid_default", "map", "shareReplay", "id", "host", "h", "svg", "shadow", "watchDetails", "el", "target$", "print$", "open", "merge", "map", "target", "filter", "details", "active", "tap", "mountDetails", "options", "defer", "push$", "Subject", "action", "reveal", "state", "finalize", "__spreadValues", "sentinel", "h", "mountDataTable", "el", "renderTable", "of", "watchContentTabs", "el", "inputs", "getElements", "initial", "input", "merge", "fromEvent", "map", "getElement", "startWith", "active", "mountContentTabs", "viewport$", "prev", "renderTabbedControl", "next", "container", "defer", "push$", "Subject", "done$", "takeLast", "combineLatest", "watchElementSize", "auditTime", "animationFrameScheduler", "takeUntil", "size", "offset", "getElementOffset", "width", "getElementSize", "content", "getElementContentOffset", "watchElementContentOffset", "getElementContentSize", "direction", "feature", "skip", "withLatestFrom", "tab", "y", "set", "label", "tabs", "tap", "state", "finalize", "__spreadValues", "subscribeOn", "asyncScheduler", "mountContent", "el", "viewport$", "target$", "print$", "merge", "getElements", "child", "mountCodeBlock", "mountMermaid", "mountDataTable", "mountDetails", "mountContentTabs", "watchDialog", "_el", "alert$", "switchMap", "message", "merge", "of", "delay", "map", "active", "mountDialog", "el", "options", "inner", "getElement", "defer", "push$", "Subject", "tap", "state", "finalize", "__spreadValues", "isHidden", "viewport$", "feature", "of", "direction$", "map", "y", "bufferCount", "a", "b", "distinctUntilKeyChanged", "hidden$", "combineLatest", "filter", "offset", "direction", "distinctUntilChanged", "search$", "watchToggle", "search", "switchMap", "active", "startWith", "watchHeader", "el", "options", "defer", "watchElementSize", "height", "hidden", "shareReplay", "mountHeader", "header$", "main$", "push$", "Subject", "done$", "takeLast", "combineLatestWith", "takeUntil", "state", "__spreadValues", "watchHeaderTitle", "el", "viewport$", "header$", "watchViewportAt", "map", "y", "height", "getElementSize", "distinctUntilKeyChanged", "mountHeaderTitle", "options", "defer", "push$", "Subject", "active", "heading", "getOptionalElement", "EMPTY", "tap", "state", "finalize", "__spreadValues", "watchMain", "el", "viewport$", "header$", "adjust$", "map", "height", "distinctUntilChanged", "border$", "switchMap", "watchElementSize", "distinctUntilKeyChanged", "combineLatest", "header", "top", "bottom", "y", "a", "b", "watchPalette", "inputs", "current", "input", "of", "mergeMap", "fromEvent", "map", "startWith", "shareReplay", "mountPalette", "el", "defer", "push$", "Subject", "palette", "key", "value", "index", "label", "observeOn", "asyncScheduler", "getElements", "tap", "state", "finalize", "__spreadValues", "import_clipboard", "extract", "el", "text", "setupClipboardJS", "alert$", "ClipboardJS", "Observable", "subscriber", "getElement", "ev", "tap", "map", "translation", "preprocess", "urls", "root", "next", "a", "b", "url", "index", "fetchSitemap", "base", "cached", "of", "config", "configuration", "requestXML", "map", "sitemap", "getElements", "node", "catchError", "EMPTY", "defaultIfEmpty", "tap", "setupInstantLoading", "document$", "location$", "viewport$", "config", "configuration", "fromEvent", "favicon", "getOptionalElement", "push$", "fetchSitemap", "map", "paths", "path", "switchMap", "urls", "filter", "ev", "el", "url", "of", "NEVER", "share", "pop$", "merge", "distinctUntilChanged", "a", "b", "response$", "distinctUntilKeyChanged", "request", "catchError", "setLocation", "sample", "dom", "res", "skip", "replacement", "selector", "feature", "source", "target", "getComponentElement", "getElements", "concatMap", "script", "h", "name", "Observable", "observer", "EMPTY", "offset", "setLocationHash", "skipUntil", "debounceTime", "bufferCount", "state", "import_escape_html", "import_escape_html", "setupSearchHighlighter", "config", "escape", "separator", "highlight", "_", "data", "term", "query", "match", "value", "escapeHTML", "defaultTransform", "query", "terms", "index", "isSearchReadyMessage", "message", "isSearchQueryMessage", "isSearchResultMessage", "setupSearchIndex", "config", "docs", "translation", "options", "feature", "setupSearchWorker", "url", "index", "configuration", "worker", "tx$", "Subject", "rx$", "watchWorker", "map", "message", "isSearchResultMessage", "result", "document", "share", "from", "data", "setupVersionSelector", "document$", "config", "configuration", "versions$", "requestJSON", "catchError", "EMPTY", "current$", "map", "versions", "current", "version", "aliases", "switchMap", "urls", "fromEvent", "filter", "ev", "withLatestFrom", "el", "url", "of", "fetchSitemap", "sitemap", "path", "getLocation", "setLocation", "combineLatest", "getElement", "renderVersionSelector", "_a", "outdated", "latest", "warning", "getComponentElements", "watchSearchQuery", "el", "rx$", "fn", "defaultTransform", "searchParams", "getLocation", "setToggle", "param$", "filter", "isSearchReadyMessage", "take", "map", "watchToggle", "active", "url", "value", "focus$", "watchElementFocus", "value$", "merge", "fromEvent", "delay", "startWith", "distinctUntilChanged", "combineLatest", "focus", "shareReplay", "mountSearchQuery", "tx$", "push$", "Subject", "done$", "takeLast", "distinctUntilKeyChanged", "translation", "takeUntil", "tap", "state", "finalize", "__spreadValues", "share", "mountSearchResult", "el", "rx$", "query$", "push$", "Subject", "boundary$", "watchElementBoundary", "filter", "meta", "getElement", "list", "ready$", "isSearchReadyMessage", "take", "withLatestFrom", "skipUntil", "items", "value", "translation", "round", "tap", "switchMap", "merge", "of", "bufferCount", "zipWith", "chunk", "result", "renderSearchResultItem", "isSearchResultMessage", "map", "data", "state", "finalize", "__spreadValues", "watchSearchShare", "_el", "query$", "map", "value", "url", "getLocation", "mountSearchShare", "el", "options", "push$", "Subject", "fromEvent", "ev", "tap", "state", "finalize", "__spreadValues", "mountSearchSuggest", "el", "rx$", "keyboard$", "push$", "Subject", "query", "getComponentElement", "query$", "merge", "fromEvent", "observeOn", "asyncScheduler", "map", "distinctUntilChanged", "combineLatestWith", "suggestions", "value", "words", "last", "filter", "mode", "key", "isSearchResultMessage", "data", "tap", "state", "finalize", "mountSearch", "el", "index$", "keyboard$", "config", "configuration", "url", "worker", "setupSearchWorker", "query", "getComponentElement", "result", "tx$", "rx$", "filter", "isSearchQueryMessage", "sample", "isSearchReadyMessage", "take", "mode", "key", "active", "getActiveElement", "anchors", "anchor", "getElements", "article", "best", "a", "b", "setToggle", "els", "i", "query$", "mountSearchQuery", "result$", "mountSearchResult", "merge", "mergeWith", "getComponentElements", "child", "mountSearchShare", "mountSearchSuggest", "err", "NEVER", "mountSearchHiglight", "el", "index$", "location$", "combineLatest", "startWith", "getLocation", "filter", "url", "map", "index", "setupSearchHighlighter", "fn", "_a", "nodes", "it", "node", "original", "replaced", "text", "childNodes", "h", "watchSidebar", "el", "viewport$", "main$", "parent", "adjust", "combineLatest", "map", "offset", "height", "y", "distinctUntilChanged", "a", "b", "mountSidebar", "_a", "_b", "header$", "options", "__objRest", "inner", "getElement", "getElementOffset", "defer", "push$", "Subject", "auditTime", "animationFrameScheduler", "withLatestFrom", "observeOn", "take", "item", "getElements", "container", "getElementContainer", "getElementSize", "tap", "state", "finalize", "__spreadValues", "fetchSourceFactsFromGitHub", "user", "repo", "url", "zip", "requestJSON", "catchError", "EMPTY", "map", "release", "defaultIfEmpty", "info", "__spreadValues", "fetchSourceFactsFromGitLab", "base", "project", "url", "requestJSON", "catchError", "EMPTY", "map", "star_count", "forks_count", "defaultIfEmpty", "fetchSourceFacts", "url", "type", "user", "repo", "fetchSourceFactsFromGitHub", "base", "slug", "fetchSourceFactsFromGitLab", "EMPTY", "fetch$", "watchSource", "el", "defer", "cached", "of", "getComponentElements", "consent", "EMPTY", "fetchSourceFacts", "tap", "facts", "catchError", "filter", "map", "shareReplay", "mountSource", "inner", "getElement", "push$", "Subject", "renderSourceFacts", "state", "finalize", "__spreadValues", "watchTabs", "el", "viewport$", "header$", "watchElementSize", "switchMap", "watchViewportAt", "map", "y", "distinctUntilKeyChanged", "mountTabs", "options", "defer", "push$", "Subject", "hidden", "feature", "of", "tap", "state", "finalize", "__spreadValues", "watchTableOfContents", "el", "viewport$", "header$", "table", "anchors", "getElements", "anchor", "id", "target", "getOptionalElement", "adjust$", "distinctUntilKeyChanged", "map", "height", "main", "getComponentElement", "grid", "getElement", "share", "watchElementSize", "switchMap", "body", "defer", "path", "of", "index", "offset", "a", "b", "combineLatestWith", "adjust", "scan", "prev", "next", "y", "size", "last", "distinctUntilChanged", "startWith", "bufferCount", "mountTableOfContents", "target$", "push$", "Subject", "done$", "takeLast", "feature", "smooth$", "merge", "debounceTime", "filter", "withLatestFrom", "behavior", "container", "getElementContainer", "getElementSize", "takeUntil", "skip", "repeat", "url", "getLocation", "active", "hash", "tap", "state", "finalize", "__spreadValues", "watchBackToTop", "_el", "viewport$", "main$", "target$", "direction$", "map", "y", "bufferCount", "a", "b", "distinctUntilChanged", "active$", "active", "combineLatest", "direction", "takeUntil", "skip", "endWith", "repeat", "hidden", "mountBackToTop", "el", "header$", "push$", "Subject", "done$", "takeLast", "distinctUntilKeyChanged", "height", "tap", "state", "finalize", "__spreadValues", "patchIndeterminate", "document$", "tablet$", "switchMap", "getElements", "tap", "el", "mergeMap", "fromEvent", "takeWhile", "map", "withLatestFrom", "tablet", "isAppleDevice", "patchScrollfix", "document$", "switchMap", "getElements", "tap", "el", "filter", "mergeMap", "fromEvent", "map", "top", "patchScrolllock", "viewport$", "tablet$", "combineLatest", "watchToggle", "map", "active", "tablet", "switchMap", "of", "delay", "withLatestFrom", "y", "value", "obj", "data", "key", "x", "y", "nodes", "parent", "i", "node", "document$", "watchDocument", "location$", "watchLocation", "target$", "watchLocationTarget", "keyboard$", "watchKeyboard", "viewport$", "watchViewport", "tablet$", "watchMedia", "screen$", "print$", "watchPrint", "config", "configuration", "index$", "requestJSON", "NEVER", "alert$", "Subject", "setupClipboardJS", "feature", "setupInstantLoading", "_a", "setupVersionSelector", "merge", "delay", "setToggle", "filter", "mode", "key", "prev", "getOptionalElement", "next", "patchIndeterminate", "patchScrollfix", "patchScrolllock", "header$", "watchHeader", "getComponentElement", "main$", "map", "switchMap", "el", "watchMain", "shareReplay", "control$", "getComponentElements", "mountConsent", "mountDialog", "mountHeader", "mountPalette", "mountSearch", "mountSource", "content$", "defer", "mountAnnounce", "mountContent", "mountSearchHiglight", "EMPTY", "mountHeaderTitle", "at", "mountSidebar", "mountTabs", "mountTableOfContents", "mountBackToTop", "component$", "mergeWith"] +} diff --git a/assets/javascripts/lunr/min/lunr.ar.min.js b/assets/javascripts/lunr/min/lunr.ar.min.js new file mode 100644 index 00000000..248ddc5d --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ar.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ar=function(){this.pipeline.reset(),this.pipeline.add(e.ar.trimmer,e.ar.stopWordFilter,e.ar.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ar.stemmer))},e.ar.wordCharacters="ء-ٛٱـ",e.ar.trimmer=e.trimmerSupport.generateTrimmer(e.ar.wordCharacters),e.Pipeline.registerFunction(e.ar.trimmer,"trimmer-ar"),e.ar.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ف ك ب و س ل ن ا ي ت",pre2:"ال لل",pre3:"بال وال فال تال كال ولل",pre4:"فبال كبال وبال وكال"},e.suf={suf1:"ه ك ت ن ا ي",suf2:"نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه",suf3:"تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها",suf4:"كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا"},e.patterns=JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}'),e.execArray=["cleanWord","removeDiacritics","cleanAlef","removeStopWords","normalizeHamzaAndAlef","removeStartWaw","removePre432","removeEndTaa","wordCheck"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHamzaAndAlef=function(){return e.word=e.word.replace("ؤ","ء"),e.word=e.word.replace("ئ","ء"),e.word=e.word.replace(/([\u0627])\1+/gi,"ا"),!1},e.removeEndTaa=function(){return!(e.word.length>2)||(e.word=e.word.replace(/[\u0627]$/,""),e.word=e.word.replace("ة",""),!1)},e.removeStartWaw=function(){return e.word.length>3&&"و"==e.word[0]&&"و"==e.word[1]&&(e.word=e.word.slice(1)),!1},e.removePre432=function(){var r=e.word;if(e.word.length>=7){var t=new RegExp("^("+e.pre.pre4.split(" ").join("|")+")");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=6){var c=new RegExp("^("+e.pre.pre3.split(" ").join("|")+")");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=5){var l=new RegExp("^("+e.pre.pre2.split(" ").join("|")+")");e.word=e.word.replace(l,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.patternCheck=function(r){for(var t=0;t3){var t=new RegExp("^("+e.pre.pre1.split(" ").join("|")+")");e.word=e.word.replace(t,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.removeSuf1=function(){var r=e.word;if(0==e.sufRemoved&&e.word.length>3){var t=new RegExp("("+e.suf.suf1.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.removeSuf432=function(){var r=e.word;if(e.word.length>=6){var t=new RegExp("("+e.suf.suf4.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=5){var c=new RegExp("("+e.suf.suf3.split(" ").join("|")+")$");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=4){var l=new RegExp("("+e.suf.suf2.split(" ").join("|")+")$");e.word=e.word.replace(l,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.wordCheck=function(){for(var r=(e.word,[e.removeSuf432,e.removeSuf1,e.removePre1]),t=0,c=!1;e.word.length>=7&&!e.result&&t=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.de.min.js b/assets/javascripts/lunr/min/lunr.de.min.js new file mode 100644 index 00000000..f3b5c108 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.de.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `German` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.du.min.js b/assets/javascripts/lunr/min/lunr.du.min.js new file mode 100644 index 00000000..49a0f3f0 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.du.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Dutch` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.es.min.js b/assets/javascripts/lunr/min/lunr.es.min.js new file mode 100644 index 00000000..2989d342 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.es.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Spanish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=function(){var s=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(){if(A.out_grouping(x,97,252)){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.fi.min.js b/assets/javascripts/lunr/min/lunr.fi.min.js new file mode 100644 index 00000000..29f5dfce --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.fi.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Finnish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.fr.min.js b/assets/javascripts/lunr/min/lunr.fr.min.js new file mode 100644 index 00000000..68cd0094 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.fr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `French` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.hi.min.js b/assets/javascripts/lunr/min/lunr.hi.min.js new file mode 100644 index 00000000..7dbc4140 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.hi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.hu.min.js b/assets/javascripts/lunr/min/lunr.hu.min.js new file mode 100644 index 00000000..ed9d909f --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.hu.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Hungarian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.it.min.js b/assets/javascripts/lunr/min/lunr.it.min.js new file mode 100644 index 00000000..344b6a3c --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.it.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Italian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!x.eq_s(1,e)||(x.ket=x.cursor,!x.in_grouping(L,97,249)))&&(x.slice_from(r),x.cursor=n,!0)}function i(){for(var r,n,i,o,t=x.cursor;;){if(x.bra=x.cursor,r=x.find_among(h,7))switch(x.ket=x.cursor,r){case 1:x.slice_from("à");continue;case 2:x.slice_from("è");continue;case 3:x.slice_from("ì");continue;case 4:x.slice_from("ò");continue;case 5:x.slice_from("ù");continue;case 6:x.slice_from("qU");continue;case 7:if(x.cursor>=x.limit)break;x.cursor++;continue}break}for(x.cursor=t;;)for(n=x.cursor;;){if(i=x.cursor,x.in_grouping(L,97,249)){if(x.bra=x.cursor,o=x.cursor,e("u","U",i))break;if(x.cursor=o,e("i","I",i))break}if(x.cursor=i,x.cursor>=x.limit)return void(x.cursor=n);x.cursor++}}function o(e){if(x.cursor=e,!x.in_grouping(L,97,249))return!1;for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function t(){if(x.in_grouping(L,97,249)){var e=x.cursor;if(x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return o(e);x.cursor++}return!0}return o(e)}return!1}function s(){var e,r=x.cursor;if(!t()){if(x.cursor=r,!x.out_grouping(L,97,249))return;if(e=x.cursor,x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return x.cursor=e,void(x.in_grouping(L,97,249)&&x.cursor=x.limit)return;x.cursor++}k=x.cursor}function a(){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function u(){var e=x.cursor;k=x.limit,p=k,g=k,s(),x.cursor=e,a()&&(p=x.cursor,a()&&(g=x.cursor))}function c(){for(var e;;){if(x.bra=x.cursor,!(e=x.find_among(q,3)))break;switch(x.ket=x.cursor,e){case 1:x.slice_from("i");break;case 2:x.slice_from("u");break;case 3:if(x.cursor>=x.limit)return;x.cursor++}}}function w(){return k<=x.cursor}function l(){return p<=x.cursor}function m(){return g<=x.cursor}function f(){var e;if(x.ket=x.cursor,x.find_among_b(C,37)&&(x.bra=x.cursor,(e=x.find_among_b(z,5))&&w()))switch(e){case 1:x.slice_del();break;case 2:x.slice_from("e")}}function v(){var e;if(x.ket=x.cursor,!(e=x.find_among_b(S,51)))return!1;switch(x.bra=x.cursor,e){case 1:if(!m())return!1;x.slice_del();break;case 2:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del());break;case 3:if(!m())return!1;x.slice_from("log");break;case 4:if(!m())return!1;x.slice_from("u");break;case 5:if(!m())return!1;x.slice_from("ente");break;case 6:if(!w())return!1;x.slice_del();break;case 7:if(!l())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(P,4),e&&(x.bra=x.cursor,m()&&(x.slice_del(),1==e&&(x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&x.slice_del()))));break;case 8:if(!m())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(F,3),e&&(x.bra=x.cursor,1==e&&m()&&x.slice_del());break;case 9:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del())))}return!0}function b(){var e,r;x.cursor>=k&&(r=x.limit_backward,x.limit_backward=k,x.ket=x.cursor,e=x.find_among_b(W,87),e&&(x.bra=x.cursor,1==e&&x.slice_del()),x.limit_backward=r)}function d(){var e=x.limit-x.cursor;if(x.ket=x.cursor,x.in_grouping_b(y,97,242)&&(x.bra=x.cursor,w()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(1,"i")&&(x.bra=x.cursor,w()))))return void x.slice_del();x.cursor=x.limit-e}function _(){d(),x.ket=x.cursor,x.eq_s_b(1,"h")&&(x.bra=x.cursor,x.in_grouping_b(U,99,103)&&w()&&x.slice_del())}var g,p,k,h=[new r("",-1,7),new r("qu",0,6),new r("á",0,1),new r("é",0,2),new r("í",0,3),new r("ó",0,4),new r("ú",0,5)],q=[new r("",-1,3),new r("I",0,1),new r("U",0,2)],C=[new r("la",-1,-1),new r("cela",0,-1),new r("gliela",0,-1),new r("mela",0,-1),new r("tela",0,-1),new r("vela",0,-1),new r("le",-1,-1),new r("cele",6,-1),new r("gliele",6,-1),new r("mele",6,-1),new r("tele",6,-1),new r("vele",6,-1),new r("ne",-1,-1),new r("cene",12,-1),new r("gliene",12,-1),new r("mene",12,-1),new r("sene",12,-1),new r("tene",12,-1),new r("vene",12,-1),new r("ci",-1,-1),new r("li",-1,-1),new r("celi",20,-1),new r("glieli",20,-1),new r("meli",20,-1),new r("teli",20,-1),new r("veli",20,-1),new r("gli",20,-1),new r("mi",-1,-1),new r("si",-1,-1),new r("ti",-1,-1),new r("vi",-1,-1),new r("lo",-1,-1),new r("celo",31,-1),new r("glielo",31,-1),new r("melo",31,-1),new r("telo",31,-1),new r("velo",31,-1)],z=[new r("ando",-1,1),new r("endo",-1,1),new r("ar",-1,2),new r("er",-1,2),new r("ir",-1,2)],P=[new r("ic",-1,-1),new r("abil",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],F=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],S=[new r("ica",-1,1),new r("logia",-1,3),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,9),new r("anza",-1,1),new r("enza",-1,5),new r("ice",-1,1),new r("atrice",7,1),new r("iche",-1,1),new r("logie",-1,3),new r("abile",-1,1),new r("ibile",-1,1),new r("usione",-1,4),new r("azione",-1,2),new r("uzione",-1,4),new r("atore",-1,2),new r("ose",-1,1),new r("ante",-1,1),new r("mente",-1,1),new r("amente",19,7),new r("iste",-1,1),new r("ive",-1,9),new r("anze",-1,1),new r("enze",-1,5),new r("ici",-1,1),new r("atrici",25,1),new r("ichi",-1,1),new r("abili",-1,1),new r("ibili",-1,1),new r("ismi",-1,1),new r("usioni",-1,4),new r("azioni",-1,2),new r("uzioni",-1,4),new r("atori",-1,2),new r("osi",-1,1),new r("anti",-1,1),new r("amenti",-1,6),new r("imenti",-1,6),new r("isti",-1,1),new r("ivi",-1,9),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,6),new r("imento",-1,6),new r("ivo",-1,9),new r("ità",-1,8),new r("istà",-1,1),new r("istè",-1,1),new r("istì",-1,1)],W=[new r("isca",-1,1),new r("enda",-1,1),new r("ata",-1,1),new r("ita",-1,1),new r("uta",-1,1),new r("ava",-1,1),new r("eva",-1,1),new r("iva",-1,1),new r("erebbe",-1,1),new r("irebbe",-1,1),new r("isce",-1,1),new r("ende",-1,1),new r("are",-1,1),new r("ere",-1,1),new r("ire",-1,1),new r("asse",-1,1),new r("ate",-1,1),new r("avate",16,1),new r("evate",16,1),new r("ivate",16,1),new r("ete",-1,1),new r("erete",20,1),new r("irete",20,1),new r("ite",-1,1),new r("ereste",-1,1),new r("ireste",-1,1),new r("ute",-1,1),new r("erai",-1,1),new r("irai",-1,1),new r("isci",-1,1),new r("endi",-1,1),new r("erei",-1,1),new r("irei",-1,1),new r("assi",-1,1),new r("ati",-1,1),new r("iti",-1,1),new r("eresti",-1,1),new r("iresti",-1,1),new r("uti",-1,1),new r("avi",-1,1),new r("evi",-1,1),new r("ivi",-1,1),new r("isco",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("Yamo",-1,1),new r("iamo",-1,1),new r("avamo",-1,1),new r("evamo",-1,1),new r("ivamo",-1,1),new r("eremo",-1,1),new r("iremo",-1,1),new r("assimo",-1,1),new r("ammo",-1,1),new r("emmo",-1,1),new r("eremmo",54,1),new r("iremmo",54,1),new r("immo",-1,1),new r("ano",-1,1),new r("iscano",58,1),new r("avano",58,1),new r("evano",58,1),new r("ivano",58,1),new r("eranno",-1,1),new r("iranno",-1,1),new r("ono",-1,1),new r("iscono",65,1),new r("arono",65,1),new r("erono",65,1),new r("irono",65,1),new r("erebbero",-1,1),new r("irebbero",-1,1),new r("assero",-1,1),new r("essero",-1,1),new r("issero",-1,1),new r("ato",-1,1),new r("ito",-1,1),new r("uto",-1,1),new r("avo",-1,1),new r("evo",-1,1),new r("ivo",-1,1),new r("ar",-1,1),new r("ir",-1,1),new r("erà",-1,1),new r("irà",-1,1),new r("erò",-1,1),new r("irò",-1,1)],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],y=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],U=[17],x=new n;this.setCurrent=function(e){x.setCurrent(e)},this.getCurrent=function(){return x.getCurrent()},this.stem=function(){var e=x.cursor;return i(),x.cursor=e,u(),x.limit_backward=e,x.cursor=x.limit,f(),x.cursor=x.limit,v()||(x.cursor=x.limit,b()),x.cursor=x.limit,_(),x.cursor=x.limit_backward,c(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ja.min.js b/assets/javascripts/lunr/min/lunr.ja.min.js new file mode 100644 index 00000000..5f254ebe --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ja.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.no.min.js b/assets/javascripts/lunr/min/lunr.no.min.js new file mode 100644 index 00000000..92bc7e4e --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.no.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Norwegian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.pt.min.js b/assets/javascripts/lunr/min/lunr.pt.min.js new file mode 100644 index 00000000..6c16996d --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.pt.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Portuguese` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ro.min.js b/assets/javascripts/lunr/min/lunr.ro.min.js new file mode 100644 index 00000000..72771401 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ro.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Romanian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=function(){var i=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(e,i){L.eq_s(1,e)&&(L.ket=L.cursor,L.in_grouping(W,97,259)&&L.slice_from(i))}function n(){for(var i,r;;){if(i=L.cursor,L.in_grouping(W,97,259)&&(r=L.cursor,L.bra=r,e("u","U"),L.cursor=r,e("i","I")),L.cursor=i,L.cursor>=L.limit)break;L.cursor++}}function t(){if(L.out_grouping(W,97,259)){for(;!L.in_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}return!0}function a(){if(L.in_grouping(W,97,259))for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}function o(){var e,i,r=L.cursor;if(L.in_grouping(W,97,259)){if(e=L.cursor,!t())return void(h=L.cursor);if(L.cursor=e,!a())return void(h=L.cursor)}L.cursor=r,L.out_grouping(W,97,259)&&(i=L.cursor,t()&&(L.cursor=i,L.in_grouping(W,97,259)&&L.cursor=L.limit)return!1;L.cursor++}for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!1;L.cursor++}return!0}function c(){var e=L.cursor;h=L.limit,k=h,g=h,o(),L.cursor=e,u()&&(k=L.cursor,u()&&(g=L.cursor))}function s(){for(var e;;){if(L.bra=L.cursor,e=L.find_among(z,3))switch(L.ket=L.cursor,e){case 1:L.slice_from("i");continue;case 2:L.slice_from("u");continue;case 3:if(L.cursor>=L.limit)break;L.cursor++;continue}break}}function w(){return h<=L.cursor}function m(){return k<=L.cursor}function l(){return g<=L.cursor}function f(){var e,i;if(L.ket=L.cursor,(e=L.find_among_b(C,16))&&(L.bra=L.cursor,m()))switch(e){case 1:L.slice_del();break;case 2:L.slice_from("a");break;case 3:L.slice_from("e");break;case 4:L.slice_from("i");break;case 5:i=L.limit-L.cursor,L.eq_s_b(2,"ab")||(L.cursor=L.limit-i,L.slice_from("i"));break;case 6:L.slice_from("at");break;case 7:L.slice_from("aţi")}}function p(){var e,i=L.limit-L.cursor;if(L.ket=L.cursor,(e=L.find_among_b(P,46))&&(L.bra=L.cursor,m())){switch(e){case 1:L.slice_from("abil");break;case 2:L.slice_from("ibil");break;case 3:L.slice_from("iv");break;case 4:L.slice_from("ic");break;case 5:L.slice_from("at");break;case 6:L.slice_from("it")}return _=!0,L.cursor=L.limit-i,!0}return!1}function d(){var e,i;for(_=!1;;)if(i=L.limit-L.cursor,!p()){L.cursor=L.limit-i;break}if(L.ket=L.cursor,(e=L.find_among_b(F,62))&&(L.bra=L.cursor,l())){switch(e){case 1:L.slice_del();break;case 2:L.eq_s_b(1,"ţ")&&(L.bra=L.cursor,L.slice_from("t"));break;case 3:L.slice_from("ist")}_=!0}}function b(){var e,i,r;if(L.cursor>=h){if(i=L.limit_backward,L.limit_backward=h,L.ket=L.cursor,e=L.find_among_b(q,94))switch(L.bra=L.cursor,e){case 1:if(r=L.limit-L.cursor,!L.out_grouping_b(W,97,259)&&(L.cursor=L.limit-r,!L.eq_s_b(1,"u")))break;case 2:L.slice_del()}L.limit_backward=i}}function v(){var e;L.ket=L.cursor,(e=L.find_among_b(S,5))&&(L.bra=L.cursor,w()&&1==e&&L.slice_del())}var _,g,k,h,z=[new i("",-1,3),new i("I",0,1),new i("U",0,2)],C=[new i("ea",-1,3),new i("aţia",-1,7),new i("aua",-1,2),new i("iua",-1,4),new i("aţie",-1,7),new i("ele",-1,3),new i("ile",-1,5),new i("iile",6,4),new i("iei",-1,4),new i("atei",-1,6),new i("ii",-1,4),new i("ului",-1,1),new i("ul",-1,1),new i("elor",-1,3),new i("ilor",-1,4),new i("iilor",14,4)],P=[new i("icala",-1,4),new i("iciva",-1,4),new i("ativa",-1,5),new i("itiva",-1,6),new i("icale",-1,4),new i("aţiune",-1,5),new i("iţiune",-1,6),new i("atoare",-1,5),new i("itoare",-1,6),new i("ătoare",-1,5),new i("icitate",-1,4),new i("abilitate",-1,1),new i("ibilitate",-1,2),new i("ivitate",-1,3),new i("icive",-1,4),new i("ative",-1,5),new i("itive",-1,6),new i("icali",-1,4),new i("atori",-1,5),new i("icatori",18,4),new i("itori",-1,6),new i("ători",-1,5),new i("icitati",-1,4),new i("abilitati",-1,1),new i("ivitati",-1,3),new i("icivi",-1,4),new i("ativi",-1,5),new i("itivi",-1,6),new i("icităi",-1,4),new i("abilităi",-1,1),new i("ivităi",-1,3),new i("icităţi",-1,4),new i("abilităţi",-1,1),new i("ivităţi",-1,3),new i("ical",-1,4),new i("ator",-1,5),new i("icator",35,4),new i("itor",-1,6),new i("ător",-1,5),new i("iciv",-1,4),new i("ativ",-1,5),new i("itiv",-1,6),new i("icală",-1,4),new i("icivă",-1,4),new i("ativă",-1,5),new i("itivă",-1,6)],F=[new i("ica",-1,1),new i("abila",-1,1),new i("ibila",-1,1),new i("oasa",-1,1),new i("ata",-1,1),new i("ita",-1,1),new i("anta",-1,1),new i("ista",-1,3),new i("uta",-1,1),new i("iva",-1,1),new i("ic",-1,1),new i("ice",-1,1),new i("abile",-1,1),new i("ibile",-1,1),new i("isme",-1,3),new i("iune",-1,2),new i("oase",-1,1),new i("ate",-1,1),new i("itate",17,1),new i("ite",-1,1),new i("ante",-1,1),new i("iste",-1,3),new i("ute",-1,1),new i("ive",-1,1),new i("ici",-1,1),new i("abili",-1,1),new i("ibili",-1,1),new i("iuni",-1,2),new i("atori",-1,1),new i("osi",-1,1),new i("ati",-1,1),new i("itati",30,1),new i("iti",-1,1),new i("anti",-1,1),new i("isti",-1,3),new i("uti",-1,1),new i("işti",-1,3),new i("ivi",-1,1),new i("ităi",-1,1),new i("oşi",-1,1),new i("ităţi",-1,1),new i("abil",-1,1),new i("ibil",-1,1),new i("ism",-1,3),new i("ator",-1,1),new i("os",-1,1),new i("at",-1,1),new i("it",-1,1),new i("ant",-1,1),new i("ist",-1,3),new i("ut",-1,1),new i("iv",-1,1),new i("ică",-1,1),new i("abilă",-1,1),new i("ibilă",-1,1),new i("oasă",-1,1),new i("ată",-1,1),new i("ită",-1,1),new i("antă",-1,1),new i("istă",-1,3),new i("ută",-1,1),new i("ivă",-1,1)],q=[new i("ea",-1,1),new i("ia",-1,1),new i("esc",-1,1),new i("ăsc",-1,1),new i("ind",-1,1),new i("ând",-1,1),new i("are",-1,1),new i("ere",-1,1),new i("ire",-1,1),new i("âre",-1,1),new i("se",-1,2),new i("ase",10,1),new i("sese",10,2),new i("ise",10,1),new i("use",10,1),new i("âse",10,1),new i("eşte",-1,1),new i("ăşte",-1,1),new i("eze",-1,1),new i("ai",-1,1),new i("eai",19,1),new i("iai",19,1),new i("sei",-1,2),new i("eşti",-1,1),new i("ăşti",-1,1),new i("ui",-1,1),new i("ezi",-1,1),new i("âi",-1,1),new i("aşi",-1,1),new i("seşi",-1,2),new i("aseşi",29,1),new i("seseşi",29,2),new i("iseşi",29,1),new i("useşi",29,1),new i("âseşi",29,1),new i("işi",-1,1),new i("uşi",-1,1),new i("âşi",-1,1),new i("aţi",-1,2),new i("eaţi",38,1),new i("iaţi",38,1),new i("eţi",-1,2),new i("iţi",-1,2),new i("âţi",-1,2),new i("arăţi",-1,1),new i("serăţi",-1,2),new i("aserăţi",45,1),new i("seserăţi",45,2),new i("iserăţi",45,1),new i("userăţi",45,1),new i("âserăţi",45,1),new i("irăţi",-1,1),new i("urăţi",-1,1),new i("ârăţi",-1,1),new i("am",-1,1),new i("eam",54,1),new i("iam",54,1),new i("em",-1,2),new i("asem",57,1),new i("sesem",57,2),new i("isem",57,1),new i("usem",57,1),new i("âsem",57,1),new i("im",-1,2),new i("âm",-1,2),new i("ăm",-1,2),new i("arăm",65,1),new i("serăm",65,2),new i("aserăm",67,1),new i("seserăm",67,2),new i("iserăm",67,1),new i("userăm",67,1),new i("âserăm",67,1),new i("irăm",65,1),new i("urăm",65,1),new i("ârăm",65,1),new i("au",-1,1),new i("eau",76,1),new i("iau",76,1),new i("indu",-1,1),new i("ându",-1,1),new i("ez",-1,1),new i("ească",-1,1),new i("ară",-1,1),new i("seră",-1,2),new i("aseră",84,1),new i("seseră",84,2),new i("iseră",84,1),new i("useră",84,1),new i("âseră",84,1),new i("iră",-1,1),new i("ură",-1,1),new i("âră",-1,1),new i("ează",-1,1)],S=[new i("a",-1,1),new i("e",-1,1),new i("ie",1,1),new i("i",-1,1),new i("ă",-1,1)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var e=L.cursor;return n(),L.cursor=e,c(),L.limit_backward=e,L.cursor=L.limit,f(),L.cursor=L.limit,d(),L.cursor=L.limit,_||(L.cursor=L.limit,b(),L.cursor=L.limit),v(),L.cursor=L.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.ru.min.js b/assets/javascripts/lunr/min/lunr.ru.min.js new file mode 100644 index 00000000..186cc485 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.ru.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Russian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.sv.min.js b/assets/javascripts/lunr/min/lunr.sv.min.js new file mode 100644 index 00000000..3e5eb640 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.sv.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Swedish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.th.min.js b/assets/javascripts/lunr/min/lunr.th.min.js new file mode 100644 index 00000000..dee3aac6 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.th.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.tr.min.js b/assets/javascripts/lunr/min/lunr.tr.min.js new file mode 100644 index 00000000..563f6ec1 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.tr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Turkish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=function(){var i=r.stemmerSupport.Among,e=r.stemmerSupport.SnowballProgram,n=new function(){function r(r,i,e){for(;;){var n=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(r,i,e)){Dr.cursor=Dr.limit-n;break}if(Dr.cursor=Dr.limit-n,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function n(){var i,e;i=Dr.limit-Dr.cursor,r(Wr,97,305);for(var n=0;nDr.limit_backward&&(Dr.cursor--,e=Dr.limit-Dr.cursor,i()))?(Dr.cursor=Dr.limit-e,!0):(Dr.cursor=Dr.limit-n,r()?(Dr.cursor=Dr.limit-n,!1):(Dr.cursor=Dr.limit-n,!(Dr.cursor<=Dr.limit_backward)&&(Dr.cursor--,!!i()&&(Dr.cursor=Dr.limit-n,!0))))}function u(r){return t(r,function(){return Dr.in_grouping_b(Wr,97,305)})}function o(){return u(function(){return Dr.eq_s_b(1,"n")})}function s(){return u(function(){return Dr.eq_s_b(1,"s")})}function c(){return u(function(){return Dr.eq_s_b(1,"y")})}function l(){return t(function(){return Dr.in_grouping_b(Lr,105,305)},function(){return Dr.out_grouping_b(Wr,97,305)})}function a(){return Dr.find_among_b(ur,10)&&l()}function m(){return n()&&Dr.in_grouping_b(Lr,105,305)&&s()}function d(){return Dr.find_among_b(or,2)}function f(){return n()&&Dr.in_grouping_b(Lr,105,305)&&c()}function b(){return n()&&Dr.find_among_b(sr,4)}function w(){return n()&&Dr.find_among_b(cr,4)&&o()}function _(){return n()&&Dr.find_among_b(lr,2)&&c()}function k(){return n()&&Dr.find_among_b(ar,2)}function p(){return n()&&Dr.find_among_b(mr,4)}function g(){return n()&&Dr.find_among_b(dr,2)}function y(){return n()&&Dr.find_among_b(fr,4)}function z(){return n()&&Dr.find_among_b(br,2)}function v(){return n()&&Dr.find_among_b(wr,2)&&c()}function h(){return Dr.eq_s_b(2,"ki")}function q(){return n()&&Dr.find_among_b(_r,2)&&o()}function C(){return n()&&Dr.find_among_b(kr,4)&&c()}function P(){return n()&&Dr.find_among_b(pr,4)}function F(){return n()&&Dr.find_among_b(gr,4)&&c()}function S(){return Dr.find_among_b(yr,4)}function W(){return n()&&Dr.find_among_b(zr,2)}function L(){return n()&&Dr.find_among_b(vr,4)}function x(){return n()&&Dr.find_among_b(hr,8)}function A(){return Dr.find_among_b(qr,2)}function E(){return n()&&Dr.find_among_b(Cr,32)&&c()}function j(){return Dr.find_among_b(Pr,8)&&c()}function T(){return n()&&Dr.find_among_b(Fr,4)&&c()}function Z(){return Dr.eq_s_b(3,"ken")&&c()}function B(){var r=Dr.limit-Dr.cursor;return!(T()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,Z()))))}function D(){if(A()){var r=Dr.limit-Dr.cursor;if(S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T())return!1}return!0}function G(){if(W()){Dr.bra=Dr.cursor,Dr.slice_del();var r=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,x()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,T()||(Dr.cursor=Dr.limit-r)))),nr=!1,!1}return!0}function H(){if(!L())return!0;var r=Dr.limit-Dr.cursor;return!E()&&(Dr.cursor=Dr.limit-r,!j())}function I(){var r,i=Dr.limit-Dr.cursor;return!(S()||(Dr.cursor=Dr.limit-i,F()||(Dr.cursor=Dr.limit-i,P()||(Dr.cursor=Dr.limit-i,C()))))||(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,T()||(Dr.cursor=Dr.limit-r),!1)}function J(){var r,i=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,nr=!0,B()&&(Dr.cursor=Dr.limit-i,D()&&(Dr.cursor=Dr.limit-i,G()&&(Dr.cursor=Dr.limit-i,H()&&(Dr.cursor=Dr.limit-i,I()))))){if(Dr.cursor=Dr.limit-i,!x())return;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T()||(Dr.cursor=Dr.limit-r)}Dr.bra=Dr.cursor,Dr.slice_del()}function K(){var r,i,e,n;if(Dr.ket=Dr.cursor,h()){if(r=Dr.limit-Dr.cursor,p())return Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,a()&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))),!0;if(Dr.cursor=Dr.limit-r,w()){if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,e=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-e,!m()&&(Dr.cursor=Dr.limit-e,!K())))return!0;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}return!0}if(Dr.cursor=Dr.limit-r,g()){if(n=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-n,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-n,!K())return!1;return!0}}return!1}function M(r){if(Dr.ket=Dr.cursor,!g()&&(Dr.cursor=Dr.limit-r,!k()))return!1;var i=Dr.limit-Dr.cursor;if(d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-i,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-i,!K())return!1;return!0}function N(r){if(Dr.ket=Dr.cursor,!z()&&(Dr.cursor=Dr.limit-r,!b()))return!1;var i=Dr.limit-Dr.cursor;return!(!m()&&(Dr.cursor=Dr.limit-i,!d()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)}function O(){var r,i=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,!(!w()&&(Dr.cursor=Dr.limit-i,!v()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,!(!W()||(Dr.bra=Dr.cursor,Dr.slice_del(),!K()))||(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!(a()||(Dr.cursor=Dr.limit-r,m()||(Dr.cursor=Dr.limit-r,K())))||(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)))}function Q(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,!p()&&(Dr.cursor=Dr.limit-e,!f()&&(Dr.cursor=Dr.limit-e,!_())))return!1;if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,a())Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()||(Dr.cursor=Dr.limit-i);else if(Dr.cursor=Dr.limit-r,!W())return!0;return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,K(),!0}function R(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,W())return Dr.bra=Dr.cursor,Dr.slice_del(),void K();if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,q())if(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-r,!m())){if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!W())return;if(Dr.bra=Dr.cursor,Dr.slice_del(),!K())return}Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}else if(Dr.cursor=Dr.limit-e,!M(e)&&(Dr.cursor=Dr.limit-e,!N(e))){if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,y())return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,i=Dr.limit-Dr.cursor,void(a()?(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())):(Dr.cursor=Dr.limit-i,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,K())));if(Dr.cursor=Dr.limit-e,!O()){if(Dr.cursor=Dr.limit-e,d())return Dr.bra=Dr.cursor,void Dr.slice_del();Dr.cursor=Dr.limit-e,K()||(Dr.cursor=Dr.limit-e,Q()||(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,(a()||(Dr.cursor=Dr.limit-e,m()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))))}}}function U(){var r;if(Dr.ket=Dr.cursor,r=Dr.find_among_b(Sr,4))switch(Dr.bra=Dr.cursor,r){case 1:Dr.slice_from("p");break;case 2:Dr.slice_from("ç");break;case 3:Dr.slice_from("t");break;case 4:Dr.slice_from("k")}}function V(){for(;;){var r=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(Wr,97,305)){Dr.cursor=Dr.limit-r;break}if(Dr.cursor=Dr.limit-r,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function X(r,i,e){if(Dr.cursor=Dr.limit-r,V()){var n=Dr.limit-Dr.cursor;if(!Dr.eq_s_b(1,i)&&(Dr.cursor=Dr.limit-n,!Dr.eq_s_b(1,e)))return!0;Dr.cursor=Dr.limit-r;var t=Dr.cursor;return Dr.insert(Dr.cursor,Dr.cursor,e),Dr.cursor=t,!1}return!0}function Y(){var r=Dr.limit-Dr.cursor;(Dr.eq_s_b(1,"d")||(Dr.cursor=Dr.limit-r,Dr.eq_s_b(1,"g")))&&X(r,"a","ı")&&X(r,"e","i")&&X(r,"o","u")&&X(r,"ö","ü")}function $(){for(var r,i=Dr.cursor,e=2;;){for(r=Dr.cursor;!Dr.in_grouping(Wr,97,305);){if(Dr.cursor>=Dr.limit)return Dr.cursor=r,!(e>0)&&(Dr.cursor=i,!0);Dr.cursor++}e--}}function rr(r,i,e){for(;!Dr.eq_s(i,e);){if(Dr.cursor>=Dr.limit)return!0;Dr.cursor++}return(tr=i)!=Dr.limit||(Dr.cursor=r,!1)}function ir(){var r=Dr.cursor;return!rr(r,2,"ad")||(Dr.cursor=r,!rr(r,5,"soyad"))}function er(){var r=Dr.cursor;return!ir()&&(Dr.limit_backward=r,Dr.cursor=Dr.limit,Y(),Dr.cursor=Dr.limit,U(),!0)}var nr,tr,ur=[new i("m",-1,-1),new i("n",-1,-1),new i("miz",-1,-1),new i("niz",-1,-1),new i("muz",-1,-1),new i("nuz",-1,-1),new i("müz",-1,-1),new i("nüz",-1,-1),new i("mız",-1,-1),new i("nız",-1,-1)],or=[new i("leri",-1,-1),new i("ları",-1,-1)],sr=[new i("ni",-1,-1),new i("nu",-1,-1),new i("nü",-1,-1),new i("nı",-1,-1)],cr=[new i("in",-1,-1),new i("un",-1,-1),new i("ün",-1,-1),new i("ın",-1,-1)],lr=[new i("a",-1,-1),new i("e",-1,-1)],ar=[new i("na",-1,-1),new i("ne",-1,-1)],mr=[new i("da",-1,-1),new i("ta",-1,-1),new i("de",-1,-1),new i("te",-1,-1)],dr=[new i("nda",-1,-1),new i("nde",-1,-1)],fr=[new i("dan",-1,-1),new i("tan",-1,-1),new i("den",-1,-1),new i("ten",-1,-1)],br=[new i("ndan",-1,-1),new i("nden",-1,-1)],wr=[new i("la",-1,-1),new i("le",-1,-1)],_r=[new i("ca",-1,-1),new i("ce",-1,-1)],kr=[new i("im",-1,-1),new i("um",-1,-1),new i("üm",-1,-1),new i("ım",-1,-1)],pr=[new i("sin",-1,-1),new i("sun",-1,-1),new i("sün",-1,-1),new i("sın",-1,-1)],gr=[new i("iz",-1,-1),new i("uz",-1,-1),new i("üz",-1,-1),new i("ız",-1,-1)],yr=[new i("siniz",-1,-1),new i("sunuz",-1,-1),new i("sünüz",-1,-1),new i("sınız",-1,-1)],zr=[new i("lar",-1,-1),new i("ler",-1,-1)],vr=[new i("niz",-1,-1),new i("nuz",-1,-1),new i("nüz",-1,-1),new i("nız",-1,-1)],hr=[new i("dir",-1,-1),new i("tir",-1,-1),new i("dur",-1,-1),new i("tur",-1,-1),new i("dür",-1,-1),new i("tür",-1,-1),new i("dır",-1,-1),new i("tır",-1,-1)],qr=[new i("casına",-1,-1),new i("cesine",-1,-1)],Cr=[new i("di",-1,-1),new i("ti",-1,-1),new i("dik",-1,-1),new i("tik",-1,-1),new i("duk",-1,-1),new i("tuk",-1,-1),new i("dük",-1,-1),new i("tük",-1,-1),new i("dık",-1,-1),new i("tık",-1,-1),new i("dim",-1,-1),new i("tim",-1,-1),new i("dum",-1,-1),new i("tum",-1,-1),new i("düm",-1,-1),new i("tüm",-1,-1),new i("dım",-1,-1),new i("tım",-1,-1),new i("din",-1,-1),new i("tin",-1,-1),new i("dun",-1,-1),new i("tun",-1,-1),new i("dün",-1,-1),new i("tün",-1,-1),new i("dın",-1,-1),new i("tın",-1,-1),new i("du",-1,-1),new i("tu",-1,-1),new i("dü",-1,-1),new i("tü",-1,-1),new i("dı",-1,-1),new i("tı",-1,-1)],Pr=[new i("sa",-1,-1),new i("se",-1,-1),new i("sak",-1,-1),new i("sek",-1,-1),new i("sam",-1,-1),new i("sem",-1,-1),new i("san",-1,-1),new i("sen",-1,-1)],Fr=[new i("miş",-1,-1),new i("muş",-1,-1),new i("müş",-1,-1),new i("mış",-1,-1)],Sr=[new i("b",-1,1),new i("c",-1,2),new i("d",-1,3),new i("ğ",-1,4)],Wr=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],Lr=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],xr=[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],Ar=[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],Er=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],jr=[17],Tr=[65],Zr=[65],Br=[["a",xr,97,305],["e",Ar,101,252],["ı",Er,97,305],["i",jr,101,105],["o",Tr,111,117],["ö",Zr,246,252],["u",Tr,111,117]],Dr=new e;this.setCurrent=function(r){Dr.setCurrent(r)},this.getCurrent=function(){return Dr.getCurrent()},this.stem=function(){return!!($()&&(Dr.limit_backward=Dr.cursor,Dr.cursor=Dr.limit,J(),Dr.cursor=Dr.limit,nr&&(R(),Dr.cursor=Dr.limit_backward,er())))}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.tr.stemmer,"stemmer-tr"),r.tr.stopWordFilter=r.generateStopWordFilter("acaba altmış altı ama ancak arada aslında ayrıca bana bazı belki ben benden beni benim beri beş bile bin bir biri birkaç birkez birçok birşey birşeyi biz bizden bize bizi bizim bu buna bunda bundan bunlar bunları bunların bunu bunun burada böyle böylece da daha dahi de defa değil diye diğer doksan dokuz dolayı dolayısıyla dört edecek eden ederek edilecek ediliyor edilmesi ediyor elli en etmesi etti ettiği ettiğini eğer gibi göre halen hangi hatta hem henüz hep hepsi her herhangi herkesin hiç hiçbir iki ile ilgili ise itibaren itibariyle için işte kadar karşın katrilyon kendi kendilerine kendini kendisi kendisine kendisini kez ki kim kimden kime kimi kimse kırk milyar milyon mu mü mı nasıl ne neden nedenle nerde nerede nereye niye niçin o olan olarak oldu olduklarını olduğu olduğunu olmadı olmadığı olmak olması olmayan olmaz olsa olsun olup olur olursa oluyor on ona ondan onlar onlardan onları onların onu onun otuz oysa pek rağmen sadece sanki sekiz seksen sen senden seni senin siz sizden sizi sizin tarafından trilyon tüm var vardı ve veya ya yani yapacak yapmak yaptı yaptıkları yaptığı yaptığını yapılan yapılması yapıyor yedi yerine yetmiş yine yirmi yoksa yüz zaten çok çünkü öyle üzere üç şey şeyden şeyi şeyler şu şuna şunda şundan şunları şunu şöyle".split(" ")),r.Pipeline.registerFunction(r.tr.stopWordFilter,"stopWordFilter-tr")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.vi.min.js b/assets/javascripts/lunr/min/lunr.vi.min.js new file mode 100644 index 00000000..22aed28c --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.vi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/min/lunr.zh.min.js b/assets/javascripts/lunr/min/lunr.zh.min.js new file mode 100644 index 00000000..7727bbe2 --- /dev/null +++ b/assets/javascripts/lunr/min/lunr.zh.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("nodejieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}}); \ No newline at end of file diff --git a/assets/javascripts/lunr/tinyseg.js b/assets/javascripts/lunr/tinyseg.js new file mode 100644 index 00000000..167fa6dd --- /dev/null +++ b/assets/javascripts/lunr/tinyseg.js @@ -0,0 +1,206 @@ +/** + * export the module via AMD, CommonJS or as a browser global + * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js + */ +;(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory) + } else if (typeof exports === 'object') { + /** + * Node. Does not work with strict CommonJS, but + * only CommonJS-like environments that support module.exports, + * like Node. + */ + module.exports = factory() + } else { + // Browser globals (root is window) + factory()(root.lunr); + } +}(this, function () { + /** + * Just return a value to define the module export. + * This example returns an object, but the module + * can return a function as the exported value. + */ + + return function(lunr) { + // TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript + // (c) 2008 Taku Kudo + // TinySegmenter is freely distributable under the terms of a new BSD licence. + // For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt + + function TinySegmenter() { + var patterns = { + "[一二三四五六七八九十百千万億兆]":"M", + "[一-龠々〆ヵヶ]":"H", + "[ぁ-ん]":"I", + "[ァ-ヴーア-ン゙ー]":"K", + "[a-zA-Za-zA-Z]":"A", + "[0-90-9]":"N" + } + this.chartype_ = []; + for (var i in patterns) { + var regexp = new RegExp(i); + this.chartype_.push([regexp, patterns[i]]); + } + + this.BIAS__ = -332 + this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378}; + this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920}; + this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266}; + this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352}; + this.BP2__ = {"BO":60,"OO":-1762}; + this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965}; + this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146}; + this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699}; + this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973}; + this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682}; + this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669}; + this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990}; + this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832}; + this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649}; + this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393}; + this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841}; + this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68}; + this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591}; + this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685}; + this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156}; + this.TW1__ = {"につい":-4681,"東京都":2026}; + this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216}; + this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287}; + this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865}; + this.UC1__ = {"A":484,"K":93,"M":645,"O":-505}; + this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646}; + this.UC3__ = {"A":-1370,"I":2311}; + this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646}; + this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831}; + this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387}; + this.UP1__ = {"O":-214}; + this.UP2__ = {"B":69,"O":935}; + this.UP3__ = {"B":189}; + this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422}; + this.UQ2__ = {"BH":216,"BI":113,"OK":1759}; + this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212}; + this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135}; + this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568}; + this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278}; + this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637}; + this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343}; + this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496}; + + return this; + } + TinySegmenter.prototype.ctype_ = function(str) { + for (var i in this.chartype_) { + if (str.match(this.chartype_[i][0])) { + return this.chartype_[i][1]; + } + } + return "O"; + } + + TinySegmenter.prototype.ts_ = function(v) { + if (v) { return v; } + return 0; + } + + TinySegmenter.prototype.segment = function(input) { + if (input == null || input == undefined || input == "") { + return []; + } + var result = []; + var seg = ["B3","B2","B1"]; + var ctype = ["O","O","O"]; + var o = input.split(""); + for (i = 0; i < o.length; ++i) { + seg.push(o[i]); + ctype.push(this.ctype_(o[i])) + } + seg.push("E1"); + seg.push("E2"); + seg.push("E3"); + ctype.push("O"); + ctype.push("O"); + ctype.push("O"); + var word = seg[3]; + var p1 = "U"; + var p2 = "U"; + var p3 = "U"; + for (var i = 4; i < seg.length - 3; ++i) { + var score = this.BIAS__; + var w1 = seg[i-3]; + var w2 = seg[i-2]; + var w3 = seg[i-1]; + var w4 = seg[i]; + var w5 = seg[i+1]; + var w6 = seg[i+2]; + var c1 = ctype[i-3]; + var c2 = ctype[i-2]; + var c3 = ctype[i-1]; + var c4 = ctype[i]; + var c5 = ctype[i+1]; + var c6 = ctype[i+2]; + score += this.ts_(this.UP1__[p1]); + score += this.ts_(this.UP2__[p2]); + score += this.ts_(this.UP3__[p3]); + score += this.ts_(this.BP1__[p1 + p2]); + score += this.ts_(this.BP2__[p2 + p3]); + score += this.ts_(this.UW1__[w1]); + score += this.ts_(this.UW2__[w2]); + score += this.ts_(this.UW3__[w3]); + score += this.ts_(this.UW4__[w4]); + score += this.ts_(this.UW5__[w5]); + score += this.ts_(this.UW6__[w6]); + score += this.ts_(this.BW1__[w2 + w3]); + score += this.ts_(this.BW2__[w3 + w4]); + score += this.ts_(this.BW3__[w4 + w5]); + score += this.ts_(this.TW1__[w1 + w2 + w3]); + score += this.ts_(this.TW2__[w2 + w3 + w4]); + score += this.ts_(this.TW3__[w3 + w4 + w5]); + score += this.ts_(this.TW4__[w4 + w5 + w6]); + score += this.ts_(this.UC1__[c1]); + score += this.ts_(this.UC2__[c2]); + score += this.ts_(this.UC3__[c3]); + score += this.ts_(this.UC4__[c4]); + score += this.ts_(this.UC5__[c5]); + score += this.ts_(this.UC6__[c6]); + score += this.ts_(this.BC1__[c2 + c3]); + score += this.ts_(this.BC2__[c3 + c4]); + score += this.ts_(this.BC3__[c4 + c5]); + score += this.ts_(this.TC1__[c1 + c2 + c3]); + score += this.ts_(this.TC2__[c2 + c3 + c4]); + score += this.ts_(this.TC3__[c3 + c4 + c5]); + score += this.ts_(this.TC4__[c4 + c5 + c6]); + // score += this.ts_(this.TC5__[c4 + c5 + c6]); + score += this.ts_(this.UQ1__[p1 + c1]); + score += this.ts_(this.UQ2__[p2 + c2]); + score += this.ts_(this.UQ3__[p3 + c3]); + score += this.ts_(this.BQ1__[p2 + c2 + c3]); + score += this.ts_(this.BQ2__[p2 + c3 + c4]); + score += this.ts_(this.BQ3__[p3 + c2 + c3]); + score += this.ts_(this.BQ4__[p3 + c3 + c4]); + score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]); + score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]); + score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]); + score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]); + var p = "O"; + if (score > 0) { + result.push(word); + word = ""; + p = "B"; + } + p1 = p2; + p2 = p3; + p3 = p; + word += seg[i]; + } + result.push(word); + + return result; + } + + lunr.TinySegmenter = TinySegmenter; + }; + +})); \ No newline at end of file diff --git a/assets/javascripts/lunr/wordcut.js b/assets/javascripts/lunr/wordcut.js new file mode 100644 index 00000000..146f4b44 --- /dev/null +++ b/assets/javascripts/lunr/wordcut.js @@ -0,0 +1,6708 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.lunr || (g.lunr = {})).wordcut = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1; + }) + this.addWords(words, false) + } + if(finalize){ + this.finalizeDict(); + } + }, + + dictSeek: function (l, r, ch, strOffset, pos) { + var ans = null; + while (l <= r) { + var m = Math.floor((l + r) / 2), + dict_item = this.dict[m], + len = dict_item.length; + if (len <= strOffset) { + l = m + 1; + } else { + var ch_ = dict_item[strOffset]; + if (ch_ < ch) { + l = m + 1; + } else if (ch_ > ch) { + r = m - 1; + } else { + ans = m; + if (pos == LEFT) { + r = m - 1; + } else { + l = m + 1; + } + } + } + } + return ans; + }, + + isFinal: function (acceptor) { + return this.dict[acceptor.l].length == acceptor.strOffset; + }, + + createAcceptor: function () { + return { + l: 0, + r: this.dict.length - 1, + strOffset: 0, + isFinal: false, + dict: this, + transit: function (ch) { + return this.dict.transit(this, ch); + }, + isError: false, + tag: "DICT", + w: 1, + type: "DICT" + }; + }, + + transit: function (acceptor, ch) { + var l = this.dictSeek(acceptor.l, + acceptor.r, + ch, + acceptor.strOffset, + LEFT); + if (l !== null) { + var r = this.dictSeek(l, + acceptor.r, + ch, + acceptor.strOffset, + RIGHT); + acceptor.l = l; + acceptor.r = r; + acceptor.strOffset++; + acceptor.isFinal = this.isFinal(acceptor); + } else { + acceptor.isError = true; + } + return acceptor; + }, + + sortuniq: function(a){ + return a.sort().filter(function(item, pos, arr){ + return !pos || item != arr[pos - 1]; + }) + }, + + flatten: function(a){ + //[[1,2],[3]] -> [1,2,3] + return [].concat.apply([], a); + } +}; +module.exports = WordcutDict; + +}).call(this,"/dist/tmp") +},{"glob":16,"path":22}],3:[function(require,module,exports){ +var WordRule = { + createAcceptor: function(tag) { + if (tag["WORD_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + var lch = ch.toLowerCase(); + if (lch >= "a" && lch <= "z") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "WORD_RULE", + type: "WORD_RULE", + w: 1}; + } +}; + +var NumberRule = { + createAcceptor: function(tag) { + if (tag["NUMBER_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch >= "0" && ch <= "9") { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "NUMBER_RULE", + type: "NUMBER_RULE", + w: 1}; + } +}; + +var SpaceRule = { + tag: "SPACE_RULE", + createAcceptor: function(tag) { + + if (tag["SPACE_RULE"]) + return null; + + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (ch == " " || ch == "\t" || ch == "\r" || ch == "\n" || + ch == "\u00A0" || ch=="\u2003"//nbsp and emsp + ) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: SpaceRule.tag, + w: 1, + type: "SPACE_RULE"}; + } +} + +var SingleSymbolRule = { + tag: "SINSYM", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (this.strOffset == 0 && ch.match(/^[\@\(\)\/\,\-\."`]$/)) { + this.isFinal = true; + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "SINSYM", + w: 1, + type: "SINSYM"}; + } +} + + +var LatinRules = [WordRule, SpaceRule, SingleSymbolRule, NumberRule]; + +module.exports = LatinRules; + +},{}],4:[function(require,module,exports){ +var _ = require("underscore") + , WordcutCore = require("./wordcut_core"); +var PathInfoBuilder = { + + /* + buildByPartAcceptors: function(path, acceptors, i) { + var + var genInfos = partAcceptors.reduce(function(genInfos, acceptor) { + + }, []); + + return genInfos; + } + */ + + buildByAcceptors: function(path, finalAcceptors, i) { + var self = this; + var infos = finalAcceptors.map(function(acceptor) { + var p = i - acceptor.strOffset + 1 + , _info = path[p]; + + var info = {p: p, + mw: _info.mw + (acceptor.mw === undefined ? 0 : acceptor.mw), + w: acceptor.w + _info.w, + unk: (acceptor.unk ? acceptor.unk : 0) + _info.unk, + type: acceptor.type}; + + if (acceptor.type == "PART") { + for(var j = p + 1; j <= i; j++) { + path[j].merge = p; + } + info.merge = p; + } + + return info; + }); + return infos.filter(function(info) { return info; }); + }, + + fallback: function(path, leftBoundary, text, i) { + var _info = path[leftBoundary]; + if (text[i].match(/[\u0E48-\u0E4E]/)) { + if (leftBoundary != 0) + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + mw: 0, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; +/* } else if(leftBoundary > 0 && path[leftBoundary].type !== "UNK") { + leftBoundary = path[leftBoundary].p; + return {p: leftBoundary, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; */ + } else { + return {p: leftBoundary, + mw: _info.mw, + w: 1 + _info.w, + unk: 1 + _info.unk, + type: "UNK"}; + } + }, + + build: function(path, finalAcceptors, i, leftBoundary, text) { + var basicPathInfos = this.buildByAcceptors(path, finalAcceptors, i); + if (basicPathInfos.length > 0) { + return basicPathInfos; + } else { + return [this.fallback(path, leftBoundary, text, i)]; + } + } +}; + +module.exports = function() { + return _.clone(PathInfoBuilder); +} + +},{"./wordcut_core":8,"underscore":25}],5:[function(require,module,exports){ +var _ = require("underscore"); + + +var PathSelector = { + selectPath: function(paths) { + var path = paths.reduce(function(selectedPath, path) { + if (selectedPath == null) { + return path; + } else { + if (path.unk < selectedPath.unk) + return path; + if (path.unk == selectedPath.unk) { + if (path.mw < selectedPath.mw) + return path + if (path.mw == selectedPath.mw) { + if (path.w < selectedPath.w) + return path; + } + } + return selectedPath; + } + }, null); + return path; + }, + + createPath: function() { + return [{p:null, w:0, unk:0, type: "INIT", mw:0}]; + } +}; + +module.exports = function() { + return _.clone(PathSelector); +}; + +},{"underscore":25}],6:[function(require,module,exports){ +function isMatch(pat, offset, ch) { + if (pat.length <= offset) + return false; + var _ch = pat[offset]; + return _ch == ch || + (_ch.match(/[กข]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/[มบ]/) && ch.match(/[ก-ฮ]/)) || + (_ch.match(/\u0E49/) && ch.match(/[\u0E48-\u0E4B]/)); +} + +var Rule0 = { + pat: "เหก็ม", + createAcceptor: function(tag) { + return {strOffset: 0, + isFinal: false, + transit: function(ch) { + if (isMatch(Rule0.pat, this.strOffset,ch)) { + this.isFinal = (this.strOffset + 1 == Rule0.pat.length); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "THAI_RULE", + type: "THAI_RULE", + w: 1}; + } +}; + +var PartRule = { + createAcceptor: function(tag) { + return {strOffset: 0, + patterns: [ + "แก", "เก", "ก้", "กก์", "กา", "กี", "กิ", "กืก" + ], + isFinal: false, + transit: function(ch) { + var offset = this.strOffset; + this.patterns = this.patterns.filter(function(pat) { + return isMatch(pat, offset, ch); + }); + + if (this.patterns.length > 0) { + var len = 1 + offset; + this.isFinal = this.patterns.some(function(pat) { + return pat.length == len; + }); + this.strOffset++; + } else { + this.isError = true; + } + return this; + }, + isError: false, + tag: "PART", + type: "PART", + unk: 1, + w: 1}; + } +}; + +var ThaiRules = [Rule0, PartRule]; + +module.exports = ThaiRules; + +},{}],7:[function(require,module,exports){ +var sys = require("sys") + , WordcutDict = require("./dict") + , WordcutCore = require("./wordcut_core") + , PathInfoBuilder = require("./path_info_builder") + , PathSelector = require("./path_selector") + , Acceptors = require("./acceptors") + , latinRules = require("./latin_rules") + , thaiRules = require("./thai_rules") + , _ = require("underscore"); + + +var Wordcut = Object.create(WordcutCore); +Wordcut.defaultPathInfoBuilder = PathInfoBuilder; +Wordcut.defaultPathSelector = PathSelector; +Wordcut.defaultAcceptors = Acceptors; +Wordcut.defaultLatinRules = latinRules; +Wordcut.defaultThaiRules = thaiRules; +Wordcut.defaultDict = WordcutDict; + + +Wordcut.initNoDict = function(dict_path) { + var self = this; + self.pathInfoBuilder = new self.defaultPathInfoBuilder; + self.pathSelector = new self.defaultPathSelector; + self.acceptors = new self.defaultAcceptors; + self.defaultLatinRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); + self.defaultThaiRules.forEach(function(rule) { + self.acceptors.creators.push(rule); + }); +}; + +Wordcut.init = function(dict_path, withDefault, additionalWords) { + withDefault = withDefault || false; + this.initNoDict(); + var dict = _.clone(this.defaultDict); + dict.init(dict_path, withDefault, additionalWords); + this.acceptors.creators.push(dict); +}; + +module.exports = Wordcut; + +},{"./acceptors":1,"./dict":2,"./latin_rules":3,"./path_info_builder":4,"./path_selector":5,"./thai_rules":6,"./wordcut_core":8,"sys":28,"underscore":25}],8:[function(require,module,exports){ +var WordcutCore = { + + buildPath: function(text) { + var self = this + , path = self.pathSelector.createPath() + , leftBoundary = 0; + self.acceptors.reset(); + for (var i = 0; i < text.length; i++) { + var ch = text[i]; + self.acceptors.transit(ch); + + var possiblePathInfos = self + .pathInfoBuilder + .build(path, + self.acceptors.getFinalAcceptors(), + i, + leftBoundary, + text); + var selectedPath = self.pathSelector.selectPath(possiblePathInfos) + + path.push(selectedPath); + if (selectedPath.type !== "UNK") { + leftBoundary = i; + } + } + return path; + }, + + pathToRanges: function(path) { + var e = path.length - 1 + , ranges = []; + + while (e > 0) { + var info = path[e] + , s = info.p; + + if (info.merge !== undefined && ranges.length > 0) { + var r = ranges[ranges.length - 1]; + r.s = info.merge; + s = r.s; + } else { + ranges.push({s:s, e:e}); + } + e = s; + } + return ranges.reverse(); + }, + + rangesToText: function(text, ranges, delimiter) { + return ranges.map(function(r) { + return text.substring(r.s, r.e); + }).join(delimiter); + }, + + cut: function(text, delimiter) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + return this + .rangesToText(text, ranges, + (delimiter === undefined ? "|" : delimiter)); + }, + + cutIntoRanges: function(text, noText) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + if (!noText) { + ranges.forEach(function(r) { + r.text = text.substring(r.s, r.e); + }); + } + return ranges; + }, + + cutIntoArray: function(text) { + var path = this.buildPath(text) + , ranges = this.pathToRanges(path); + + return ranges.map(function(r) { + return text.substring(r.s, r.e) + }); + } +}; + +module.exports = WordcutCore; + +},{}],9:[function(require,module,exports){ +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// when used in node, this will actually load the util module we depend on +// versus loading the builtin util module as happens otherwise +// this is a bug in node module loading as far as I am concerned +var util = require('util/'); + +var pSlice = Array.prototype.slice; +var hasOwn = Object.prototype.hasOwnProperty; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } + else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = stackStartFunction.name; + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function replacer(key, value) { + if (util.isUndefined(value)) { + return '' + value; + } + if (util.isNumber(value) && !isFinite(value)) { + return value.toString(); + } + if (util.isFunction(value) || util.isRegExp(value)) { + return value.toString(); + } + return value; +} + +function truncate(s, n) { + if (util.isString(s)) { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} + +function getMessage(self) { + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + + self.operator + ' ' + + truncate(JSON.stringify(self.expected, replacer), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (util.isBuffer(actual) && util.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!util.isObject(actual) && !util.isObject(expected)) { + return actual == expected; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) { + return a === b; + } + var aIsArgs = isArguments(a), + bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + var ka = objectKeys(a), + kb = objectKeys(b), + key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key])) return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (util.isString(expected)) { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function(err) { if (err) {throw err;}}; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +},{"util/":28}],10:[function(require,module,exports){ +'use strict'; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); + + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; +} + +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} + +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + + if (ai >= 0 && bi > 0) { + begs = []; + left = str.length; + + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + + bi = str.indexOf(b, i + 1); + } + + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; +} + +},{}],11:[function(require,module,exports){ +var concatMap = require('concat-map'); +var balanced = require('balanced-match'); + +module.exports = expandTop; + +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; + +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + + +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; + + var parts = []; + var m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); + + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +function identity(e) { + return e; +} + +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} + +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} + +function expand(str, isTop) { + var expansions = []; + + var m = balanced('{', '}', str); + if (!m || /\$$/.test(m.pre)) return [str]; + + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,.*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + var post = m.post.length + ? expand(m.post, false) + : ['']; + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = concatMap(n, function(el) { return expand(el, false) }); + } + + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + + return expansions; +} + + +},{"balanced-match":10,"concat-map":13}],12:[function(require,module,exports){ + +},{}],13:[function(require,module,exports){ +module.exports = function (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + var x = fn(xs[i], i); + if (isArray(x)) res.push.apply(res, x); + else res.push(x); + } + return res; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],14:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],15:[function(require,module,exports){ +(function (process){ +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var path = require("path") +var minimatch = require("minimatch") +var isAbsolute = require("path-is-absolute") +var Minimatch = minimatch.Minimatch + +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} + +function alphasort (a, b) { + return a.localeCompare(b) +} + +function setupIgnores (self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern) + } + + return { + matcher: new Minimatch(pattern), + gmatcher: gmatcher + } +} + +function setopts (self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = options.cwd + self.changedCwd = path.resolve(options.cwd) !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") + + self.nomount = !!options.nomount + + // disable comments and negation unless the user explicitly + // passes in false as the option. + options.nonegate = options.nonegate === false ? false : true + options.nocomment = options.nocomment === false ? false : true + deprecationWarning(options) + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +// TODO(isaacs): remove entirely in v6 +// exported to reset in tests +exports.deprecationWarned +function deprecationWarning(options) { + if (!options.nonegate || !options.nocomment) { + if (process.noDeprecation !== true && !exports.deprecationWarned) { + var msg = 'glob WARNING: comments and negation will be disabled in v6' + if (process.throwDeprecation) + throw new Error(msg) + else if (process.traceDeprecation) + console.trace(msg) + else + console.error(msg) + + exports.deprecationWarned = true + } + } +} + +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + return !(/\/$/.test(e)) + }) + } + } + + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +}).call(this,require('_process')) +},{"_process":24,"minimatch":20,"path":22,"path-is-absolute":23}],16:[function(require,module,exports){ +(function (process){ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var inherits = require('inherits') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var globSync = require('./sync.js') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('inflight') +var util = require('util') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('once') + +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +glob.hasMagic = function (pattern, options_) { + var options = util._extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + var n = this.minimatch.set.length + this._processing = 0 + this.matches = new Array(n) + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) + } + + function done () { + --self._processing + if (self._processing <= 0) + self._finish() + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next () { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + fs.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (this.matches[index][e]) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = this._makeAbs(e) + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + if (this.mark) + e = this._mark(e) + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er) + return cb() + + var isSym = lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) + + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && !stat.isDirectory()) + return cb(null, false, stat) + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return cb() + + return cb(null, c, stat) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./sync.js":17,"_process":24,"assert":9,"events":14,"fs":12,"inflight":18,"inherits":19,"minimatch":20,"once":21,"path":22,"path-is-absolute":23,"util":28}],17:[function(require,module,exports){ +(function (process){ +module.exports = globSync +globSync.GlobSync = GlobSync + +var fs = require('fs') +var minimatch = require('minimatch') +var Minimatch = minimatch.Minimatch +var Glob = require('./glob.js').Glob +var util = require('util') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path-is-absolute') +var common = require('./common.js') +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored + +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = fs.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this.matches[index][e] = true + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[this._makeAbs(e)] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + // lstat failed, doesn't exist + return null + } + + var isSym = lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + this.cache[this._makeAbs(f)] = 'FILE' + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this.matches[index][prefix] = true +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + return false + } + + if (lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c !== 'DIR') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +}).call(this,require('_process')) +},{"./common.js":15,"./glob.js":16,"_process":24,"assert":9,"fs":12,"minimatch":20,"path":22,"path-is-absolute":23,"util":28}],18:[function(require,module,exports){ +(function (process){ +var wrappy = require('wrappy') +var reqs = Object.create(null) +var once = require('once') + +module.exports = wrappy(inflight) + +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice (args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} + +}).call(this,require('_process')) +},{"_process":24,"once":21,"wrappy":29}],19:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],20:[function(require,module,exports){ +module.exports = minimatch +minimatch.Minimatch = Minimatch + +var path = { sep: '/' } +try { + path = require('path') +} catch (er) {} + +var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} +var expand = require('brace-expansion') + +var plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} + +// any single thing other than / +// don't need to escape / when using new RegExp() +var qmark = '[^/]' + +// * => any number of characters +var star = qmark + '*?' + +// ** when dots are allowed. Anything goes, except .. and . +// not (^ or / followed by one or two dots followed by $ or /), +// followed by anything, any number of times. +var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' + +// not a ^ or / followed by a dot, +// followed by anything, any number of times. +var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' + +// characters that need to be escaped in RegExp. +var reSpecials = charSet('().*{}+?[]^$\\!') + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split('').reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + +function minimatch (p, pattern, options) { + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + return false + } + + // "" only matches "" + if (pattern.trim() === '') return p === '' + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options) + } + + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows support: need to use /, not \ + if (path.sep !== '/') { + pattern = pattern.split(path.sep).join('/') + } + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.debug = function () {} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = console.error + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return s.indexOf(false) === -1 + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + var negate = false + var options = this.options + var negateOffset = 0 + + if (options.nonegate) return + + for (var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === '!' + ; i++) { + negate = !negate + negateOffset++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return braceExpand(pattern, options) +} + +Minimatch.prototype.braceExpand = braceExpand + +function braceExpand (pattern, options) { + if (!options) { + if (this instanceof Minimatch) { + options = this.options + } else { + options = {} + } + } + + pattern = typeof pattern === 'undefined' + ? this.pattern : pattern + + if (typeof pattern === 'undefined') { + throw new TypeError('undefined pattern') + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + return expand(pattern) +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError('pattern is too long') + } + + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === '**') return GLOBSTAR + if (pattern === '') return '' + + var re = '' + var hasMagic = !!options.nocase + var escaping = false + // ? => one single character + var patternListStack = [] + var negativeLists = [] + var stateChar + var inClass = false + var reClassStart = -1 + var classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + var patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + var self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for (var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += '\\' + c + escaping = false + continue + } + + switch (c) { + case '/': + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case '\\': + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case '(': + if (inClass) { + re += '(' + continue + } + + if (!stateChar) { + re += '\\(' + continue + } + + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } + + clearStateChar() + hasMagic = true + var pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue + + case '|': + if (inClass || !patternListStack.length || escaping) { + re += '\\|' + escaping = false + continue + } + + clearStateChar() + re += '|' + continue + + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += '\\' + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + escaping = false + continue + } + + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + if (inClass) { + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + var cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + var sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === '^' && inClass)) { + re += '\\' + } + + re += c + + } // switch + } // for + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) + + this.debug('tail=%j\n %s', tail, tail, pl, re) + var t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case '.': + case '[': + case '(': addPatternStart = true + } + + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (var n = negativeLists.length - 1; n > -1; n--) { + var nl = negativeLists[n] + + var nlBefore = re.slice(0, nl.reStart) + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + var nlAfter = re.slice(nl.reEnd) + + nlLast += nlAfter + + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + var openParensBefore = nlBefore.split('(').length - 1 + var cleanAfter = nlAfter + for (i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter + + var dollar = '' + if (nlAfter === '' && isSub !== SUBPARSE) { + dollar = '$' + } + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + re = newRe + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } + + if (addPatternStart) { + re = patternStart + re + } + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? 'i' : '' + try { + var regExp = new RegExp('^' + re + '$', flags) + } catch (er) { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') + } + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) { + this.regexp = false + return this.regexp + } + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + var flags = options.nocase ? 'i' : '' + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === 'string') ? regExpEscape(p) + : p._src + }).join('\\\/') + }).join('|') + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' + + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' + + try { + this.regexp = new RegExp(re, flags) + } catch (ex) { + this.regexp = false + } + return this.regexp +} + +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' + + if (f === '/' && partial) return true + + var options = this.options + + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, 'set', set) + + // Find the basename of the path by looking for the last non-empty segment + var filename + var i + for (i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (i = 0; i < set.length; i++) { + var pattern = set[i] + var file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) + + this.debug('matchOne', file.length, pattern.length) + + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + return emptyFileEnd + } + + // should be unreachable. + throw new Error('wtf?') +} + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, '$1') +} + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +} + +},{"brace-expansion":11,"path":22}],21:[function(require,module,exports){ +var wrappy = require('wrappy') +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + +},{"wrappy":29}],22:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":24}],23:[function(require,module,exports){ +(function (process){ +'use strict'; + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); +} + +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; + +}).call(this,require('_process')) +},{"_process":24}],24:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],25:[function(require,module,exports){ +// Underscore.js 1.8.3 +// http://underscorejs.org +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.8.3'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var optimizeCb = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + case 2: return function(value, other) { + return func.call(context, value, other); + }; + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + // A mostly-internal function to generate callbacks that can be applied + // to each element in a collection, returning the desired result — either + // identity, an arbitrary callback, a property matcher, or a property accessor. + var cb = function(value, context, argCount) { + if (value == null) return _.identity; + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); + return _.property(value); + }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + var property = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = property('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } + } else { + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } + } + return obj; + }; + + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); + + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; + }; + + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; + + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; + + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; + + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; + } + }); + } + return result; + }; + + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var set = isArrayLike(obj) ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; + } + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iteratee, context) { + var result = {}; + iteratee = cb(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(obj, predicate, context) { + predicate = cb(predicate, context); + var pass = [], fail = []; + _.each(obj, function(value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); + }); + return [pass, fail]; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; + } + } + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; + } + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } + } + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(flatten(arguments, true, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = getLength(array); i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); + } + return result; + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = flatten(arguments, true, true, 1); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); + } + return result; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + var result = {}; + for (var i = 0, length = getLength(list); i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // Generator function to create the findIndex and findLastIndex functions + function createPredicateIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions + function createIndexFinder(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); + } else { + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; + } + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; + } + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + } + + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (stop == null) { + stop = start || 0; + start = 0; + } + step = step || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); + + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); + }; + return bound; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); + } + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ + return func.apply(null, args); + }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; + + // Returns a function that will only be executed on and after the Nth call. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); + + // Object Functions + // ---------------- + + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; + } + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; + if (obj == null) return result; + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); + } else { + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } + return result; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(flatten(arguments, false, false, 1), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); + }; + + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; + } + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; + } + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj !== +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; + }; + + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; + }; + + _.noop = function(){}; + + _.property = property; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); + return function(obj) { + return _.isMatch(obj, attrs); + }; + }; + + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); + }; + + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + + // Adobe VMs need the match returned to produce the correct offest. + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result(this, func.apply(_, args)); + }; + }); + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; + }; + + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; + }; + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}.call(this)); + +},{}],26:[function(require,module,exports){ +arguments[4][19][0].apply(exports,arguments) +},{"dup":19}],27:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],28:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":27,"_process":24,"inherits":26}],29:[function(require,module,exports){ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + +},{}]},{},[7])(7) +}); \ No newline at end of file diff --git a/assets/javascripts/workers/search.5bf1dace.min.js b/assets/javascripts/workers/search.5bf1dace.min.js new file mode 100644 index 00000000..5b80d43c --- /dev/null +++ b/assets/javascripts/workers/search.5bf1dace.min.js @@ -0,0 +1,48 @@ +"use strict";(()=>{var ge=Object.create;var W=Object.defineProperty,ye=Object.defineProperties,me=Object.getOwnPropertyDescriptor,ve=Object.getOwnPropertyDescriptors,xe=Object.getOwnPropertyNames,G=Object.getOwnPropertySymbols,Se=Object.getPrototypeOf,X=Object.prototype.hasOwnProperty,Qe=Object.prototype.propertyIsEnumerable;var J=(t,e,r)=>e in t?W(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,M=(t,e)=>{for(var r in e||(e={}))X.call(e,r)&&J(t,r,e[r]);if(G)for(var r of G(e))Qe.call(e,r)&&J(t,r,e[r]);return t},Z=(t,e)=>ye(t,ve(e));var K=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var be=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of xe(e))!X.call(t,i)&&i!==r&&W(t,i,{get:()=>e[i],enumerable:!(n=me(e,i))||n.enumerable});return t};var H=(t,e,r)=>(r=t!=null?ge(Se(t)):{},be(e||!t||!t.__esModule?W(r,"default",{value:t,enumerable:!0}):r,t));var z=(t,e,r)=>new Promise((n,i)=>{var s=u=>{try{a(r.next(u))}catch(c){i(c)}},o=u=>{try{a(r.throw(u))}catch(c){i(c)}},a=u=>u.done?n(u.value):Promise.resolve(u.value).then(s,o);a((r=r.apply(t,e)).next())});var re=K((ee,te)=>{/** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + */(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";/*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + */t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var h=t.utils.clone(r)||{};h.position=[a,c],h.index=s.length,s.push(new t.Token(n.slice(a,o),h))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;/*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + */t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?h+=2:a==u&&(r+=n[c+1]*i[h+1],c+=2,h+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var h=s.str.charAt(0),y=s.str.charAt(1),g;y in s.node.edges?g=s.node.edges[y]:(g=new t.TokenSet,s.node.edges[y]=g),s.str.length==1&&(g.final=!0),i.push({node:g,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};/*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + */t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof ee=="object"?te.exports=r():e.lunr=r()}(this,function(){return t})})()});var q=K((Re,ne)=>{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var Le=/["'&<>]/;ne.exports=we;function we(t){var e=""+t,r=Le.exec(e);if(!r)return e;var n,i="",s=0,o=0;for(s=r.index;s=0;r--){let n=t[r];typeof n!="object"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?e.insertBefore(this.previousSibling,n):e.replaceChild(n,this)}}}));var ie=H(q());function se(t){let e=new Map,r=new Set;for(let n of t){let[i,s]=n.location.split("#"),o=n.location,a=n.title,u=n.tags,c=(0,ie.default)(n.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(s){let h=e.get(i);r.has(h)?e.set(o,{location:o,title:a,text:c,parent:h}):(h.title=n.title,h.text=c,r.add(h))}else e.set(o,M({location:o,title:a,text:c},u&&{tags:u}))}return e}var oe=H(q());function ae(t,e){let r=new RegExp(t.separator,"img"),n=(i,s,o)=>`${s}${o}`;return i=>{i=i.replace(/[\s*+\-:~^]+/g," ").trim();let s=new RegExp(`(^|${t.separator})(${i.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return o=>(e?(0,oe.default)(o):o).replace(s,n).replace(/<\/mark>(\s+)]*>/img,"$1")}}function ue(t){let e=new lunr.Query(["title","text"]);return new lunr.QueryParser(t,e).parse(),e.clauses}function ce(t,e){var i;let r=new Set(t),n={};for(let s=0;s!n.has(i)))]}var U=class{constructor({config:e,docs:r,options:n}){this.options=n,this.documents=se(r),this.highlight=ae(e,!1),lunr.tokenizer.separator=new RegExp(e.separator),this.index=lunr(function(){e.lang.length===1&&e.lang[0]!=="en"?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang));let i=Ee(["trimmer","stopWordFilter","stemmer"],n.pipeline);for(let s of e.lang.map(o=>o==="en"?lunr:lunr[o]))for(let o of i)this.pipeline.remove(s[o]),this.searchPipeline.remove(s[o]);this.ref("location"),this.field("title",{boost:1e3}),this.field("text"),this.field("tags",{boost:1e6,extractor:s=>{let{tags:o=[]}=s;return o.reduce((a,u)=>[...a,...lunr.tokenizer(u)],[])}});for(let s of r)this.add(s,{boost:s.boost})})}search(e){if(e)try{let r=this.highlight(e),n=ue(e).filter(o=>o.presence!==lunr.Query.presence.PROHIBITED),i=this.index.search(`${e}*`).reduce((o,{ref:a,score:u,matchData:c})=>{let h=this.documents.get(a);if(typeof h!="undefined"){let{location:y,title:g,text:b,tags:m,parent:Q}=h,p=ce(n,Object.keys(c.metadata)),d=+!Q+ +Object.values(p).every(w=>w);o.push(Z(M({location:y,title:r(g),text:r(b)},m&&{tags:m.map(r)}),{score:u*(1+d),terms:p}))}return o},[]).sort((o,a)=>a.score-o.score).reduce((o,a)=>{let u=this.documents.get(a.location);if(typeof u!="undefined"){let c="parent"in u?u.parent.location:u.location;o.set(c,[...o.get(c)||[],a])}return o},new Map),s;if(this.options.suggestions){let o=this.index.query(a=>{for(let u of n)a.term(u.term,{fields:["title"],presence:lunr.Query.presence.REQUIRED,wildcard:lunr.Query.wildcard.TRAILING})});s=o.length?Object.keys(o[0].matchData.metadata):[]}return M({items:[...i.values()]},typeof s!="undefined"&&{suggestions:s})}catch(r){console.warn(`Invalid query: ${e} \u2013 see https://bit.ly/2s3ChXG`)}return{items:[]}}};var Y;function ke(t){return z(this,null,function*(){let e="../lunr";if(typeof parent!="undefined"&&"IFrameWorker"in parent){let n=document.querySelector("script[src]"),[i]=n.src.split("/worker");e=e.replace("..",i)}let r=[];for(let n of t.lang){switch(n){case"ja":r.push(`${e}/tinyseg.js`);break;case"hi":case"th":r.push(`${e}/wordcut.js`);break}n!=="en"&&r.push(`${e}/min/lunr.${n}.min.js`)}t.lang.length>1&&r.push(`${e}/min/lunr.multi.min.js`),r.length&&(yield importScripts(`${e}/min/lunr.stemmer.support.min.js`,...r))})}function Te(t){return z(this,null,function*(){switch(t.type){case 0:return yield ke(t.data.config),Y=new U(t.data),{type:1};case 2:return{type:3,data:Y?Y.search(t.data):{items:[]}};default:throw new TypeError("Invalid message type")}})}self.lunr=le.default;addEventListener("message",t=>z(void 0,null,function*(){postMessage(yield Te(t.data))}));})(); +//# sourceMappingURL=search.5bf1dace.min.js.map + diff --git a/assets/javascripts/workers/search.5bf1dace.min.js.map b/assets/javascripts/workers/search.5bf1dace.min.js.map new file mode 100644 index 00000000..1df8be0e --- /dev/null +++ b/assets/javascripts/workers/search.5bf1dace.min.js.map @@ -0,0 +1,8 @@ +{ + "version": 3, + "sources": ["node_modules/lunr/lunr.js", "node_modules/escape-html/index.js", "src/assets/javascripts/integrations/search/worker/main/index.ts", "src/assets/javascripts/polyfills/index.ts", "src/assets/javascripts/integrations/search/document/index.ts", "src/assets/javascripts/integrations/search/highlighter/index.ts", "src/assets/javascripts/integrations/search/query/_/index.ts", "src/assets/javascripts/integrations/search/_/index.ts"], + "sourceRoot": "../../../..", + "sourcesContent": ["/**\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9\n * Copyright (C) 2020 Oliver Nightingale\n * @license MIT\n */\n\n;(function(){\n\n/**\n * A convenience function for configuring and constructing\n * a new lunr Index.\n *\n * A lunr.Builder instance is created and the pipeline setup\n * with a trimmer, stop word filter and stemmer.\n *\n * This builder object is yielded to the configuration function\n * that is passed as a parameter, allowing the list of fields\n * and other builder parameters to be customised.\n *\n * All documents _must_ be added within the passed config function.\n *\n * @example\n * var idx = lunr(function () {\n * this.field('title')\n * this.field('body')\n * this.ref('id')\n *\n * documents.forEach(function (doc) {\n * this.add(doc)\n * }, this)\n * })\n *\n * @see {@link lunr.Builder}\n * @see {@link lunr.Pipeline}\n * @see {@link lunr.trimmer}\n * @see {@link lunr.stopWordFilter}\n * @see {@link lunr.stemmer}\n * @namespace {function} lunr\n */\nvar lunr = function (config) {\n var builder = new lunr.Builder\n\n builder.pipeline.add(\n lunr.trimmer,\n lunr.stopWordFilter,\n lunr.stemmer\n )\n\n builder.searchPipeline.add(\n lunr.stemmer\n )\n\n config.call(builder, builder)\n return builder.build()\n}\n\nlunr.version = \"2.3.9\"\n/*!\n * lunr.utils\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A namespace containing utils for the rest of the lunr library\n * @namespace lunr.utils\n */\nlunr.utils = {}\n\n/**\n * Print a warning message to the console.\n *\n * @param {String} message The message to be printed.\n * @memberOf lunr.utils\n * @function\n */\nlunr.utils.warn = (function (global) {\n /* eslint-disable no-console */\n return function (message) {\n if (global.console && console.warn) {\n console.warn(message)\n }\n }\n /* eslint-enable no-console */\n})(this)\n\n/**\n * Convert an object to a string.\n *\n * In the case of `null` and `undefined` the function returns\n * the empty string, in all other cases the result of calling\n * `toString` on the passed object is returned.\n *\n * @param {Any} obj The object to convert to a string.\n * @return {String} string representation of the passed object.\n * @memberOf lunr.utils\n */\nlunr.utils.asString = function (obj) {\n if (obj === void 0 || obj === null) {\n return \"\"\n } else {\n return obj.toString()\n }\n}\n\n/**\n * Clones an object.\n *\n * Will create a copy of an existing object such that any mutations\n * on the copy cannot affect the original.\n *\n * Only shallow objects are supported, passing a nested object to this\n * function will cause a TypeError.\n *\n * Objects with primitives, and arrays of primitives are supported.\n *\n * @param {Object} obj The object to clone.\n * @return {Object} a clone of the passed object.\n * @throws {TypeError} when a nested object is passed.\n * @memberOf Utils\n */\nlunr.utils.clone = function (obj) {\n if (obj === null || obj === undefined) {\n return obj\n }\n\n var clone = Object.create(null),\n keys = Object.keys(obj)\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i],\n val = obj[key]\n\n if (Array.isArray(val)) {\n clone[key] = val.slice()\n continue\n }\n\n if (typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean') {\n clone[key] = val\n continue\n }\n\n throw new TypeError(\"clone is not deep and does not support nested objects\")\n }\n\n return clone\n}\nlunr.FieldRef = function (docRef, fieldName, stringValue) {\n this.docRef = docRef\n this.fieldName = fieldName\n this._stringValue = stringValue\n}\n\nlunr.FieldRef.joiner = \"/\"\n\nlunr.FieldRef.fromString = function (s) {\n var n = s.indexOf(lunr.FieldRef.joiner)\n\n if (n === -1) {\n throw \"malformed field ref string\"\n }\n\n var fieldRef = s.slice(0, n),\n docRef = s.slice(n + 1)\n\n return new lunr.FieldRef (docRef, fieldRef, s)\n}\n\nlunr.FieldRef.prototype.toString = function () {\n if (this._stringValue == undefined) {\n this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef\n }\n\n return this._stringValue\n}\n/*!\n * lunr.Set\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A lunr set.\n *\n * @constructor\n */\nlunr.Set = function (elements) {\n this.elements = Object.create(null)\n\n if (elements) {\n this.length = elements.length\n\n for (var i = 0; i < this.length; i++) {\n this.elements[elements[i]] = true\n }\n } else {\n this.length = 0\n }\n}\n\n/**\n * A complete set that contains all elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.complete = {\n intersect: function (other) {\n return other\n },\n\n union: function () {\n return this\n },\n\n contains: function () {\n return true\n }\n}\n\n/**\n * An empty set that contains no elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.empty = {\n intersect: function () {\n return this\n },\n\n union: function (other) {\n return other\n },\n\n contains: function () {\n return false\n }\n}\n\n/**\n * Returns true if this set contains the specified object.\n *\n * @param {object} object - Object whose presence in this set is to be tested.\n * @returns {boolean} - True if this set contains the specified object.\n */\nlunr.Set.prototype.contains = function (object) {\n return !!this.elements[object]\n}\n\n/**\n * Returns a new set containing only the elements that are present in both\n * this set and the specified set.\n *\n * @param {lunr.Set} other - set to intersect with this set.\n * @returns {lunr.Set} a new set that is the intersection of this and the specified set.\n */\n\nlunr.Set.prototype.intersect = function (other) {\n var a, b, elements, intersection = []\n\n if (other === lunr.Set.complete) {\n return this\n }\n\n if (other === lunr.Set.empty) {\n return other\n }\n\n if (this.length < other.length) {\n a = this\n b = other\n } else {\n a = other\n b = this\n }\n\n elements = Object.keys(a.elements)\n\n for (var i = 0; i < elements.length; i++) {\n var element = elements[i]\n if (element in b.elements) {\n intersection.push(element)\n }\n }\n\n return new lunr.Set (intersection)\n}\n\n/**\n * Returns a new set combining the elements of this and the specified set.\n *\n * @param {lunr.Set} other - set to union with this set.\n * @return {lunr.Set} a new set that is the union of this and the specified set.\n */\n\nlunr.Set.prototype.union = function (other) {\n if (other === lunr.Set.complete) {\n return lunr.Set.complete\n }\n\n if (other === lunr.Set.empty) {\n return this\n }\n\n return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))\n}\n/**\n * A function to calculate the inverse document frequency for\n * a posting. This is shared between the builder and the index\n *\n * @private\n * @param {object} posting - The posting for a given term\n * @param {number} documentCount - The total number of documents.\n */\nlunr.idf = function (posting, documentCount) {\n var documentsWithTerm = 0\n\n for (var fieldName in posting) {\n if (fieldName == '_index') continue // Ignore the term index, its not a field\n documentsWithTerm += Object.keys(posting[fieldName]).length\n }\n\n var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5)\n\n return Math.log(1 + Math.abs(x))\n}\n\n/**\n * A token wraps a string representation of a token\n * as it is passed through the text processing pipeline.\n *\n * @constructor\n * @param {string} [str=''] - The string token being wrapped.\n * @param {object} [metadata={}] - Metadata associated with this token.\n */\nlunr.Token = function (str, metadata) {\n this.str = str || \"\"\n this.metadata = metadata || {}\n}\n\n/**\n * Returns the token string that is being wrapped by this object.\n *\n * @returns {string}\n */\nlunr.Token.prototype.toString = function () {\n return this.str\n}\n\n/**\n * A token update function is used when updating or optionally\n * when cloning a token.\n *\n * @callback lunr.Token~updateFunction\n * @param {string} str - The string representation of the token.\n * @param {Object} metadata - All metadata associated with this token.\n */\n\n/**\n * Applies the given function to the wrapped string token.\n *\n * @example\n * token.update(function (str, metadata) {\n * return str.toUpperCase()\n * })\n *\n * @param {lunr.Token~updateFunction} fn - A function to apply to the token string.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.update = function (fn) {\n this.str = fn(this.str, this.metadata)\n return this\n}\n\n/**\n * Creates a clone of this token. Optionally a function can be\n * applied to the cloned token.\n *\n * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.clone = function (fn) {\n fn = fn || function (s) { return s }\n return new lunr.Token (fn(this.str, this.metadata), this.metadata)\n}\n/*!\n * lunr.tokenizer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A function for splitting a string into tokens ready to be inserted into\n * the search index. Uses `lunr.tokenizer.separator` to split strings, change\n * the value of this property to change how strings are split into tokens.\n *\n * This tokenizer will convert its parameter to a string by calling `toString` and\n * then will split this string on the character in `lunr.tokenizer.separator`.\n * Arrays will have their elements converted to strings and wrapped in a lunr.Token.\n *\n * Optional metadata can be passed to the tokenizer, this metadata will be cloned and\n * added as metadata to every token that is created from the object to be tokenized.\n *\n * @static\n * @param {?(string|object|object[])} obj - The object to convert into tokens\n * @param {?object} metadata - Optional metadata to associate with every token\n * @returns {lunr.Token[]}\n * @see {@link lunr.Pipeline}\n */\nlunr.tokenizer = function (obj, metadata) {\n if (obj == null || obj == undefined) {\n return []\n }\n\n if (Array.isArray(obj)) {\n return obj.map(function (t) {\n return new lunr.Token(\n lunr.utils.asString(t).toLowerCase(),\n lunr.utils.clone(metadata)\n )\n })\n }\n\n var str = obj.toString().toLowerCase(),\n len = str.length,\n tokens = []\n\n for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {\n var char = str.charAt(sliceEnd),\n sliceLength = sliceEnd - sliceStart\n\n if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {\n\n if (sliceLength > 0) {\n var tokenMetadata = lunr.utils.clone(metadata) || {}\n tokenMetadata[\"position\"] = [sliceStart, sliceLength]\n tokenMetadata[\"index\"] = tokens.length\n\n tokens.push(\n new lunr.Token (\n str.slice(sliceStart, sliceEnd),\n tokenMetadata\n )\n )\n }\n\n sliceStart = sliceEnd + 1\n }\n\n }\n\n return tokens\n}\n\n/**\n * The separator used to split a string into tokens. Override this property to change the behaviour of\n * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.\n *\n * @static\n * @see lunr.tokenizer\n */\nlunr.tokenizer.separator = /[\\s\\-]+/\n/*!\n * lunr.Pipeline\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Pipelines maintain an ordered list of functions to be applied to all\n * tokens in documents entering the search index and queries being ran against\n * the index.\n *\n * An instance of lunr.Index created with the lunr shortcut will contain a\n * pipeline with a stop word filter and an English language stemmer. Extra\n * functions can be added before or after either of these functions or these\n * default functions can be removed.\n *\n * When run the pipeline will call each function in turn, passing a token, the\n * index of that token in the original list of all tokens and finally a list of\n * all the original tokens.\n *\n * The output of functions in the pipeline will be passed to the next function\n * in the pipeline. To exclude a token from entering the index the function\n * should return undefined, the rest of the pipeline will not be called with\n * this token.\n *\n * For serialisation of pipelines to work, all functions used in an instance of\n * a pipeline should be registered with lunr.Pipeline. Registered functions can\n * then be loaded. If trying to load a serialised pipeline that uses functions\n * that are not registered an error will be thrown.\n *\n * If not planning on serialising the pipeline then registering pipeline functions\n * is not necessary.\n *\n * @constructor\n */\nlunr.Pipeline = function () {\n this._stack = []\n}\n\nlunr.Pipeline.registeredFunctions = Object.create(null)\n\n/**\n * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token\n * string as well as all known metadata. A pipeline function can mutate the token string\n * or mutate (or add) metadata for a given token.\n *\n * A pipeline function can indicate that the passed token should be discarded by returning\n * null, undefined or an empty string. This token will not be passed to any downstream pipeline\n * functions and will not be added to the index.\n *\n * Multiple tokens can be returned by returning an array of tokens. Each token will be passed\n * to any downstream pipeline functions and all will returned tokens will be added to the index.\n *\n * Any number of pipeline functions may be chained together using a lunr.Pipeline.\n *\n * @interface lunr.PipelineFunction\n * @param {lunr.Token} token - A token from the document being processed.\n * @param {number} i - The index of this token in the complete list of tokens for this document/field.\n * @param {lunr.Token[]} tokens - All tokens for this document/field.\n * @returns {(?lunr.Token|lunr.Token[])}\n */\n\n/**\n * Register a function with the pipeline.\n *\n * Functions that are used in the pipeline should be registered if the pipeline\n * needs to be serialised, or a serialised pipeline needs to be loaded.\n *\n * Registering a function does not add it to a pipeline, functions must still be\n * added to instances of the pipeline for them to be used when running a pipeline.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @param {String} label - The label to register this function with\n */\nlunr.Pipeline.registerFunction = function (fn, label) {\n if (label in this.registeredFunctions) {\n lunr.utils.warn('Overwriting existing registered function: ' + label)\n }\n\n fn.label = label\n lunr.Pipeline.registeredFunctions[fn.label] = fn\n}\n\n/**\n * Warns if the function is not registered as a Pipeline function.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @private\n */\nlunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {\n var isRegistered = fn.label && (fn.label in this.registeredFunctions)\n\n if (!isRegistered) {\n lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\\n', fn)\n }\n}\n\n/**\n * Loads a previously serialised pipeline.\n *\n * All functions to be loaded must already be registered with lunr.Pipeline.\n * If any function from the serialised data has not been registered then an\n * error will be thrown.\n *\n * @param {Object} serialised - The serialised pipeline to load.\n * @returns {lunr.Pipeline}\n */\nlunr.Pipeline.load = function (serialised) {\n var pipeline = new lunr.Pipeline\n\n serialised.forEach(function (fnName) {\n var fn = lunr.Pipeline.registeredFunctions[fnName]\n\n if (fn) {\n pipeline.add(fn)\n } else {\n throw new Error('Cannot load unregistered function: ' + fnName)\n }\n })\n\n return pipeline\n}\n\n/**\n * Adds new functions to the end of the pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline.\n */\nlunr.Pipeline.prototype.add = function () {\n var fns = Array.prototype.slice.call(arguments)\n\n fns.forEach(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n this._stack.push(fn)\n }, this)\n}\n\n/**\n * Adds a single function after a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.after = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n pos = pos + 1\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Adds a single function before a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.before = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Removes a function from the pipeline.\n *\n * @param {lunr.PipelineFunction} fn The function to remove from the pipeline.\n */\nlunr.Pipeline.prototype.remove = function (fn) {\n var pos = this._stack.indexOf(fn)\n if (pos == -1) {\n return\n }\n\n this._stack.splice(pos, 1)\n}\n\n/**\n * Runs the current list of functions that make up the pipeline against the\n * passed tokens.\n *\n * @param {Array} tokens The tokens to run through the pipeline.\n * @returns {Array}\n */\nlunr.Pipeline.prototype.run = function (tokens) {\n var stackLength = this._stack.length\n\n for (var i = 0; i < stackLength; i++) {\n var fn = this._stack[i]\n var memo = []\n\n for (var j = 0; j < tokens.length; j++) {\n var result = fn(tokens[j], j, tokens)\n\n if (result === null || result === void 0 || result === '') continue\n\n if (Array.isArray(result)) {\n for (var k = 0; k < result.length; k++) {\n memo.push(result[k])\n }\n } else {\n memo.push(result)\n }\n }\n\n tokens = memo\n }\n\n return tokens\n}\n\n/**\n * Convenience method for passing a string through a pipeline and getting\n * strings out. This method takes care of wrapping the passed string in a\n * token and mapping the resulting tokens back to strings.\n *\n * @param {string} str - The string to pass through the pipeline.\n * @param {?object} metadata - Optional metadata to associate with the token\n * passed to the pipeline.\n * @returns {string[]}\n */\nlunr.Pipeline.prototype.runString = function (str, metadata) {\n var token = new lunr.Token (str, metadata)\n\n return this.run([token]).map(function (t) {\n return t.toString()\n })\n}\n\n/**\n * Resets the pipeline by removing any existing processors.\n *\n */\nlunr.Pipeline.prototype.reset = function () {\n this._stack = []\n}\n\n/**\n * Returns a representation of the pipeline ready for serialisation.\n *\n * Logs a warning if the function has not been registered.\n *\n * @returns {Array}\n */\nlunr.Pipeline.prototype.toJSON = function () {\n return this._stack.map(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n\n return fn.label\n })\n}\n/*!\n * lunr.Vector\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A vector is used to construct the vector space of documents and queries. These\n * vectors support operations to determine the similarity between two documents or\n * a document and a query.\n *\n * Normally no parameters are required for initializing a vector, but in the case of\n * loading a previously dumped vector the raw elements can be provided to the constructor.\n *\n * For performance reasons vectors are implemented with a flat array, where an elements\n * index is immediately followed by its value. E.g. [index, value, index, value]. This\n * allows the underlying array to be as sparse as possible and still offer decent\n * performance when being used for vector calculations.\n *\n * @constructor\n * @param {Number[]} [elements] - The flat list of element index and element value pairs.\n */\nlunr.Vector = function (elements) {\n this._magnitude = 0\n this.elements = elements || []\n}\n\n\n/**\n * Calculates the position within the vector to insert a given index.\n *\n * This is used internally by insert and upsert. If there are duplicate indexes then\n * the position is returned as if the value for that index were to be updated, but it\n * is the callers responsibility to check whether there is a duplicate at that index\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @returns {Number}\n */\nlunr.Vector.prototype.positionForIndex = function (index) {\n // For an empty vector the tuple can be inserted at the beginning\n if (this.elements.length == 0) {\n return 0\n }\n\n var start = 0,\n end = this.elements.length / 2,\n sliceLength = end - start,\n pivotPoint = Math.floor(sliceLength / 2),\n pivotIndex = this.elements[pivotPoint * 2]\n\n while (sliceLength > 1) {\n if (pivotIndex < index) {\n start = pivotPoint\n }\n\n if (pivotIndex > index) {\n end = pivotPoint\n }\n\n if (pivotIndex == index) {\n break\n }\n\n sliceLength = end - start\n pivotPoint = start + Math.floor(sliceLength / 2)\n pivotIndex = this.elements[pivotPoint * 2]\n }\n\n if (pivotIndex == index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex > index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex < index) {\n return (pivotPoint + 1) * 2\n }\n}\n\n/**\n * Inserts an element at an index within the vector.\n *\n * Does not allow duplicates, will throw an error if there is already an entry\n * for this index.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n */\nlunr.Vector.prototype.insert = function (insertIdx, val) {\n this.upsert(insertIdx, val, function () {\n throw \"duplicate index\"\n })\n}\n\n/**\n * Inserts or updates an existing index within the vector.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n * @param {function} fn - A function that is called for updates, the existing value and the\n * requested value are passed as arguments\n */\nlunr.Vector.prototype.upsert = function (insertIdx, val, fn) {\n this._magnitude = 0\n var position = this.positionForIndex(insertIdx)\n\n if (this.elements[position] == insertIdx) {\n this.elements[position + 1] = fn(this.elements[position + 1], val)\n } else {\n this.elements.splice(position, 0, insertIdx, val)\n }\n}\n\n/**\n * Calculates the magnitude of this vector.\n *\n * @returns {Number}\n */\nlunr.Vector.prototype.magnitude = function () {\n if (this._magnitude) return this._magnitude\n\n var sumOfSquares = 0,\n elementsLength = this.elements.length\n\n for (var i = 1; i < elementsLength; i += 2) {\n var val = this.elements[i]\n sumOfSquares += val * val\n }\n\n return this._magnitude = Math.sqrt(sumOfSquares)\n}\n\n/**\n * Calculates the dot product of this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The vector to compute the dot product with.\n * @returns {Number}\n */\nlunr.Vector.prototype.dot = function (otherVector) {\n var dotProduct = 0,\n a = this.elements, b = otherVector.elements,\n aLen = a.length, bLen = b.length,\n aVal = 0, bVal = 0,\n i = 0, j = 0\n\n while (i < aLen && j < bLen) {\n aVal = a[i], bVal = b[j]\n if (aVal < bVal) {\n i += 2\n } else if (aVal > bVal) {\n j += 2\n } else if (aVal == bVal) {\n dotProduct += a[i + 1] * b[j + 1]\n i += 2\n j += 2\n }\n }\n\n return dotProduct\n}\n\n/**\n * Calculates the similarity between this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The other vector to calculate the\n * similarity with.\n * @returns {Number}\n */\nlunr.Vector.prototype.similarity = function (otherVector) {\n return this.dot(otherVector) / this.magnitude() || 0\n}\n\n/**\n * Converts the vector to an array of the elements within the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toArray = function () {\n var output = new Array (this.elements.length / 2)\n\n for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {\n output[j] = this.elements[i]\n }\n\n return output\n}\n\n/**\n * A JSON serializable representation of the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toJSON = function () {\n return this.elements\n}\n/* eslint-disable */\n/*!\n * lunr.stemmer\n * Copyright (C) 2020 Oliver Nightingale\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\n */\n\n/**\n * lunr.stemmer is an english language stemmer, this is a JavaScript\n * implementation of the PorterStemmer taken from http://tartarus.org/~martin\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token - The string to stem\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n * @function\n */\nlunr.stemmer = (function(){\n var step2list = {\n \"ational\" : \"ate\",\n \"tional\" : \"tion\",\n \"enci\" : \"ence\",\n \"anci\" : \"ance\",\n \"izer\" : \"ize\",\n \"bli\" : \"ble\",\n \"alli\" : \"al\",\n \"entli\" : \"ent\",\n \"eli\" : \"e\",\n \"ousli\" : \"ous\",\n \"ization\" : \"ize\",\n \"ation\" : \"ate\",\n \"ator\" : \"ate\",\n \"alism\" : \"al\",\n \"iveness\" : \"ive\",\n \"fulness\" : \"ful\",\n \"ousness\" : \"ous\",\n \"aliti\" : \"al\",\n \"iviti\" : \"ive\",\n \"biliti\" : \"ble\",\n \"logi\" : \"log\"\n },\n\n step3list = {\n \"icate\" : \"ic\",\n \"ative\" : \"\",\n \"alize\" : \"al\",\n \"iciti\" : \"ic\",\n \"ical\" : \"ic\",\n \"ful\" : \"\",\n \"ness\" : \"\"\n },\n\n c = \"[^aeiou]\", // consonant\n v = \"[aeiouy]\", // vowel\n C = c + \"[^aeiouy]*\", // consonant sequence\n V = v + \"[aeiou]*\", // vowel sequence\n\n mgr0 = \"^(\" + C + \")?\" + V + C, // [C]VC... is m>0\n meq1 = \"^(\" + C + \")?\" + V + C + \"(\" + V + \")?$\", // [C]VC[V] is m=1\n mgr1 = \"^(\" + C + \")?\" + V + C + V + C, // [C]VCVC... is m>1\n s_v = \"^(\" + C + \")?\" + v; // vowel in stem\n\n var re_mgr0 = new RegExp(mgr0);\n var re_mgr1 = new RegExp(mgr1);\n var re_meq1 = new RegExp(meq1);\n var re_s_v = new RegExp(s_v);\n\n var re_1a = /^(.+?)(ss|i)es$/;\n var re2_1a = /^(.+?)([^s])s$/;\n var re_1b = /^(.+?)eed$/;\n var re2_1b = /^(.+?)(ed|ing)$/;\n var re_1b_2 = /.$/;\n var re2_1b_2 = /(at|bl|iz)$/;\n var re3_1b_2 = new RegExp(\"([^aeiouylsz])\\\\1$\");\n var re4_1b_2 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var re_1c = /^(.+?[^aeiou])y$/;\n var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\n\n var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\n\n var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n var re2_4 = /^(.+?)(s|t)(ion)$/;\n\n var re_5 = /^(.+?)e$/;\n var re_5_1 = /ll$/;\n var re3_5 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var porterStemmer = function porterStemmer(w) {\n var stem,\n suffix,\n firstch,\n re,\n re2,\n re3,\n re4;\n\n if (w.length < 3) { return w; }\n\n firstch = w.substr(0,1);\n if (firstch == \"y\") {\n w = firstch.toUpperCase() + w.substr(1);\n }\n\n // Step 1a\n re = re_1a\n re2 = re2_1a;\n\n if (re.test(w)) { w = w.replace(re,\"$1$2\"); }\n else if (re2.test(w)) { w = w.replace(re2,\"$1$2\"); }\n\n // Step 1b\n re = re_1b;\n re2 = re2_1b;\n if (re.test(w)) {\n var fp = re.exec(w);\n re = re_mgr0;\n if (re.test(fp[1])) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1];\n re2 = re_s_v;\n if (re2.test(stem)) {\n w = stem;\n re2 = re2_1b_2;\n re3 = re3_1b_2;\n re4 = re4_1b_2;\n if (re2.test(w)) { w = w + \"e\"; }\n else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,\"\"); }\n else if (re4.test(w)) { w = w + \"e\"; }\n }\n }\n\n // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)\n re = re_1c;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n w = stem + \"i\";\n }\n\n // Step 2\n re = re_2;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step2list[suffix];\n }\n }\n\n // Step 3\n re = re_3;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step3list[suffix];\n }\n }\n\n // Step 4\n re = re_4;\n re2 = re2_4;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n if (re.test(stem)) {\n w = stem;\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1] + fp[2];\n re2 = re_mgr1;\n if (re2.test(stem)) {\n w = stem;\n }\n }\n\n // Step 5\n re = re_5;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n re2 = re_meq1;\n re3 = re3_5;\n if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {\n w = stem;\n }\n }\n\n re = re_5_1;\n re2 = re_mgr1;\n if (re.test(w) && re2.test(w)) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n\n // and turn initial Y back to y\n\n if (firstch == \"y\") {\n w = firstch.toLowerCase() + w.substr(1);\n }\n\n return w;\n };\n\n return function (token) {\n return token.update(porterStemmer);\n }\n})();\n\nlunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')\n/*!\n * lunr.stopWordFilter\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.generateStopWordFilter builds a stopWordFilter function from the provided\n * list of stop words.\n *\n * The built in lunr.stopWordFilter is built using this generator and can be used\n * to generate custom stopWordFilters for applications or non English languages.\n *\n * @function\n * @param {Array} token The token to pass through the filter\n * @returns {lunr.PipelineFunction}\n * @see lunr.Pipeline\n * @see lunr.stopWordFilter\n */\nlunr.generateStopWordFilter = function (stopWords) {\n var words = stopWords.reduce(function (memo, stopWord) {\n memo[stopWord] = stopWord\n return memo\n }, {})\n\n return function (token) {\n if (token && words[token.toString()] !== token.toString()) return token\n }\n}\n\n/**\n * lunr.stopWordFilter is an English language stop word list filter, any words\n * contained in the list will not be passed through the filter.\n *\n * This is intended to be used in the Pipeline. If the token does not pass the\n * filter then undefined will be returned.\n *\n * @function\n * @implements {lunr.PipelineFunction}\n * @params {lunr.Token} token - A token to check for being a stop word.\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n */\nlunr.stopWordFilter = lunr.generateStopWordFilter([\n 'a',\n 'able',\n 'about',\n 'across',\n 'after',\n 'all',\n 'almost',\n 'also',\n 'am',\n 'among',\n 'an',\n 'and',\n 'any',\n 'are',\n 'as',\n 'at',\n 'be',\n 'because',\n 'been',\n 'but',\n 'by',\n 'can',\n 'cannot',\n 'could',\n 'dear',\n 'did',\n 'do',\n 'does',\n 'either',\n 'else',\n 'ever',\n 'every',\n 'for',\n 'from',\n 'get',\n 'got',\n 'had',\n 'has',\n 'have',\n 'he',\n 'her',\n 'hers',\n 'him',\n 'his',\n 'how',\n 'however',\n 'i',\n 'if',\n 'in',\n 'into',\n 'is',\n 'it',\n 'its',\n 'just',\n 'least',\n 'let',\n 'like',\n 'likely',\n 'may',\n 'me',\n 'might',\n 'most',\n 'must',\n 'my',\n 'neither',\n 'no',\n 'nor',\n 'not',\n 'of',\n 'off',\n 'often',\n 'on',\n 'only',\n 'or',\n 'other',\n 'our',\n 'own',\n 'rather',\n 'said',\n 'say',\n 'says',\n 'she',\n 'should',\n 'since',\n 'so',\n 'some',\n 'than',\n 'that',\n 'the',\n 'their',\n 'them',\n 'then',\n 'there',\n 'these',\n 'they',\n 'this',\n 'tis',\n 'to',\n 'too',\n 'twas',\n 'us',\n 'wants',\n 'was',\n 'we',\n 'were',\n 'what',\n 'when',\n 'where',\n 'which',\n 'while',\n 'who',\n 'whom',\n 'why',\n 'will',\n 'with',\n 'would',\n 'yet',\n 'you',\n 'your'\n])\n\nlunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')\n/*!\n * lunr.trimmer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.trimmer is a pipeline function for trimming non word\n * characters from the beginning and end of tokens before they\n * enter the index.\n *\n * This implementation may not work correctly for non latin\n * characters and should either be removed or adapted for use\n * with languages with non-latin characters.\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token The token to pass through the filter\n * @returns {lunr.Token}\n * @see lunr.Pipeline\n */\nlunr.trimmer = function (token) {\n return token.update(function (s) {\n return s.replace(/^\\W+/, '').replace(/\\W+$/, '')\n })\n}\n\nlunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')\n/*!\n * lunr.TokenSet\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A token set is used to store the unique list of all tokens\n * within an index. Token sets are also used to represent an\n * incoming query to the index, this query token set and index\n * token set are then intersected to find which tokens to look\n * up in the inverted index.\n *\n * A token set can hold multiple tokens, as in the case of the\n * index token set, or it can hold a single token as in the\n * case of a simple query token set.\n *\n * Additionally token sets are used to perform wildcard matching.\n * Leading, contained and trailing wildcards are supported, and\n * from this edit distance matching can also be provided.\n *\n * Token sets are implemented as a minimal finite state automata,\n * where both common prefixes and suffixes are shared between tokens.\n * This helps to reduce the space used for storing the token set.\n *\n * @constructor\n */\nlunr.TokenSet = function () {\n this.final = false\n this.edges = {}\n this.id = lunr.TokenSet._nextId\n lunr.TokenSet._nextId += 1\n}\n\n/**\n * Keeps track of the next, auto increment, identifier to assign\n * to a new tokenSet.\n *\n * TokenSets require a unique identifier to be correctly minimised.\n *\n * @private\n */\nlunr.TokenSet._nextId = 1\n\n/**\n * Creates a TokenSet instance from the given sorted array of words.\n *\n * @param {String[]} arr - A sorted array of strings to create the set from.\n * @returns {lunr.TokenSet}\n * @throws Will throw an error if the input array is not sorted.\n */\nlunr.TokenSet.fromArray = function (arr) {\n var builder = new lunr.TokenSet.Builder\n\n for (var i = 0, len = arr.length; i < len; i++) {\n builder.insert(arr[i])\n }\n\n builder.finish()\n return builder.root\n}\n\n/**\n * Creates a token set from a query clause.\n *\n * @private\n * @param {Object} clause - A single clause from lunr.Query.\n * @param {string} clause.term - The query clause term.\n * @param {number} [clause.editDistance] - The optional edit distance for the term.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromClause = function (clause) {\n if ('editDistance' in clause) {\n return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance)\n } else {\n return lunr.TokenSet.fromString(clause.term)\n }\n}\n\n/**\n * Creates a token set representing a single string with a specified\n * edit distance.\n *\n * Insertions, deletions, substitutions and transpositions are each\n * treated as an edit distance of 1.\n *\n * Increasing the allowed edit distance will have a dramatic impact\n * on the performance of both creating and intersecting these TokenSets.\n * It is advised to keep the edit distance less than 3.\n *\n * @param {string} str - The string to create the token set from.\n * @param {number} editDistance - The allowed edit distance to match.\n * @returns {lunr.Vector}\n */\nlunr.TokenSet.fromFuzzyString = function (str, editDistance) {\n var root = new lunr.TokenSet\n\n var stack = [{\n node: root,\n editsRemaining: editDistance,\n str: str\n }]\n\n while (stack.length) {\n var frame = stack.pop()\n\n // no edit\n if (frame.str.length > 0) {\n var char = frame.str.charAt(0),\n noEditNode\n\n if (char in frame.node.edges) {\n noEditNode = frame.node.edges[char]\n } else {\n noEditNode = new lunr.TokenSet\n frame.node.edges[char] = noEditNode\n }\n\n if (frame.str.length == 1) {\n noEditNode.final = true\n }\n\n stack.push({\n node: noEditNode,\n editsRemaining: frame.editsRemaining,\n str: frame.str.slice(1)\n })\n }\n\n if (frame.editsRemaining == 0) {\n continue\n }\n\n // insertion\n if (\"*\" in frame.node.edges) {\n var insertionNode = frame.node.edges[\"*\"]\n } else {\n var insertionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = insertionNode\n }\n\n if (frame.str.length == 0) {\n insertionNode.final = true\n }\n\n stack.push({\n node: insertionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str\n })\n\n // deletion\n // can only do a deletion if we have enough edits remaining\n // and if there are characters left to delete in the string\n if (frame.str.length > 1) {\n stack.push({\n node: frame.node,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // deletion\n // just removing the last character from the str\n if (frame.str.length == 1) {\n frame.node.final = true\n }\n\n // substitution\n // can only do a substitution if we have enough edits remaining\n // and if there are characters left to substitute\n if (frame.str.length >= 1) {\n if (\"*\" in frame.node.edges) {\n var substitutionNode = frame.node.edges[\"*\"]\n } else {\n var substitutionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = substitutionNode\n }\n\n if (frame.str.length == 1) {\n substitutionNode.final = true\n }\n\n stack.push({\n node: substitutionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // transposition\n // can only do a transposition if there are edits remaining\n // and there are enough characters to transpose\n if (frame.str.length > 1) {\n var charA = frame.str.charAt(0),\n charB = frame.str.charAt(1),\n transposeNode\n\n if (charB in frame.node.edges) {\n transposeNode = frame.node.edges[charB]\n } else {\n transposeNode = new lunr.TokenSet\n frame.node.edges[charB] = transposeNode\n }\n\n if (frame.str.length == 1) {\n transposeNode.final = true\n }\n\n stack.push({\n node: transposeNode,\n editsRemaining: frame.editsRemaining - 1,\n str: charA + frame.str.slice(2)\n })\n }\n }\n\n return root\n}\n\n/**\n * Creates a TokenSet from a string.\n *\n * The string may contain one or more wildcard characters (*)\n * that will allow wildcard matching when intersecting with\n * another TokenSet.\n *\n * @param {string} str - The string to create a TokenSet from.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromString = function (str) {\n var node = new lunr.TokenSet,\n root = node\n\n /*\n * Iterates through all characters within the passed string\n * appending a node for each character.\n *\n * When a wildcard character is found then a self\n * referencing edge is introduced to continually match\n * any number of any characters.\n */\n for (var i = 0, len = str.length; i < len; i++) {\n var char = str[i],\n final = (i == len - 1)\n\n if (char == \"*\") {\n node.edges[char] = node\n node.final = final\n\n } else {\n var next = new lunr.TokenSet\n next.final = final\n\n node.edges[char] = next\n node = next\n }\n }\n\n return root\n}\n\n/**\n * Converts this TokenSet into an array of strings\n * contained within the TokenSet.\n *\n * This is not intended to be used on a TokenSet that\n * contains wildcards, in these cases the results are\n * undefined and are likely to cause an infinite loop.\n *\n * @returns {string[]}\n */\nlunr.TokenSet.prototype.toArray = function () {\n var words = []\n\n var stack = [{\n prefix: \"\",\n node: this\n }]\n\n while (stack.length) {\n var frame = stack.pop(),\n edges = Object.keys(frame.node.edges),\n len = edges.length\n\n if (frame.node.final) {\n /* In Safari, at this point the prefix is sometimes corrupted, see:\n * https://github.com/olivernn/lunr.js/issues/279 Calling any\n * String.prototype method forces Safari to \"cast\" this string to what\n * it's supposed to be, fixing the bug. */\n frame.prefix.charAt(0)\n words.push(frame.prefix)\n }\n\n for (var i = 0; i < len; i++) {\n var edge = edges[i]\n\n stack.push({\n prefix: frame.prefix.concat(edge),\n node: frame.node.edges[edge]\n })\n }\n }\n\n return words\n}\n\n/**\n * Generates a string representation of a TokenSet.\n *\n * This is intended to allow TokenSets to be used as keys\n * in objects, largely to aid the construction and minimisation\n * of a TokenSet. As such it is not designed to be a human\n * friendly representation of the TokenSet.\n *\n * @returns {string}\n */\nlunr.TokenSet.prototype.toString = function () {\n // NOTE: Using Object.keys here as this.edges is very likely\n // to enter 'hash-mode' with many keys being added\n //\n // avoiding a for-in loop here as it leads to the function\n // being de-optimised (at least in V8). From some simple\n // benchmarks the performance is comparable, but allowing\n // V8 to optimize may mean easy performance wins in the future.\n\n if (this._str) {\n return this._str\n }\n\n var str = this.final ? '1' : '0',\n labels = Object.keys(this.edges).sort(),\n len = labels.length\n\n for (var i = 0; i < len; i++) {\n var label = labels[i],\n node = this.edges[label]\n\n str = str + label + node.id\n }\n\n return str\n}\n\n/**\n * Returns a new TokenSet that is the intersection of\n * this TokenSet and the passed TokenSet.\n *\n * This intersection will take into account any wildcards\n * contained within the TokenSet.\n *\n * @param {lunr.TokenSet} b - An other TokenSet to intersect with.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.prototype.intersect = function (b) {\n var output = new lunr.TokenSet,\n frame = undefined\n\n var stack = [{\n qNode: b,\n output: output,\n node: this\n }]\n\n while (stack.length) {\n frame = stack.pop()\n\n // NOTE: As with the #toString method, we are using\n // Object.keys and a for loop instead of a for-in loop\n // as both of these objects enter 'hash' mode, causing\n // the function to be de-optimised in V8\n var qEdges = Object.keys(frame.qNode.edges),\n qLen = qEdges.length,\n nEdges = Object.keys(frame.node.edges),\n nLen = nEdges.length\n\n for (var q = 0; q < qLen; q++) {\n var qEdge = qEdges[q]\n\n for (var n = 0; n < nLen; n++) {\n var nEdge = nEdges[n]\n\n if (nEdge == qEdge || qEdge == '*') {\n var node = frame.node.edges[nEdge],\n qNode = frame.qNode.edges[qEdge],\n final = node.final && qNode.final,\n next = undefined\n\n if (nEdge in frame.output.edges) {\n // an edge already exists for this character\n // no need to create a new node, just set the finality\n // bit unless this node is already final\n next = frame.output.edges[nEdge]\n next.final = next.final || final\n\n } else {\n // no edge exists yet, must create one\n // set the finality bit and insert it\n // into the output\n next = new lunr.TokenSet\n next.final = final\n frame.output.edges[nEdge] = next\n }\n\n stack.push({\n qNode: qNode,\n output: next,\n node: node\n })\n }\n }\n }\n }\n\n return output\n}\nlunr.TokenSet.Builder = function () {\n this.previousWord = \"\"\n this.root = new lunr.TokenSet\n this.uncheckedNodes = []\n this.minimizedNodes = {}\n}\n\nlunr.TokenSet.Builder.prototype.insert = function (word) {\n var node,\n commonPrefix = 0\n\n if (word < this.previousWord) {\n throw new Error (\"Out of order word insertion\")\n }\n\n for (var i = 0; i < word.length && i < this.previousWord.length; i++) {\n if (word[i] != this.previousWord[i]) break\n commonPrefix++\n }\n\n this.minimize(commonPrefix)\n\n if (this.uncheckedNodes.length == 0) {\n node = this.root\n } else {\n node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child\n }\n\n for (var i = commonPrefix; i < word.length; i++) {\n var nextNode = new lunr.TokenSet,\n char = word[i]\n\n node.edges[char] = nextNode\n\n this.uncheckedNodes.push({\n parent: node,\n char: char,\n child: nextNode\n })\n\n node = nextNode\n }\n\n node.final = true\n this.previousWord = word\n}\n\nlunr.TokenSet.Builder.prototype.finish = function () {\n this.minimize(0)\n}\n\nlunr.TokenSet.Builder.prototype.minimize = function (downTo) {\n for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {\n var node = this.uncheckedNodes[i],\n childKey = node.child.toString()\n\n if (childKey in this.minimizedNodes) {\n node.parent.edges[node.char] = this.minimizedNodes[childKey]\n } else {\n // Cache the key for this node since\n // we know it can't change anymore\n node.child._str = childKey\n\n this.minimizedNodes[childKey] = node.child\n }\n\n this.uncheckedNodes.pop()\n }\n}\n/*!\n * lunr.Index\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * An index contains the built index of all documents and provides a query interface\n * to the index.\n *\n * Usually instances of lunr.Index will not be created using this constructor, instead\n * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be\n * used to load previously built and serialized indexes.\n *\n * @constructor\n * @param {Object} attrs - The attributes of the built search index.\n * @param {Object} attrs.invertedIndex - An index of term/field to document reference.\n * @param {Object} attrs.fieldVectors - Field vectors\n * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.\n * @param {string[]} attrs.fields - The names of indexed document fields.\n * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.\n */\nlunr.Index = function (attrs) {\n this.invertedIndex = attrs.invertedIndex\n this.fieldVectors = attrs.fieldVectors\n this.tokenSet = attrs.tokenSet\n this.fields = attrs.fields\n this.pipeline = attrs.pipeline\n}\n\n/**\n * A result contains details of a document matching a search query.\n * @typedef {Object} lunr.Index~Result\n * @property {string} ref - The reference of the document this result represents.\n * @property {number} score - A number between 0 and 1 representing how similar this document is to the query.\n * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match.\n */\n\n/**\n * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple\n * query language which itself is parsed into an instance of lunr.Query.\n *\n * For programmatically building queries it is advised to directly use lunr.Query, the query language\n * is best used for human entered text rather than program generated text.\n *\n * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported\n * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello'\n * or 'world', though those that contain both will rank higher in the results.\n *\n * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can\n * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding\n * wildcards will increase the number of documents that will be found but can also have a negative\n * impact on query performance, especially with wildcards at the beginning of a term.\n *\n * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term\n * hello in the title field will match this query. Using a field not present in the index will lead\n * to an error being thrown.\n *\n * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term\n * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported\n * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.\n * Avoid large values for edit distance to improve query performance.\n *\n * Each term also supports a presence modifier. By default a term's presence in document is optional, however\n * this can be changed to either required or prohibited. For a term's presence to be required in a document the\n * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and\n * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not\n * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.\n *\n * To escape special characters the backslash character '\\' can be used, this allows searches to include\n * characters that would normally be considered modifiers, e.g. `foo\\~2` will search for a term \"foo~2\" instead\n * of attempting to apply a boost of 2 to the search term \"foo\".\n *\n * @typedef {string} lunr.Index~QueryString\n * @example Simple single term query\n * hello\n * @example Multiple term query\n * hello world\n * @example term scoped to a field\n * title:hello\n * @example term with a boost of 10\n * hello^10\n * @example term with an edit distance of 2\n * hello~2\n * @example terms with presence modifiers\n * -foo +bar baz\n */\n\n/**\n * Performs a search against the index using lunr query syntax.\n *\n * Results will be returned sorted by their score, the most relevant results\n * will be returned first. For details on how the score is calculated, please see\n * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.\n *\n * For more programmatic querying use lunr.Index#query.\n *\n * @param {lunr.Index~QueryString} queryString - A string containing a lunr query.\n * @throws {lunr.QueryParseError} If the passed query string cannot be parsed.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.search = function (queryString) {\n return this.query(function (query) {\n var parser = new lunr.QueryParser(queryString, query)\n parser.parse()\n })\n}\n\n/**\n * A query builder callback provides a query object to be used to express\n * the query to perform on the index.\n *\n * @callback lunr.Index~queryBuilder\n * @param {lunr.Query} query - The query object to build up.\n * @this lunr.Query\n */\n\n/**\n * Performs a query against the index using the yielded lunr.Query object.\n *\n * If performing programmatic queries against the index, this method is preferred\n * over lunr.Index#search so as to avoid the additional query parsing overhead.\n *\n * A query object is yielded to the supplied function which should be used to\n * express the query to be run against the index.\n *\n * Note that although this function takes a callback parameter it is _not_ an\n * asynchronous operation, the callback is just yielded a query object to be\n * customized.\n *\n * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.query = function (fn) {\n // for each query clause\n // * process terms\n // * expand terms from token set\n // * find matching documents and metadata\n // * get document vectors\n // * score documents\n\n var query = new lunr.Query(this.fields),\n matchingFields = Object.create(null),\n queryVectors = Object.create(null),\n termFieldCache = Object.create(null),\n requiredMatches = Object.create(null),\n prohibitedMatches = Object.create(null)\n\n /*\n * To support field level boosts a query vector is created per\n * field. An empty vector is eagerly created to support negated\n * queries.\n */\n for (var i = 0; i < this.fields.length; i++) {\n queryVectors[this.fields[i]] = new lunr.Vector\n }\n\n fn.call(query, query)\n\n for (var i = 0; i < query.clauses.length; i++) {\n /*\n * Unless the pipeline has been disabled for this term, which is\n * the case for terms with wildcards, we need to pass the clause\n * term through the search pipeline. A pipeline returns an array\n * of processed terms. Pipeline functions may expand the passed\n * term, which means we may end up performing multiple index lookups\n * for a single query term.\n */\n var clause = query.clauses[i],\n terms = null,\n clauseMatches = lunr.Set.empty\n\n if (clause.usePipeline) {\n terms = this.pipeline.runString(clause.term, {\n fields: clause.fields\n })\n } else {\n terms = [clause.term]\n }\n\n for (var m = 0; m < terms.length; m++) {\n var term = terms[m]\n\n /*\n * Each term returned from the pipeline needs to use the same query\n * clause object, e.g. the same boost and or edit distance. The\n * simplest way to do this is to re-use the clause object but mutate\n * its term property.\n */\n clause.term = term\n\n /*\n * From the term in the clause we create a token set which will then\n * be used to intersect the indexes token set to get a list of terms\n * to lookup in the inverted index\n */\n var termTokenSet = lunr.TokenSet.fromClause(clause),\n expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()\n\n /*\n * If a term marked as required does not exist in the tokenSet it is\n * impossible for the search to return any matches. We set all the field\n * scoped required matches set to empty and stop examining any further\n * clauses.\n */\n if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = lunr.Set.empty\n }\n\n break\n }\n\n for (var j = 0; j < expandedTerms.length; j++) {\n /*\n * For each term get the posting and termIndex, this is required for\n * building the query vector.\n */\n var expandedTerm = expandedTerms[j],\n posting = this.invertedIndex[expandedTerm],\n termIndex = posting._index\n\n for (var k = 0; k < clause.fields.length; k++) {\n /*\n * For each field that this query term is scoped by (by default\n * all fields are in scope) we need to get all the document refs\n * that have this term in that field.\n *\n * The posting is the entry in the invertedIndex for the matching\n * term from above.\n */\n var field = clause.fields[k],\n fieldPosting = posting[field],\n matchingDocumentRefs = Object.keys(fieldPosting),\n termField = expandedTerm + \"/\" + field,\n matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)\n\n /*\n * if the presence of this term is required ensure that the matching\n * documents are added to the set of required matches for this clause.\n *\n */\n if (clause.presence == lunr.Query.presence.REQUIRED) {\n clauseMatches = clauseMatches.union(matchingDocumentsSet)\n\n if (requiredMatches[field] === undefined) {\n requiredMatches[field] = lunr.Set.complete\n }\n }\n\n /*\n * if the presence of this term is prohibited ensure that the matching\n * documents are added to the set of prohibited matches for this field,\n * creating that set if it does not yet exist.\n */\n if (clause.presence == lunr.Query.presence.PROHIBITED) {\n if (prohibitedMatches[field] === undefined) {\n prohibitedMatches[field] = lunr.Set.empty\n }\n\n prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)\n\n /*\n * Prohibited matches should not be part of the query vector used for\n * similarity scoring and no metadata should be extracted so we continue\n * to the next field\n */\n continue\n }\n\n /*\n * The query field vector is populated using the termIndex found for\n * the term and a unit value with the appropriate boost applied.\n * Using upsert because there could already be an entry in the vector\n * for the term we are working with. In that case we just add the scores\n * together.\n */\n queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })\n\n /**\n * If we've already seen this term, field combo then we've already collected\n * the matching documents and metadata, no need to go through all that again\n */\n if (termFieldCache[termField]) {\n continue\n }\n\n for (var l = 0; l < matchingDocumentRefs.length; l++) {\n /*\n * All metadata for this term/field/document triple\n * are then extracted and collected into an instance\n * of lunr.MatchData ready to be returned in the query\n * results\n */\n var matchingDocumentRef = matchingDocumentRefs[l],\n matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field),\n metadata = fieldPosting[matchingDocumentRef],\n fieldMatch\n\n if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) {\n matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata)\n } else {\n fieldMatch.add(expandedTerm, field, metadata)\n }\n\n }\n\n termFieldCache[termField] = true\n }\n }\n }\n\n /**\n * If the presence was required we need to update the requiredMatches field sets.\n * We do this after all fields for the term have collected their matches because\n * the clause terms presence is required in _any_ of the fields not _all_ of the\n * fields.\n */\n if (clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)\n }\n }\n }\n\n /**\n * Need to combine the field scoped required and prohibited\n * matching documents into a global set of required and prohibited\n * matches\n */\n var allRequiredMatches = lunr.Set.complete,\n allProhibitedMatches = lunr.Set.empty\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i]\n\n if (requiredMatches[field]) {\n allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])\n }\n\n if (prohibitedMatches[field]) {\n allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])\n }\n }\n\n var matchingFieldRefs = Object.keys(matchingFields),\n results = [],\n matches = Object.create(null)\n\n /*\n * If the query is negated (contains only prohibited terms)\n * we need to get _all_ fieldRefs currently existing in the\n * index. This is only done when we know that the query is\n * entirely prohibited terms to avoid any cost of getting all\n * fieldRefs unnecessarily.\n *\n * Additionally, blank MatchData must be created to correctly\n * populate the results.\n */\n if (query.isNegated()) {\n matchingFieldRefs = Object.keys(this.fieldVectors)\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n var matchingFieldRef = matchingFieldRefs[i]\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)\n matchingFields[matchingFieldRef] = new lunr.MatchData\n }\n }\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n /*\n * Currently we have document fields that match the query, but we\n * need to return documents. The matchData and scores are combined\n * from multiple fields belonging to the same document.\n *\n * Scores are calculated by field, using the query vectors created\n * above, and combined into a final document score using addition.\n */\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),\n docRef = fieldRef.docRef\n\n if (!allRequiredMatches.contains(docRef)) {\n continue\n }\n\n if (allProhibitedMatches.contains(docRef)) {\n continue\n }\n\n var fieldVector = this.fieldVectors[fieldRef],\n score = queryVectors[fieldRef.fieldName].similarity(fieldVector),\n docMatch\n\n if ((docMatch = matches[docRef]) !== undefined) {\n docMatch.score += score\n docMatch.matchData.combine(matchingFields[fieldRef])\n } else {\n var match = {\n ref: docRef,\n score: score,\n matchData: matchingFields[fieldRef]\n }\n matches[docRef] = match\n results.push(match)\n }\n }\n\n /*\n * Sort the results objects by score, highest first.\n */\n return results.sort(function (a, b) {\n return b.score - a.score\n })\n}\n\n/**\n * Prepares the index for JSON serialization.\n *\n * The schema for this JSON blob will be described in a\n * separate JSON schema file.\n *\n * @returns {Object}\n */\nlunr.Index.prototype.toJSON = function () {\n var invertedIndex = Object.keys(this.invertedIndex)\n .sort()\n .map(function (term) {\n return [term, this.invertedIndex[term]]\n }, this)\n\n var fieldVectors = Object.keys(this.fieldVectors)\n .map(function (ref) {\n return [ref, this.fieldVectors[ref].toJSON()]\n }, this)\n\n return {\n version: lunr.version,\n fields: this.fields,\n fieldVectors: fieldVectors,\n invertedIndex: invertedIndex,\n pipeline: this.pipeline.toJSON()\n }\n}\n\n/**\n * Loads a previously serialized lunr.Index\n *\n * @param {Object} serializedIndex - A previously serialized lunr.Index\n * @returns {lunr.Index}\n */\nlunr.Index.load = function (serializedIndex) {\n var attrs = {},\n fieldVectors = {},\n serializedVectors = serializedIndex.fieldVectors,\n invertedIndex = Object.create(null),\n serializedInvertedIndex = serializedIndex.invertedIndex,\n tokenSetBuilder = new lunr.TokenSet.Builder,\n pipeline = lunr.Pipeline.load(serializedIndex.pipeline)\n\n if (serializedIndex.version != lunr.version) {\n lunr.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr '\" + lunr.version + \"' does not match serialized index '\" + serializedIndex.version + \"'\")\n }\n\n for (var i = 0; i < serializedVectors.length; i++) {\n var tuple = serializedVectors[i],\n ref = tuple[0],\n elements = tuple[1]\n\n fieldVectors[ref] = new lunr.Vector(elements)\n }\n\n for (var i = 0; i < serializedInvertedIndex.length; i++) {\n var tuple = serializedInvertedIndex[i],\n term = tuple[0],\n posting = tuple[1]\n\n tokenSetBuilder.insert(term)\n invertedIndex[term] = posting\n }\n\n tokenSetBuilder.finish()\n\n attrs.fields = serializedIndex.fields\n\n attrs.fieldVectors = fieldVectors\n attrs.invertedIndex = invertedIndex\n attrs.tokenSet = tokenSetBuilder.root\n attrs.pipeline = pipeline\n\n return new lunr.Index(attrs)\n}\n/*!\n * lunr.Builder\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Builder performs indexing on a set of documents and\n * returns instances of lunr.Index ready for querying.\n *\n * All configuration of the index is done via the builder, the\n * fields to index, the document reference, the text processing\n * pipeline and document scoring parameters are all set on the\n * builder before indexing.\n *\n * @constructor\n * @property {string} _ref - Internal reference to the document reference field.\n * @property {string[]} _fields - Internal reference to the document fields to index.\n * @property {object} invertedIndex - The inverted index maps terms to document fields.\n * @property {object} documentTermFrequencies - Keeps track of document term frequencies.\n * @property {object} documentLengths - Keeps track of the length of documents added to the index.\n * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.\n * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.\n * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.\n * @property {number} documentCount - Keeps track of the total number of documents indexed.\n * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.\n * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.\n * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.\n * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.\n */\nlunr.Builder = function () {\n this._ref = \"id\"\n this._fields = Object.create(null)\n this._documents = Object.create(null)\n this.invertedIndex = Object.create(null)\n this.fieldTermFrequencies = {}\n this.fieldLengths = {}\n this.tokenizer = lunr.tokenizer\n this.pipeline = new lunr.Pipeline\n this.searchPipeline = new lunr.Pipeline\n this.documentCount = 0\n this._b = 0.75\n this._k1 = 1.2\n this.termIndex = 0\n this.metadataWhitelist = []\n}\n\n/**\n * Sets the document field used as the document reference. Every document must have this field.\n * The type of this field in the document should be a string, if it is not a string it will be\n * coerced into a string by calling toString.\n *\n * The default ref is 'id'.\n *\n * The ref should _not_ be changed during indexing, it should be set before any documents are\n * added to the index. Changing it during indexing can lead to inconsistent results.\n *\n * @param {string} ref - The name of the reference field in the document.\n */\nlunr.Builder.prototype.ref = function (ref) {\n this._ref = ref\n}\n\n/**\n * A function that is used to extract a field from a document.\n *\n * Lunr expects a field to be at the top level of a document, if however the field\n * is deeply nested within a document an extractor function can be used to extract\n * the right field for indexing.\n *\n * @callback fieldExtractor\n * @param {object} doc - The document being added to the index.\n * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.\n * @example Extracting a nested field\n * function (doc) { return doc.nested.field }\n */\n\n/**\n * Adds a field to the list of document fields that will be indexed. Every document being\n * indexed should have this field. Null values for this field in indexed documents will\n * not cause errors but will limit the chance of that document being retrieved by searches.\n *\n * All fields should be added before adding documents to the index. Adding fields after\n * a document has been indexed will have no effect on already indexed documents.\n *\n * Fields can be boosted at build time. This allows terms within that field to have more\n * importance when ranking search results. Use a field boost to specify that matches within\n * one field are more important than other fields.\n *\n * @param {string} fieldName - The name of a field to index in all documents.\n * @param {object} attributes - Optional attributes associated with this field.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.\n * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.\n * @throws {RangeError} fieldName cannot contain unsupported characters '/'\n */\nlunr.Builder.prototype.field = function (fieldName, attributes) {\n if (/\\//.test(fieldName)) {\n throw new RangeError (\"Field '\" + fieldName + \"' contains illegal character '/'\")\n }\n\n this._fields[fieldName] = attributes || {}\n}\n\n/**\n * A parameter to tune the amount of field length normalisation that is applied when\n * calculating relevance scores. A value of 0 will completely disable any normalisation\n * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b\n * will be clamped to the range 0 - 1.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.b = function (number) {\n if (number < 0) {\n this._b = 0\n } else if (number > 1) {\n this._b = 1\n } else {\n this._b = number\n }\n}\n\n/**\n * A parameter that controls the speed at which a rise in term frequency results in term\n * frequency saturation. The default value is 1.2. Setting this to a higher value will give\n * slower saturation levels, a lower value will result in quicker saturation.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.k1 = function (number) {\n this._k1 = number\n}\n\n/**\n * Adds a document to the index.\n *\n * Before adding fields to the index the index should have been fully setup, with the document\n * ref and all fields to index already having been specified.\n *\n * The document must have a field name as specified by the ref (by default this is 'id') and\n * it should have all fields defined for indexing, though null or undefined values will not\n * cause errors.\n *\n * Entire documents can be boosted at build time. Applying a boost to a document indicates that\n * this document should rank higher in search results than other documents.\n *\n * @param {object} doc - The document to add to the index.\n * @param {object} attributes - Optional attributes associated with this document.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.\n */\nlunr.Builder.prototype.add = function (doc, attributes) {\n var docRef = doc[this._ref],\n fields = Object.keys(this._fields)\n\n this._documents[docRef] = attributes || {}\n this.documentCount += 1\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i],\n extractor = this._fields[fieldName].extractor,\n field = extractor ? extractor(doc) : doc[fieldName],\n tokens = this.tokenizer(field, {\n fields: [fieldName]\n }),\n terms = this.pipeline.run(tokens),\n fieldRef = new lunr.FieldRef (docRef, fieldName),\n fieldTerms = Object.create(null)\n\n this.fieldTermFrequencies[fieldRef] = fieldTerms\n this.fieldLengths[fieldRef] = 0\n\n // store the length of this field for this document\n this.fieldLengths[fieldRef] += terms.length\n\n // calculate term frequencies for this field\n for (var j = 0; j < terms.length; j++) {\n var term = terms[j]\n\n if (fieldTerms[term] == undefined) {\n fieldTerms[term] = 0\n }\n\n fieldTerms[term] += 1\n\n // add to inverted index\n // create an initial posting if one doesn't exist\n if (this.invertedIndex[term] == undefined) {\n var posting = Object.create(null)\n posting[\"_index\"] = this.termIndex\n this.termIndex += 1\n\n for (var k = 0; k < fields.length; k++) {\n posting[fields[k]] = Object.create(null)\n }\n\n this.invertedIndex[term] = posting\n }\n\n // add an entry for this term/fieldName/docRef to the invertedIndex\n if (this.invertedIndex[term][fieldName][docRef] == undefined) {\n this.invertedIndex[term][fieldName][docRef] = Object.create(null)\n }\n\n // store all whitelisted metadata about this token in the\n // inverted index\n for (var l = 0; l < this.metadataWhitelist.length; l++) {\n var metadataKey = this.metadataWhitelist[l],\n metadata = term.metadata[metadataKey]\n\n if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) {\n this.invertedIndex[term][fieldName][docRef][metadataKey] = []\n }\n\n this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata)\n }\n }\n\n }\n}\n\n/**\n * Calculates the average document length for this index\n *\n * @private\n */\nlunr.Builder.prototype.calculateAverageFieldLengths = function () {\n\n var fieldRefs = Object.keys(this.fieldLengths),\n numberOfFields = fieldRefs.length,\n accumulator = {},\n documentsWithField = {}\n\n for (var i = 0; i < numberOfFields; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n field = fieldRef.fieldName\n\n documentsWithField[field] || (documentsWithField[field] = 0)\n documentsWithField[field] += 1\n\n accumulator[field] || (accumulator[field] = 0)\n accumulator[field] += this.fieldLengths[fieldRef]\n }\n\n var fields = Object.keys(this._fields)\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i]\n accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]\n }\n\n this.averageFieldLength = accumulator\n}\n\n/**\n * Builds a vector space model of every document using lunr.Vector\n *\n * @private\n */\nlunr.Builder.prototype.createFieldVectors = function () {\n var fieldVectors = {},\n fieldRefs = Object.keys(this.fieldTermFrequencies),\n fieldRefsLength = fieldRefs.length,\n termIdfCache = Object.create(null)\n\n for (var i = 0; i < fieldRefsLength; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n fieldName = fieldRef.fieldName,\n fieldLength = this.fieldLengths[fieldRef],\n fieldVector = new lunr.Vector,\n termFrequencies = this.fieldTermFrequencies[fieldRef],\n terms = Object.keys(termFrequencies),\n termsLength = terms.length\n\n\n var fieldBoost = this._fields[fieldName].boost || 1,\n docBoost = this._documents[fieldRef.docRef].boost || 1\n\n for (var j = 0; j < termsLength; j++) {\n var term = terms[j],\n tf = termFrequencies[term],\n termIndex = this.invertedIndex[term]._index,\n idf, score, scoreWithPrecision\n\n if (termIdfCache[term] === undefined) {\n idf = lunr.idf(this.invertedIndex[term], this.documentCount)\n termIdfCache[term] = idf\n } else {\n idf = termIdfCache[term]\n }\n\n score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)\n score *= fieldBoost\n score *= docBoost\n scoreWithPrecision = Math.round(score * 1000) / 1000\n // Converts 1.23456789 to 1.234.\n // Reducing the precision so that the vectors take up less\n // space when serialised. Doing it now so that they behave\n // the same before and after serialisation. Also, this is\n // the fastest approach to reducing a number's precision in\n // JavaScript.\n\n fieldVector.insert(termIndex, scoreWithPrecision)\n }\n\n fieldVectors[fieldRef] = fieldVector\n }\n\n this.fieldVectors = fieldVectors\n}\n\n/**\n * Creates a token set of all tokens in the index using lunr.TokenSet\n *\n * @private\n */\nlunr.Builder.prototype.createTokenSet = function () {\n this.tokenSet = lunr.TokenSet.fromArray(\n Object.keys(this.invertedIndex).sort()\n )\n}\n\n/**\n * Builds the index, creating an instance of lunr.Index.\n *\n * This completes the indexing process and should only be called\n * once all documents have been added to the index.\n *\n * @returns {lunr.Index}\n */\nlunr.Builder.prototype.build = function () {\n this.calculateAverageFieldLengths()\n this.createFieldVectors()\n this.createTokenSet()\n\n return new lunr.Index({\n invertedIndex: this.invertedIndex,\n fieldVectors: this.fieldVectors,\n tokenSet: this.tokenSet,\n fields: Object.keys(this._fields),\n pipeline: this.searchPipeline\n })\n}\n\n/**\n * Applies a plugin to the index builder.\n *\n * A plugin is a function that is called with the index builder as its context.\n * Plugins can be used to customise or extend the behaviour of the index\n * in some way. A plugin is just a function, that encapsulated the custom\n * behaviour that should be applied when building the index.\n *\n * The plugin function will be called with the index builder as its argument, additional\n * arguments can also be passed when calling use. The function will be called\n * with the index builder as its context.\n *\n * @param {Function} plugin The plugin to apply.\n */\nlunr.Builder.prototype.use = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1)\n args.unshift(this)\n fn.apply(this, args)\n}\n/**\n * Contains and collects metadata about a matching document.\n * A single instance of lunr.MatchData is returned as part of every\n * lunr.Index~Result.\n *\n * @constructor\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n * @property {object} metadata - A cloned collection of metadata associated with this document.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData = function (term, field, metadata) {\n var clonedMetadata = Object.create(null),\n metadataKeys = Object.keys(metadata || {})\n\n // Cloning the metadata to prevent the original\n // being mutated during match data combination.\n // Metadata is kept in an array within the inverted\n // index so cloning the data can be done with\n // Array#slice\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n clonedMetadata[key] = metadata[key].slice()\n }\n\n this.metadata = Object.create(null)\n\n if (term !== undefined) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = clonedMetadata\n }\n}\n\n/**\n * An instance of lunr.MatchData will be created for every term that matches a\n * document. However only one instance is required in a lunr.Index~Result. This\n * method combines metadata from another instance of lunr.MatchData with this\n * objects metadata.\n *\n * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData.prototype.combine = function (otherMatchData) {\n var terms = Object.keys(otherMatchData.metadata)\n\n for (var i = 0; i < terms.length; i++) {\n var term = terms[i],\n fields = Object.keys(otherMatchData.metadata[term])\n\n if (this.metadata[term] == undefined) {\n this.metadata[term] = Object.create(null)\n }\n\n for (var j = 0; j < fields.length; j++) {\n var field = fields[j],\n keys = Object.keys(otherMatchData.metadata[term][field])\n\n if (this.metadata[term][field] == undefined) {\n this.metadata[term][field] = Object.create(null)\n }\n\n for (var k = 0; k < keys.length; k++) {\n var key = keys[k]\n\n if (this.metadata[term][field][key] == undefined) {\n this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]\n } else {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])\n }\n\n }\n }\n }\n}\n\n/**\n * Add metadata for a term/field pair to this instance of match data.\n *\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n */\nlunr.MatchData.prototype.add = function (term, field, metadata) {\n if (!(term in this.metadata)) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = metadata\n return\n }\n\n if (!(field in this.metadata[term])) {\n this.metadata[term][field] = metadata\n return\n }\n\n var metadataKeys = Object.keys(metadata)\n\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n\n if (key in this.metadata[term][field]) {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])\n } else {\n this.metadata[term][field][key] = metadata[key]\n }\n }\n}\n/**\n * A lunr.Query provides a programmatic way of defining queries to be performed\n * against a {@link lunr.Index}.\n *\n * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method\n * so the query object is pre-initialized with the right index fields.\n *\n * @constructor\n * @property {lunr.Query~Clause[]} clauses - An array of query clauses.\n * @property {string[]} allFields - An array of all available fields in a lunr.Index.\n */\nlunr.Query = function (allFields) {\n this.clauses = []\n this.allFields = allFields\n}\n\n/**\n * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause.\n *\n * This allows wildcards to be added to the beginning and end of a term without having to manually do any string\n * concatenation.\n *\n * The wildcard constants can be bitwise combined to select both leading and trailing wildcards.\n *\n * @constant\n * @default\n * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour\n * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists\n * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with trailing wildcard\n * query.term('foo', { wildcard: lunr.Query.wildcard.TRAILING })\n * @example query term with leading and trailing wildcard\n * query.term('foo', {\n * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING\n * })\n */\n\nlunr.Query.wildcard = new String (\"*\")\nlunr.Query.wildcard.NONE = 0\nlunr.Query.wildcard.LEADING = 1\nlunr.Query.wildcard.TRAILING = 2\n\n/**\n * Constants for indicating what kind of presence a term must have in matching documents.\n *\n * @constant\n * @enum {number}\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with required presence\n * query.term('foo', { presence: lunr.Query.presence.REQUIRED })\n */\nlunr.Query.presence = {\n /**\n * Term's presence in a document is optional, this is the default value.\n */\n OPTIONAL: 1,\n\n /**\n * Term's presence in a document is required, documents that do not contain\n * this term will not be returned.\n */\n REQUIRED: 2,\n\n /**\n * Term's presence in a document is prohibited, documents that do contain\n * this term will not be returned.\n */\n PROHIBITED: 3\n}\n\n/**\n * A single clause in a {@link lunr.Query} contains a term and details on how to\n * match that term against a {@link lunr.Index}.\n *\n * @typedef {Object} lunr.Query~Clause\n * @property {string[]} fields - The fields in an index this clause should be matched against.\n * @property {number} [boost=1] - Any boost that should be applied when matching this clause.\n * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.\n * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.\n * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.\n * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.\n */\n\n/**\n * Adds a {@link lunr.Query~Clause} to this query.\n *\n * Unless the clause contains the fields to be matched all fields will be matched. In addition\n * a default boost of 1 is applied to the clause.\n *\n * @param {lunr.Query~Clause} clause - The clause to add to this query.\n * @see lunr.Query~Clause\n * @returns {lunr.Query}\n */\nlunr.Query.prototype.clause = function (clause) {\n if (!('fields' in clause)) {\n clause.fields = this.allFields\n }\n\n if (!('boost' in clause)) {\n clause.boost = 1\n }\n\n if (!('usePipeline' in clause)) {\n clause.usePipeline = true\n }\n\n if (!('wildcard' in clause)) {\n clause.wildcard = lunr.Query.wildcard.NONE\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) {\n clause.term = \"*\" + clause.term\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) {\n clause.term = \"\" + clause.term + \"*\"\n }\n\n if (!('presence' in clause)) {\n clause.presence = lunr.Query.presence.OPTIONAL\n }\n\n this.clauses.push(clause)\n\n return this\n}\n\n/**\n * A negated query is one in which every clause has a presence of\n * prohibited. These queries require some special processing to return\n * the expected results.\n *\n * @returns boolean\n */\nlunr.Query.prototype.isNegated = function () {\n for (var i = 0; i < this.clauses.length; i++) {\n if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}\n * to the list of clauses that make up this query.\n *\n * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion\n * to a token or token-like string should be done before calling this method.\n *\n * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an\n * array, each term in the array will share the same options.\n *\n * @param {object|object[]} term - The term(s) to add to the query.\n * @param {object} [options] - Any additional properties to add to the query clause.\n * @returns {lunr.Query}\n * @see lunr.Query#clause\n * @see lunr.Query~Clause\n * @example adding a single term to a query\n * query.term(\"foo\")\n * @example adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard\n * query.term(\"foo\", {\n * fields: [\"title\"],\n * boost: 10,\n * wildcard: lunr.Query.wildcard.TRAILING\n * })\n * @example using lunr.tokenizer to convert a string to tokens before using them as terms\n * query.term(lunr.tokenizer(\"foo bar\"))\n */\nlunr.Query.prototype.term = function (term, options) {\n if (Array.isArray(term)) {\n term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)\n return this\n }\n\n var clause = options || {}\n clause.term = term.toString()\n\n this.clause(clause)\n\n return this\n}\nlunr.QueryParseError = function (message, start, end) {\n this.name = \"QueryParseError\"\n this.message = message\n this.start = start\n this.end = end\n}\n\nlunr.QueryParseError.prototype = new Error\nlunr.QueryLexer = function (str) {\n this.lexemes = []\n this.str = str\n this.length = str.length\n this.pos = 0\n this.start = 0\n this.escapeCharPositions = []\n}\n\nlunr.QueryLexer.prototype.run = function () {\n var state = lunr.QueryLexer.lexText\n\n while (state) {\n state = state(this)\n }\n}\n\nlunr.QueryLexer.prototype.sliceString = function () {\n var subSlices = [],\n sliceStart = this.start,\n sliceEnd = this.pos\n\n for (var i = 0; i < this.escapeCharPositions.length; i++) {\n sliceEnd = this.escapeCharPositions[i]\n subSlices.push(this.str.slice(sliceStart, sliceEnd))\n sliceStart = sliceEnd + 1\n }\n\n subSlices.push(this.str.slice(sliceStart, this.pos))\n this.escapeCharPositions.length = 0\n\n return subSlices.join('')\n}\n\nlunr.QueryLexer.prototype.emit = function (type) {\n this.lexemes.push({\n type: type,\n str: this.sliceString(),\n start: this.start,\n end: this.pos\n })\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.escapeCharacter = function () {\n this.escapeCharPositions.push(this.pos - 1)\n this.pos += 1\n}\n\nlunr.QueryLexer.prototype.next = function () {\n if (this.pos >= this.length) {\n return lunr.QueryLexer.EOS\n }\n\n var char = this.str.charAt(this.pos)\n this.pos += 1\n return char\n}\n\nlunr.QueryLexer.prototype.width = function () {\n return this.pos - this.start\n}\n\nlunr.QueryLexer.prototype.ignore = function () {\n if (this.start == this.pos) {\n this.pos += 1\n }\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.backup = function () {\n this.pos -= 1\n}\n\nlunr.QueryLexer.prototype.acceptDigitRun = function () {\n var char, charCode\n\n do {\n char = this.next()\n charCode = char.charCodeAt(0)\n } while (charCode > 47 && charCode < 58)\n\n if (char != lunr.QueryLexer.EOS) {\n this.backup()\n }\n}\n\nlunr.QueryLexer.prototype.more = function () {\n return this.pos < this.length\n}\n\nlunr.QueryLexer.EOS = 'EOS'\nlunr.QueryLexer.FIELD = 'FIELD'\nlunr.QueryLexer.TERM = 'TERM'\nlunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'\nlunr.QueryLexer.BOOST = 'BOOST'\nlunr.QueryLexer.PRESENCE = 'PRESENCE'\n\nlunr.QueryLexer.lexField = function (lexer) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.FIELD)\n lexer.ignore()\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexTerm = function (lexer) {\n if (lexer.width() > 1) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.TERM)\n }\n\n lexer.ignore()\n\n if (lexer.more()) {\n return lunr.QueryLexer.lexText\n }\n}\n\nlunr.QueryLexer.lexEditDistance = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.EDIT_DISTANCE)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexBoost = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.BOOST)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexEOS = function (lexer) {\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n}\n\n// This matches the separator used when tokenising fields\n// within a document. These should match otherwise it is\n// not possible to search for some tokens within a document.\n//\n// It is possible for the user to change the separator on the\n// tokenizer so it _might_ clash with any other of the special\n// characters already used within the search string, e.g. :.\n//\n// This means that it is possible to change the separator in\n// such a way that makes some words unsearchable using a search\n// string.\nlunr.QueryLexer.termSeparator = lunr.tokenizer.separator\n\nlunr.QueryLexer.lexText = function (lexer) {\n while (true) {\n var char = lexer.next()\n\n if (char == lunr.QueryLexer.EOS) {\n return lunr.QueryLexer.lexEOS\n }\n\n // Escape character is '\\'\n if (char.charCodeAt(0) == 92) {\n lexer.escapeCharacter()\n continue\n }\n\n if (char == \":\") {\n return lunr.QueryLexer.lexField\n }\n\n if (char == \"~\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexEditDistance\n }\n\n if (char == \"^\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexBoost\n }\n\n // \"+\" indicates term presence is required\n // checking for length to ensure that only\n // leading \"+\" are considered\n if (char == \"+\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n // \"-\" indicates term presence is prohibited\n // checking for length to ensure that only\n // leading \"-\" are considered\n if (char == \"-\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n if (char.match(lunr.QueryLexer.termSeparator)) {\n return lunr.QueryLexer.lexTerm\n }\n }\n}\n\nlunr.QueryParser = function (str, query) {\n this.lexer = new lunr.QueryLexer (str)\n this.query = query\n this.currentClause = {}\n this.lexemeIdx = 0\n}\n\nlunr.QueryParser.prototype.parse = function () {\n this.lexer.run()\n this.lexemes = this.lexer.lexemes\n\n var state = lunr.QueryParser.parseClause\n\n while (state) {\n state = state(this)\n }\n\n return this.query\n}\n\nlunr.QueryParser.prototype.peekLexeme = function () {\n return this.lexemes[this.lexemeIdx]\n}\n\nlunr.QueryParser.prototype.consumeLexeme = function () {\n var lexeme = this.peekLexeme()\n this.lexemeIdx += 1\n return lexeme\n}\n\nlunr.QueryParser.prototype.nextClause = function () {\n var completedClause = this.currentClause\n this.query.clause(completedClause)\n this.currentClause = {}\n}\n\nlunr.QueryParser.parseClause = function (parser) {\n var lexeme = parser.peekLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.type) {\n case lunr.QueryLexer.PRESENCE:\n return lunr.QueryParser.parsePresence\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expected either a field or a term, found \" + lexeme.type\n\n if (lexeme.str.length >= 1) {\n errorMessage += \" with value '\" + lexeme.str + \"'\"\n }\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n}\n\nlunr.QueryParser.parsePresence = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.str) {\n case \"-\":\n parser.currentClause.presence = lunr.Query.presence.PROHIBITED\n break\n case \"+\":\n parser.currentClause.presence = lunr.Query.presence.REQUIRED\n break\n default:\n var errorMessage = \"unrecognised presence operator'\" + lexeme.str + \"'\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term or field, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term or field, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseField = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n if (parser.query.allFields.indexOf(lexeme.str) == -1) {\n var possibleFields = parser.query.allFields.map(function (f) { return \"'\" + f + \"'\" }).join(', '),\n errorMessage = \"unrecognised field '\" + lexeme.str + \"', possible fields: \" + possibleFields\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.fields = [lexeme.str]\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseTerm = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n parser.currentClause.term = lexeme.str.toLowerCase()\n\n if (lexeme.str.indexOf(\"*\") != -1) {\n parser.currentClause.usePipeline = false\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseEditDistance = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var editDistance = parseInt(lexeme.str, 10)\n\n if (isNaN(editDistance)) {\n var errorMessage = \"edit distance must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.editDistance = editDistance\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseBoost = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var boost = parseInt(lexeme.str, 10)\n\n if (isNaN(boost)) {\n var errorMessage = \"boost must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.boost = boost\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\n /**\n * export the module via AMD, CommonJS or as a browser global\n * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js\n */\n ;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory)\n } else if (typeof exports === 'object') {\n /**\n * Node. Does not work with strict CommonJS, but\n * only CommonJS-like enviroments that support module.exports,\n * like Node.\n */\n module.exports = factory()\n } else {\n // Browser globals (root is window)\n root.lunr = factory()\n }\n }(this, function () {\n /**\n * Just return a value to define the module export.\n * This example returns an object, but the module\n * can return a function as the exported value.\n */\n return lunr\n }))\n})();\n", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport lunr from \"lunr\"\n\nimport \"~/polyfills\"\n\nimport { Search, SearchIndexConfig } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Add support for usage with `iframe-worker` polyfill\n *\n * While `importScripts` is synchronous when executed inside of a web worker,\n * it's not possible to provide a synchronous polyfilled implementation. The\n * cool thing is that awaiting a non-Promise is a noop, so extending the type\n * definition to return a `Promise` shouldn't break anything.\n *\n * @see https://bit.ly/2PjDnXi - GitHub comment\n */\ndeclare global {\n function importScripts(...urls: string[]): Promise | void\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n */\nlet index: Search\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch (= import) multi-language support through `lunr-languages`\n *\n * This function automatically imports the stemmers necessary to process the\n * languages, which are defined through the search index configuration.\n *\n * If the worker runs inside of an `iframe` (when using `iframe-worker` as\n * a shim), the base URL for the stemmers to be loaded must be determined by\n * searching for the first `script` element with a `src` attribute, which will\n * contain the contents of this script.\n *\n * @param config - Search index configuration\n *\n * @returns Promise resolving with no result\n */\nasync function setupSearchLanguages(\n config: SearchIndexConfig\n): Promise {\n let base = \"../lunr\"\n\n /* Detect `iframe-worker` and fix base URL */\n if (typeof parent !== \"undefined\" && \"IFrameWorker\" in parent) {\n const worker = document.querySelector(\"script[src]\")!\n const [path] = worker.src.split(\"/worker\")\n\n /* Prefix base with path */\n base = base.replace(\"..\", path)\n }\n\n /* Add scripts for languages */\n const scripts = []\n for (const lang of config.lang) {\n switch (lang) {\n\n /* Add segmenter for Japanese */\n case \"ja\":\n scripts.push(`${base}/tinyseg.js`)\n break\n\n /* Add segmenter for Hindi and Thai */\n case \"hi\":\n case \"th\":\n scripts.push(`${base}/wordcut.js`)\n break\n }\n\n /* Add language support */\n if (lang !== \"en\")\n scripts.push(`${base}/min/lunr.${lang}.min.js`)\n }\n\n /* Add multi-language support */\n if (config.lang.length > 1)\n scripts.push(`${base}/min/lunr.multi.min.js`)\n\n /* Load scripts synchronously */\n if (scripts.length)\n await importScripts(\n `${base}/min/lunr.stemmer.support.min.js`,\n ...scripts\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Message handler\n *\n * @param message - Source message\n *\n * @returns Target message\n */\nexport async function handler(\n message: SearchMessage\n): Promise {\n switch (message.type) {\n\n /* Search setup message */\n case SearchMessageType.SETUP:\n await setupSearchLanguages(message.data.config)\n index = new Search(message.data)\n return {\n type: SearchMessageType.READY\n }\n\n /* Search query message */\n case SearchMessageType.QUERY:\n return {\n type: SearchMessageType.RESULT,\n data: index ? index.search(message.data) : { items: [] }\n }\n\n /* All other messages */\n default:\n throw new TypeError(\"Invalid message type\")\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Worker\n * ------------------------------------------------------------------------- */\n\n/* @ts-expect-error - expose Lunr.js in global scope, or stemmers won't work */\nself.lunr = lunr\n\n/* Handle messages */\naddEventListener(\"message\", async ev => {\n postMessage(await handler(ev.data))\n})\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Polyfills\n * ------------------------------------------------------------------------- */\n\n/* Polyfill `Object.entries` */\nif (!Object.entries)\n Object.entries = function (obj: object) {\n const data: [string, string][] = []\n for (const key of Object.keys(obj))\n // @ts-expect-error - ignore property access warning\n data.push([key, obj[key]])\n\n /* Return entries */\n return data\n }\n\n/* Polyfill `Object.values` */\nif (!Object.values)\n Object.values = function (obj: object) {\n const data: string[] = []\n for (const key of Object.keys(obj))\n // @ts-expect-error - ignore property access warning\n data.push(obj[key])\n\n /* Return values */\n return data\n }\n\n/* ------------------------------------------------------------------------- */\n\n/* Polyfills for `Element` */\nif (typeof Element !== \"undefined\") {\n\n /* Polyfill `Element.scrollTo` */\n if (!Element.prototype.scrollTo)\n Element.prototype.scrollTo = function (\n x?: ScrollToOptions | number, y?: number\n ): void {\n if (typeof x === \"object\") {\n this.scrollLeft = x.left!\n this.scrollTop = x.top!\n } else {\n this.scrollLeft = x!\n this.scrollTop = y!\n }\n }\n\n /* Polyfill `Element.replaceWith` */\n if (!Element.prototype.replaceWith)\n Element.prototype.replaceWith = function (\n ...nodes: Array\n ): void {\n const parent = this.parentNode\n if (parent) {\n if (nodes.length === 0)\n parent.removeChild(this)\n\n /* Replace children and create text nodes */\n for (let i = nodes.length - 1; i >= 0; i--) {\n let node = nodes[i]\n if (typeof node !== \"object\")\n node = document.createTextNode(node)\n else if (node.parentNode)\n node.parentNode.removeChild(node)\n\n /* Replace child or insert before previous sibling */\n if (!i)\n parent.replaceChild(node, this)\n else\n parent.insertBefore(this.previousSibling!, node)\n }\n }\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport escapeHTML from \"escape-html\"\n\nimport { SearchIndexDocument } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search document\n */\nexport interface SearchDocument extends SearchIndexDocument {\n parent?: SearchIndexDocument /* Parent article */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search document mapping\n */\nexport type SearchDocumentMap = Map\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search document mapping\n *\n * @param docs - Search index documents\n *\n * @returns Search document map\n */\nexport function setupSearchDocumentMap(\n docs: SearchIndexDocument[]\n): SearchDocumentMap {\n const documents = new Map()\n const parents = new Set()\n for (const doc of docs) {\n const [path, hash] = doc.location.split(\"#\")\n\n /* Extract location, title and tags */\n const location = doc.location\n const title = doc.title\n const tags = doc.tags\n\n /* Escape and cleanup text */\n const text = escapeHTML(doc.text)\n .replace(/\\s+(?=[,.:;!?])/g, \"\")\n .replace(/\\s+/g, \" \")\n\n /* Handle section */\n if (hash) {\n const parent = documents.get(path)!\n\n /* Ignore first section, override article */\n if (!parents.has(parent)) {\n parent.title = doc.title\n parent.text = text\n\n /* Remember that we processed the article */\n parents.add(parent)\n\n /* Add subsequent section */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n parent\n })\n }\n\n /* Add article */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n ...tags && { tags }\n })\n }\n }\n return documents\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport escapeHTML from \"escape-html\"\n\nimport { SearchIndexConfig } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search highlight function\n *\n * @param value - Value\n *\n * @returns Highlighted value\n */\nexport type SearchHighlightFn = (value: string) => string\n\n/**\n * Search highlight factory function\n *\n * @param query - Query value\n *\n * @returns Search highlight function\n */\nexport type SearchHighlightFactoryFn = (query: string) => SearchHighlightFn\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search highlighter\n *\n * @param config - Search index configuration\n * @param escape - Whether to escape HTML\n *\n * @returns Search highlight factory function\n */\nexport function setupSearchHighlighter(\n config: SearchIndexConfig, escape: boolean\n): SearchHighlightFactoryFn {\n const separator = new RegExp(config.separator, \"img\")\n const highlight = (_: unknown, data: string, term: string) => {\n return `${data}${term}`\n }\n\n /* Return factory function */\n return (query: string) => {\n query = query\n .replace(/[\\s*+\\-:~^]+/g, \" \")\n .trim()\n\n /* Create search term match expression */\n const match = new RegExp(`(^|${config.separator})(${\n query\n .replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\")\n .replace(separator, \"|\")\n })`, \"img\")\n\n /* Highlight string value */\n return value => (\n escape\n ? escapeHTML(value)\n : value\n )\n .replace(match, highlight)\n .replace(/<\\/mark>(\\s+)]*>/img, \"$1\")\n }\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query clause\n */\nexport interface SearchQueryClause {\n presence: lunr.Query.presence /* Clause presence */\n term: string /* Clause term */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search query terms\n */\nexport type SearchQueryTerms = Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Parse a search query for analysis\n *\n * @param value - Query value\n *\n * @returns Search query clauses\n */\nexport function parseSearchQuery(\n value: string\n): SearchQueryClause[] {\n const query = new (lunr as any).Query([\"title\", \"text\"])\n const parser = new (lunr as any).QueryParser(value, query)\n\n /* Parse and return query clauses */\n parser.parse()\n return query.clauses\n}\n\n/**\n * Analyze the search query clauses in regard to the search terms found\n *\n * @param query - Search query clauses\n * @param terms - Search terms\n *\n * @returns Search query terms\n */\nexport function getSearchQueryTerms(\n query: SearchQueryClause[], terms: string[]\n): SearchQueryTerms {\n const clauses = new Set(query)\n\n /* Match query clauses against terms */\n const result: SearchQueryTerms = {}\n for (let t = 0; t < terms.length; t++)\n for (const clause of clauses)\n if (terms[t].startsWith(clause.term)) {\n result[clause.term] = true\n clauses.delete(clause)\n }\n\n /* Annotate unmatched non-stopword query clauses */\n for (const clause of clauses)\n if (lunr.stopWordFilter?.(clause.term as any))\n result[clause.term] = false\n\n /* Return query terms */\n return result\n}\n", "/*\n * Copyright (c) 2016-2022 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n SearchDocument,\n SearchDocumentMap,\n setupSearchDocumentMap\n} from \"../document\"\nimport {\n SearchHighlightFactoryFn,\n setupSearchHighlighter\n} from \"../highlighter\"\nimport { SearchOptions } from \"../options\"\nimport {\n SearchQueryTerms,\n getSearchQueryTerms,\n parseSearchQuery\n} from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index configuration\n */\nexport interface SearchIndexConfig {\n lang: string[] /* Search languages */\n separator: string /* Search separator */\n}\n\n/**\n * Search index document\n */\nexport interface SearchIndexDocument {\n location: string /* Document location */\n title: string /* Document title */\n text: string /* Document text */\n tags?: string[] /* Document tags */\n boost?: number /* Document boost */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search index\n *\n * This interfaces describes the format of the `search_index.json` file which\n * is automatically built by the MkDocs search plugin.\n */\nexport interface SearchIndex {\n config: SearchIndexConfig /* Search index configuration */\n docs: SearchIndexDocument[] /* Search index documents */\n options: SearchOptions /* Search options */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search metadata\n */\nexport interface SearchMetadata {\n score: number /* Score (relevance) */\n terms: SearchQueryTerms /* Search query terms */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search result document\n */\nexport type SearchResultDocument = SearchDocument & SearchMetadata\n\n/**\n * Search result item\n */\nexport type SearchResultItem = SearchResultDocument[]\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search result\n */\nexport interface SearchResult {\n items: SearchResultItem[] /* Search result items */\n suggestions?: string[] /* Search suggestions */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute the difference of two lists of strings\n *\n * @param a - 1st list of strings\n * @param b - 2nd list of strings\n *\n * @returns Difference\n */\nfunction difference(a: string[], b: string[]): string[] {\n const [x, y] = [new Set(a), new Set(b)]\n return [\n ...new Set([...x].filter(value => !y.has(value)))\n ]\n}\n\n/* ----------------------------------------------------------------------------\n * Class\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n */\nexport class Search {\n\n /**\n * Search document mapping\n *\n * A mapping of URLs (including hash fragments) to the actual articles and\n * sections of the documentation. The search document mapping must be created\n * regardless of whether the index was prebuilt or not, as Lunr.js itself\n * only stores the actual index.\n */\n protected documents: SearchDocumentMap\n\n /**\n * Search highlight factory function\n */\n protected highlight: SearchHighlightFactoryFn\n\n /**\n * The underlying Lunr.js search index\n */\n protected index: lunr.Index\n\n /**\n * Search options\n */\n protected options: SearchOptions\n\n /**\n * Create the search integration\n *\n * @param data - Search index\n */\n public constructor({ config, docs, options }: SearchIndex) {\n this.options = options\n\n /* Set up document map and highlighter factory */\n this.documents = setupSearchDocumentMap(docs)\n this.highlight = setupSearchHighlighter(config, false)\n\n /* Set separator for tokenizer */\n lunr.tokenizer.separator = new RegExp(config.separator)\n\n /* Create search index */\n this.index = lunr(function () {\n\n /* Set up multi-language support */\n if (config.lang.length === 1 && config.lang[0] !== \"en\") {\n this.use((lunr as any)[config.lang[0]])\n } else if (config.lang.length > 1) {\n this.use((lunr as any).multiLanguage(...config.lang))\n }\n\n /* Compute functions to be removed from the pipeline */\n const fns = difference([\n \"trimmer\", \"stopWordFilter\", \"stemmer\"\n ], options.pipeline)\n\n /* Remove functions from the pipeline for registered languages */\n for (const lang of config.lang.map(language => (\n language === \"en\" ? lunr : (lunr as any)[language]\n ))) {\n for (const fn of fns) {\n this.pipeline.remove(lang[fn])\n this.searchPipeline.remove(lang[fn])\n }\n }\n\n /* Set up reference */\n this.ref(\"location\")\n\n /* Set up fields */\n this.field(\"title\", { boost: 1e3 })\n this.field(\"text\")\n this.field(\"tags\", { boost: 1e6, extractor: doc => {\n const { tags = [] } = doc as SearchDocument\n return tags.reduce((list, tag) => [\n ...list,\n ...lunr.tokenizer(tag)\n ], [] as lunr.Token[])\n } })\n\n /* Index documents */\n for (const doc of docs)\n this.add(doc, { boost: doc.boost })\n })\n }\n\n /**\n * Search for matching documents\n *\n * The search index which MkDocs provides is divided up into articles, which\n * contain the whole content of the individual pages, and sections, which only\n * contain the contents of the subsections obtained by breaking the individual\n * pages up at `h1` ... `h6`. As there may be many sections on different pages\n * with identical titles (for example within this very project, e.g. \"Usage\"\n * or \"Installation\"), they need to be put into the context of the containing\n * page. For this reason, section results are grouped within their respective\n * articles which are the top-level results that are returned.\n *\n * @param query - Query value\n *\n * @returns Search results\n */\n public search(query: string): SearchResult {\n if (query) {\n try {\n const highlight = this.highlight(query)\n\n /* Parse query to extract clauses for analysis */\n const clauses = parseSearchQuery(query)\n .filter(clause => (\n clause.presence !== lunr.Query.presence.PROHIBITED\n ))\n\n /* Perform search and post-process results */\n const groups = this.index.search(`${query}*`)\n\n /* Apply post-query boosts based on title and search query terms */\n .reduce((item, { ref, score, matchData }) => {\n const document = this.documents.get(ref)\n if (typeof document !== \"undefined\") {\n const { location, title, text, tags, parent } = document\n\n /* Compute and analyze search query terms */\n const terms = getSearchQueryTerms(\n clauses,\n Object.keys(matchData.metadata)\n )\n\n /* Highlight title and text and apply post-query boosts */\n const boost = +!parent + +Object.values(terms).every(t => t)\n item.push({\n location,\n title: highlight(title),\n text: highlight(text),\n ...tags && { tags: tags.map(highlight) },\n score: score * (1 + boost),\n terms\n })\n }\n return item\n }, [])\n\n /* Sort search results again after applying boosts */\n .sort((a, b) => b.score - a.score)\n\n /* Group search results by page */\n .reduce((items, result) => {\n const document = this.documents.get(result.location)\n if (typeof document !== \"undefined\") {\n const ref = \"parent\" in document\n ? document.parent!.location\n : document.location\n items.set(ref, [...items.get(ref) || [], result])\n }\n return items\n }, new Map())\n\n /* Generate search suggestions, if desired */\n let suggestions: string[] | undefined\n if (this.options.suggestions) {\n const titles = this.index.query(builder => {\n for (const clause of clauses)\n builder.term(clause.term, {\n fields: [\"title\"],\n presence: lunr.Query.presence.REQUIRED,\n wildcard: lunr.Query.wildcard.TRAILING\n })\n })\n\n /* Retrieve suggestions for best match */\n suggestions = titles.length\n ? Object.keys(titles[0].matchData.metadata)\n : []\n }\n\n /* Return items and suggestions */\n return {\n items: [...groups.values()],\n ...typeof suggestions !== \"undefined\" && { suggestions }\n }\n\n /* Log errors to console (for now) */\n } catch {\n console.warn(`Invalid query: ${query} \u2013 see https://bit.ly/2s3ChXG`)\n }\n }\n\n /* Return nothing in case of error or empty query */\n return { items: [] }\n }\n}\n"], + "mappings": "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L,CAAI,KACrDD,EAAIC,EAER,CAEA,OAAAG,EAAKP,EACLQ,EAAMzB,EACFwB,EAAG,KAAKJ,CAAC,GAAKK,EAAI,KAAKL,CAAC,IAC1BI,EAAKjB,EACLa,EAAIA,EAAE,QAAQI,EAAG,EAAE,GAKjBD,GAAW,MACbH,EAAIG,EAAQ,YAAY,EAAIH,EAAE,OAAO,CAAC,GAGjCA,CACT,EAEA,OAAO,SAAUhD,EAAO,CACtB,OAAOA,EAAM,OAAO+C,CAAa,CACnC,CACF,EAAG,EAEHpG,EAAK,SAAS,iBAAiBA,EAAK,QAAS,SAAS,EACtD;AAAA;AAAA;AAAA,GAkBAA,EAAK,uBAAyB,SAAU8G,EAAW,CACjD,IAAIC,EAAQD,EAAU,OAAO,SAAU7D,EAAM+D,EAAU,CACrD,OAAA/D,EAAK+D,GAAYA,EACV/D,CACT,EAAG,CAAC,CAAC,EAEL,OAAO,SAAUI,EAAO,CACtB,GAAIA,GAAS0D,EAAM1D,EAAM,SAAS,KAAOA,EAAM,SAAS,EAAG,OAAOA,CACpE,CACF,EAeArD,EAAK,eAAiBA,EAAK,uBAAuB,CAChD,IACA,OACA,QACA,SACA,QACA,MACA,SACA,OACA,KACA,QACA,KACA,MACA,MACA,MACA,KACA,KACA,KACA,UACA,OACA,MACA,KACA,MACA,SACA,QACA,OACA,MACA,KACA,OACA,SACA,OACA,OACA,QACA,MACA,OACA,MACA,MACA,MACA,MACA,OACA,KACA,MACA,OACA,MACA,MACA,MACA,UACA,IACA,KACA,KACA,OACA,KACA,KACA,MACA,OACA,QACA,MACA,OACA,SACA,MACA,KACA,QACA,OACA,OACA,KACA,UACA,KACA,MACA,MACA,KACA,MACA,QACA,KACA,OACA,KACA,QACA,MACA,MACA,SACA,OACA,MACA,OACA,MACA,SACA,QACA,KACA,OACA,OACA,OACA,MACA,QACA,OACA,OACA,QACA,QACA,OACA,OACA,MACA,KACA,MACA,OACA,KACA,QACA,MACA,KACA,OACA,OACA,OACA,QACA,QACA,QACA,MACA,OACA,MACA,OACA,OACA,QACA,MACA,MACA,MACF,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", + "names": ["require_lunr", "__commonJSMin", "exports", "module", "lunr", "config", "builder", "global", "message", "obj", "clone", "keys", "key", "val", "docRef", "fieldName", "stringValue", "s", "n", "fieldRef", "elements", "i", "other", "object", "a", "b", "intersection", "element", "posting", "documentCount", "documentsWithTerm", "x", "str", "metadata", "fn", "t", "len", "tokens", "sliceEnd", "sliceStart", "char", "sliceLength", "tokenMetadata", "label", "isRegistered", "serialised", "pipeline", "fnName", "fns", "existingFn", "newFn", "pos", "stackLength", "memo", "j", "result", "k", "token", "index", "start", "end", "pivotPoint", "pivotIndex", "insertIdx", "position", "sumOfSquares", "elementsLength", "otherVector", "dotProduct", "aLen", "bLen", "aVal", "bVal", "output", "step2list", "step3list", "c", "v", "C", "V", "mgr0", "meq1", "mgr1", "s_v", "re_mgr0", "re_mgr1", "re_meq1", "re_s_v", "re_1a", "re2_1a", "re_1b", "re2_1b", "re_1b_2", "re2_1b_2", "re3_1b_2", "re4_1b_2", "re_1c", "re_2", "re_3", "re_4", "re2_4", "re_5", "re_5_1", "re3_5", "porterStemmer", "w", "stem", "suffix", "firstch", "re", "re2", "re3", "re4", "fp", "stopWords", "words", "stopWord", "arr", "clause", "editDistance", "root", "stack", "frame", "noEditNode", "insertionNode", "substitutionNode", "charA", "charB", "transposeNode", "node", "final", "next", "edges", "edge", "labels", "qEdges", "qLen", "nEdges", "nLen", "q", "qEdge", "nEdge", "qNode", "word", "commonPrefix", "nextNode", "downTo", "childKey", "attrs", "queryString", "query", "parser", "matchingFields", "queryVectors", "termFieldCache", "requiredMatches", "prohibitedMatches", "terms", "clauseMatches", "m", "term", "termTokenSet", "expandedTerms", "field", "expandedTerm", "termIndex", "fieldPosting", "matchingDocumentRefs", "termField", "matchingDocumentsSet", "l", "matchingDocumentRef", "matchingFieldRef", "fieldMatch", "allRequiredMatches", "allProhibitedMatches", "matchingFieldRefs", "results", "matches", "fieldVector", "score", "docMatch", "match", "invertedIndex", "fieldVectors", "ref", "serializedIndex", "serializedVectors", "serializedInvertedIndex", "tokenSetBuilder", "tuple", "attributes", "number", "doc", "fields", "extractor", "fieldTerms", "metadataKey", "fieldRefs", "numberOfFields", "accumulator", "documentsWithField", "fieldRefsLength", "termIdfCache", "fieldLength", "termFrequencies", "termsLength", "fieldBoost", "docBoost", "tf", "idf", "scoreWithPrecision", "args", "clonedMetadata", "metadataKeys", "otherMatchData", "allFields", "options", "state", "subSlices", "type", "charCode", "lexer", "lexeme", "completedClause", "errorMessage", "nextLexeme", "possibleFields", "f", "boost", "factory", "require_escape_html", "__commonJSMin", "exports", "module", "matchHtmlRegExp", "escapeHtml", "string", "str", "match", "escape", "html", "index", "lastIndex", "import_lunr", "obj", "data", "key", "x", "y", "nodes", "parent", "i", "node", "import_escape_html", "setupSearchDocumentMap", "docs", "documents", "parents", "doc", "path", "hash", "location", "title", "tags", "text", "escapeHTML", "parent", "__spreadValues", "import_escape_html", "setupSearchHighlighter", "config", "escape", "separator", "highlight", "_", "data", "term", "query", "match", "value", "escapeHTML", "parseSearchQuery", "value", "query", "getSearchQueryTerms", "terms", "_a", "clauses", "result", "t", "clause", "difference", "a", "b", "x", "y", "value", "Search", "config", "docs", "options", "setupSearchDocumentMap", "setupSearchHighlighter", "fns", "lang", "language", "fn", "doc", "tags", "list", "tag", "query", "highlight", "clauses", "parseSearchQuery", "clause", "groups", "item", "ref", "score", "matchData", "document", "location", "title", "text", "parent", "terms", "getSearchQueryTerms", "boost", "t", "__spreadProps", "__spreadValues", "items", "result", "suggestions", "titles", "builder", "e", "index", "setupSearchLanguages", "config", "__async", "base", "worker", "path", "scripts", "lang", "handler", "message", "Search", "lunr", "ev"] +} diff --git a/assets/stylesheets/main.80dcb947.min.css b/assets/stylesheets/main.80dcb947.min.css new file mode 100644 index 00000000..1846d835 --- /dev/null +++ b/assets/stylesheets/main.80dcb947.min.css @@ -0,0 +1 @@ +@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:transparent;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root,[data-md-color-scheme=default]{--md-default-fg-color:rgba(0,0,0,.87);--md-default-fg-color--light:rgba(0,0,0,.54);--md-default-fg-color--lighter:rgba(0,0,0,.32);--md-default-fg-color--lightest:rgba(0,0,0,.07);--md-default-bg-color:#fff;--md-default-bg-color--light:hsla(0,0%,100%,.7);--md-default-bg-color--lighter:hsla(0,0%,100%,.3);--md-default-bg-color--lightest:hsla(0,0%,100%,.12);--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:rgba(82,108,254,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7);--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-hl-color:rgba(255,255,0,.5);--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:rgba(255,255,0,.5);--md-typeset-del-color:rgba(245,80,61,.15);--md-typeset-ins-color:rgba(11,213,112,.15);--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-table-color:rgba(0,0,0,.12);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-fg-color:#fff;--md-footer-fg-color--light:hsla(0,0%,100%,.7);--md-footer-fg-color--lighter:hsla(0,0%,100%,.3);--md-footer-bg-color:rgba(0,0,0,.87);--md-footer-bg-color--dark:rgba(0,0,0,.32);--md-shadow-z1:0 0.2rem 0.5rem rgba(0,0,0,.05),0 0 0.05rem rgba(0,0,0,.1);--md-shadow-z2:0 0.2rem 0.5rem rgba(0,0,0,.1),0 0 0.05rem rgba(0,0,0,.25);--md-shadow-z3:0 0.2rem 0.5rem rgba(0,0,0,.2),0 0 0.05rem rgba(0,0,0,.35)}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}body,input{font-feature-settings:"kern","liga";font-family:var(--md-text-font-family)}body,code,input,kbd,pre{color:var(--md-typeset-color)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent)}.md-typeset a code{color:currentcolor;transition:background-color 125ms}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr;font-variant-ligatures:none}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help;text-decoration:none}@media (hover:none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:-webkit-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}.md-typeset abbr[title]:-moz-any(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}[dir=ltr] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{left:0}[dir=ltr] .md-typeset abbr[title]:is(:focus,:hover):after{left:0}[dir=rtl] .md-typeset abbr[title]:-webkit-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:-moz-any(:focus,:hover):after{right:0}[dir=rtl] .md-typeset abbr[title]:is(:focus,:hover):after{right:0}.md-typeset abbr[title]:is(:focus,:hover):after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);display:inline-block;font-size:.7rem;margin-top:2em;max-width:80%;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;padding:.2rem .3rem;position:absolute;width:auto}}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}.md-typeset ol li :-webkit-any(ul,ol),.md-typeset ul li :-webkit-any(ul,ol){margin-bottom:.5em;margin-top:.5em}.md-typeset ol li :-moz-any(ul,ol),.md-typeset ul li :-moz-any(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset ol li :-webkit-any(ul,ol),[dir=ltr] .md-typeset ul li :-webkit-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :-moz-any(ul,ol),[dir=ltr] .md-typeset ul li :-moz-any(ul,ol){margin-left:.625em}[dir=ltr] .md-typeset ol li :is(ul,ol),[dir=ltr] .md-typeset ul li :is(ul,ol){margin-left:.625em}[dir=rtl] .md-typeset ol li :-webkit-any(ul,ol),[dir=rtl] .md-typeset ul li :-webkit-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :-moz-any(ul,ol),[dir=rtl] .md-typeset ul li :-moz-any(ul,ol){margin-right:.625em}[dir=rtl] .md-typeset ol li :is(ul,ol),[dir=rtl] .md-typeset ul li :is(ul,ol){margin-right:.625em}.md-typeset ol li :is(ul,ol),.md-typeset ul li :is(ul,ol){margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg,.md-typeset video{height:auto;max-width:100%}.md-typeset img[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child{margin-top:0}.md-typeset img[src$="#gh-dark-mode-only"],.md-typeset img[src$="#only-dark"]{display:none}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) :-webkit-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-moz-any(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :is(th,td)>:first-child{margin-top:0}.md-typeset table:not([class]) :-webkit-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-moz-any(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :is(th,td)>:last-child{margin-bottom:0}.md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:left}.md-typeset table:not([class]) :is(th,td):not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) :-webkit-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :-moz-any(th,td):not([align]){text-align:right}[dir=rtl] .md-typeset table:not([class]) :is(th,td):not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.9375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background:var(--md-typeset-mark-color);color:var(--md-default-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}[dir=ltr] .md-banner__button{float:right}[dir=rtl] .md-banner__button{float:left}.md-banner__button{color:inherit;cursor:pointer;transition:opacity .25s}.md-banner__button:hover{opacity:.7}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.9375em){body[data-md-scrolllock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;position:absolute;right:.5em;top:.5em;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:-webkit-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:-moz-any(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-clipboard--inline:is(:focus,:hover) code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}@keyframes consent{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes overlay{0%{opacity:0}to{opacity:1}}.md-consent__overlay{animation:overlay .25s both;-webkit-backdrop-filter:blur(.1rem);backdrop-filter:blur(.1rem);background-color:rgba(0,0,0,.54);height:100%;opacity:1;position:fixed;top:0;width:100%;z-index:5}.md-consent__inner{animation:consent .5s cubic-bezier(.1,.7,.1,1) both;background-color:var(--md-default-bg-color);border:0;border-radius:.1rem;bottom:0;box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);max-height:100%;overflow:auto;padding:0;position:fixed;width:100%;z-index:5}.md-consent__form{padding:.8rem}.md-consent__settings{display:none;margin:1em 0}input:checked+.md-consent__settings{display:block}.md-consent__controls{margin-bottom:.8rem}.md-typeset .md-consent__controls .md-button{display:inline}@media screen and (max-width:44.9375em){.md-typeset .md-consent__controls .md-button{display:block;margin-top:.4rem;text-align:center;width:100%}}.md-consent label{cursor:pointer}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{float:right}[dir=rtl] .md-content__button{float:left}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog--active{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-feedback{margin:2em 0 1em;text-align:center}.md-feedback fieldset{border:none;margin:0;padding:0}.md-feedback__title{font-weight:700;margin:1em auto}.md-feedback__inner{position:relative}.md-feedback__list{align-content:baseline;display:flex;flex-wrap:wrap;justify-content:center;position:relative}.md-feedback__list:hover .md-icon:not(:disabled){color:var(--md-default-fg-color--lighter)}:disabled .md-feedback__list{min-height:1.8rem}.md-feedback__icon{color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;margin:0 .1rem;transition:color 125ms}.md-feedback__icon:not(:disabled).md-icon:hover{color:var(--md-accent-fg-color)}.md-feedback__icon:disabled{color:var(--md-default-fg-color--lightest);pointer-events:none}.md-feedback__note{opacity:0;position:relative;transform:translateY(.4rem);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-feedback__note>*{margin:0 auto;max-width:16rem}:disabled .md-feedback__note{opacity:1;transform:translateY(0)}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__inner:not([hidden]){display:flex}.md-footer__link{display:flex;flex-grow:0.01;outline-color:var(--md-accent-fg-color);overflow:hidden;padding-bottom:.4rem;padding-top:1.4rem;transition:opacity .25s}.md-footer__link:-webkit-any(:focus,:hover){opacity:.7}.md-footer__link:-moz-any(:focus,:hover){opacity:.7}.md-footer__link:is(:focus,:hover){opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.9375em){.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;line-height:2.4rem;max-width:calc(100% - 2.4rem);padding:0 1rem;position:relative;white-space:nowrap}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;left:0;margin-top:-1rem;opacity:.7;padding:0 1rem;position:absolute;right:0}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:-webkit-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:-moz-any(:focus,:hover){color:var(--md-footer-fg-color)}html .md-footer-meta.md-typeset a:is(:focus,:hover){color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-typeset .md-button:is(:focus,:hover){background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:-webkit-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:-moz-any(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input:is(:focus,:hover){border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem transparent,0 .2rem .4rem transparent;color:var(--md-primary-bg-color);display:block;left:0;position:-webkit-sticky;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header--shadow{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.1875em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}.md-header__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;white-space:nowrap}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem}[dir=ltr] .md-header__title{margin-left:1rem}[dir=rtl] .md-header__title{margin-right:1rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title--active .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title--active .md-header__topic{transform:translateX(1.25rem)}.md-header__title--active .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo :-webkit-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :-moz-any(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__title .md-nav__button.md-logo :is(img,svg){fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__item{padding:0 .6rem}[dir=ltr] .md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-left:0}.md-nav__link{align-items:center;cursor:pointer;display:flex;justify-content:space-between;margin-top:.625em;overflow:hidden;scroll-snap-align:start;text-overflow:ellipsis;transition:color 125ms}.md-nav__link--passed{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item .md-nav__link--index [href]{width:100%}.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__link>*{cursor:pointer;display:flex}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.1875em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary :-webkit-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :-moz-any(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary :is(.md-nav__title,.md-nav__item){font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest);padding:0}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav--secondary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:-webkit-sticky;position:sticky;top:0;z-index:1}.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width:76.25em){.md-nav{transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:-webkit-sticky;position:sticky;top:0;z-index:1}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon,.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:-webkit-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:-moz-any(:checked,:indeterminate)~.md-nav{display:block}.md-nav__toggle:is(:checked,:indeterminate)~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700;pointer-events:none}.md-nav__item--section>.md-nav__link--index [href]{pointer-events:auto}.md-nav__item--section>.md-nav__link .md-nav__icon{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;height:.9rem;transition:background-color .25s,transform .25s;width:.9rem}[dir=rtl] .md-nav__icon{transform:rotate(180deg)}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:-.1rem;width:100%}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);font-weight:700;margin-top:0;padding:0 .6rem;position:-webkit-sticky;position:sticky;top:0;z-index:1}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link:not(.md-nav__link--index){pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link .md-nav__icon{display:none}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}[dir=ltr] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-right:.6rem}[dir=rtl] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:.6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested){padding:0 .6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested)>.md-nav__link{padding:0}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:rgba(0,0,0,.54);cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__inner{float:right}[dir=rtl] .md-search__inner{float:left}.md-search__inner{padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}}@media screen and (min-width:60em) and (max-width:76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem transparent;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:rgba(0,0,0,.26);border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:hsla(0,0%,100%,.12)}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem rgba(0,0,0,.07);color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:transparent;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::-ms-input-placeholder{-ms-transition:color .25s;transition:color .25s}.md-search__input::placeholder{transition:color .25s}.md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.9375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::-ms-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>*{margin-left:.2rem}[dir=rtl] .md-search__options>*{margin-right:.2rem}.md-search__options>*{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>*{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.9375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{color:var(--md-typeset-a-color);cursor:pointer;display:block;font-size:.64rem;outline:none;padding:.75em .8rem;scroll-snap-align:start;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem}}.md-search-result__more summary:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary:is(:focus,:hover){background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more summary::marker{display:none}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}.md-search-result__article--document .md-search-result__title{font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result__title{font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result__teaser{-webkit-box-orient:vertical;-webkit-line-clamp:2;color:var(--md-default-fg-color--light);display:-webkit-box;font-size:.64rem;line-height:1.6;margin:.5em 0;max-height:2rem;overflow:hidden;text-overflow:ellipsis}@media screen and (max-width:44.9375em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search-result__teaser{-webkit-line-clamp:3;max-height:3rem}}.md-search-result__teaser mark{background-color:initial;text-decoration:underline}.md-search-result__terms{font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color)}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:-webkit-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-webkit-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:-moz-any(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);-moz-transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms;transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select:is(:focus-within,:hover) .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid transparent;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid transparent;border-right:.2rem solid transparent;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:-webkit-sticky;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.1875em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;-ms-scroll-snap-type:none;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}.md-header--lifted~.md-container .md-sidebar{top:4.8rem}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{scrollbar-gutter:stable;-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) transparent;scrollbar-width:thin}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@supports selector(::-webkit-scrollbar){.md-sidebar__scrollwrap{scrollbar-gutter:auto}[dir=ltr] .md-sidebar__inner{padding-right:calc(100% - 11.5rem)}[dir=rtl] .md-sidebar__inner{padding-left:calc(100% - 11.5rem)}}@media screen and (max-width:76.1875em){.md-overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@keyframes facts{0%{height:0}to{height:.65rem}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{display:flex;font-size:.55rem;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source__repository--active .md-source__facts{animation:facts .25s ease-in}.md-source__fact{overflow:hidden;text-overflow:ellipsis}.md-source__repository--active .md-source__fact{animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}.md-source__fact:nth-child(1n+2){flex-shrink:0}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);display:block;line-height:1.3;overflow:auto;width:100%;z-index:3}@media print{.md-tabs{display:none}}@media screen and (max-width:76.1875em){.md-tabs{display:none}}.md-tabs[hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;list-style:none;margin:0;padding:0;white-space:nowrap}.md-tabs__item{display:inline-block;height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link--active,.md-tabs__link:-webkit-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:-moz-any(:focus,:hover){color:inherit;opacity:1}.md-tabs__link--active,.md-tabs__link:is(:focus,:hover){color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}:root{--md-tag-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-tags{margin-bottom:.75em;margin-top:-.125em}[dir=ltr] .md-typeset .md-tag{margin-right:.5em}[dir=rtl] .md-typeset .md-tag{margin-left:.5em}.md-typeset .md-tag{background:var(--md-default-fg-color--lightest);border-radius:2.4rem;display:inline-block;font-size:.64rem;font-weight:700;letter-spacing:normal;line-height:1.6;margin-bottom:.5em;padding:.3125em .9375em;vertical-align:middle}.md-typeset .md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-typeset .md-tag[href]:focus,.md-typeset .md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-typeset .md-tag{vertical-align:text-top}.md-typeset .md-tag-icon:before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline-block;height:1.2em;margin-right:.4em;-webkit-mask-image:var(--md-tag-icon);mask-image:var(--md-tag-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset .md-tag-icon:-webkit-any(a:focus,a:hover):before{background-color:var(--md-accent-bg-color)}.md-typeset .md-tag-icon:-moz-any(a:focus,a:hover):before{background-color:var(--md-accent-bg-color)}.md-typeset .md-tag-icon:is(a:focus,a:hover):before{background-color:var(--md-accent-bg-color)}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--md-default-fg-color--lightest);transform:scale(.95)}75%{box-shadow:0 0 0 .625em transparent;transform:scale(1)}to{box-shadow:0 0 0 0 transparent;transform:scale(.95)}}:root{--md-tooltip-width:20rem}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);font-family:var(--md-text-font-family);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem);max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}.md-tooltip--active{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,z-index 0ms;z-index:2}:-webkit-any(.focus-visible>.md-tooltip,.md-tooltip:target){outline:var(--md-accent-fg-color) auto}:-moz-any(.focus-visible>.md-tooltip,.md-tooltip:target){outline:var(--md-accent-fg-color) auto}:is(.focus-visible>.md-tooltip,.md-tooltip:target){outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{font-weight:400;outline:none;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}.md-annotation:not([hidden]){display:inline-block;line-height:1.325}.md-annotation__index{cursor:pointer;font-family:var(--md-code-font-family);font-size:.85em;margin:0 1ch;outline:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:0}.md-annotation .md-annotation__index{color:#fff;transition:z-index .25s}.md-annotation .md-annotation__index:-webkit-any(:focus,:hover){color:#fff}.md-annotation .md-annotation__index:-moz-any(:focus,:hover){color:#fff}.md-annotation .md-annotation__index:is(:focus,:hover){color:#fff}.md-annotation__index:after{background-color:var(--md-default-fg-color--lighter);border-radius:2ch;content:"";height:2.2ch;left:-.125em;margin:0 -.4ch;padding:0 .4ch;position:absolute;top:0;transition:color .25s,background-color .25s;width:calc(100% + 1.2ch);width:max(2.2ch,100% + 1.2ch);z-index:-1}@media not all and (prefers-reduced-motion){[data-md-visible]>.md-annotation__index:after{animation:pulse 2s infinite}}.md-tooltip--active+.md-annotation__index:after{animation:none;transition:color .25s,background-color .25s}code .md-annotation__index{font-family:var(--md-code-font-family);font-size:inherit}:-webkit-any(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index){color:var(--md-accent-bg-color)}:-moz-any(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index){color:var(--md-accent-bg-color)}:is(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index){color:var(--md-accent-bg-color)}:-webkit-any(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index):after{background-color:var(--md-accent-fg-color)}:-moz-any(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index):after{background-color:var(--md-accent-fg-color)}:is(.md-tooltip--active+.md-annotation__index,:hover>.md-annotation__index):after{background-color:var(--md-accent-fg-color)}.md-tooltip--active+.md-annotation__index{animation:none;transition:none;z-index:2}.md-annotation__index [data-md-annotation-id]{display:inline-block;line-height:90%}.md-annotation__index [data-md-annotation-id]:before{content:attr(data-md-annotation-id);display:inline-block;padding-bottom:.1em;transform:scale(1.15);transition:transform .4s cubic-bezier(.1,.7,.1,1);vertical-align:.065em}@media not print{.md-annotation__index [data-md-annotation-id]:before{content:"+"}:focus-within>.md-annotation__index [data-md-annotation-id]:before{transform:scale(1.25) rotate(45deg)}}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);display:block;font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[hidden]{transform:translate(50%,.2rem)}.md-top:-webkit-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:-moz-any(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top:is(:focus,:hover){background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.4rem}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:-webkit-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-webkit-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:-moz-any(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;-moz-transition:max-height 0ms,opacity .25s;transition:max-height 0ms,opacity .25s}.md-version:is(:focus-within,:hover) .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (pointer:coarse){.md-version:hover .md-version__list{animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:-webkit-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:-moz-any(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:is(:focus,:hover){color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset :-webkit-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}.md-typeset :-moz-any(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}[dir=ltr] .md-typeset :-webkit-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition,details){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition,details){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition,details){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition,details){border-right-width:.2rem}.md-typeset :is(.admonition,details){background-color:var(--md-admonition-bg-color);border:0 solid #448aff;border-radius:.1rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid}@media print{.md-typeset :-webkit-any(.admonition,details){box-shadow:none}.md-typeset :-moz-any(.admonition,details){box-shadow:none}.md-typeset :is(.admonition,details){box-shadow:none}}.md-typeset :-webkit-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :-moz-any(.admonition,details)>*{box-sizing:border-box}.md-typeset :is(.admonition,details)>*{box-sizing:border-box}.md-typeset :-webkit-any(.admonition,details) :-webkit-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-moz-any(.admonition,details) :-moz-any(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :is(.admonition,details) :is(.admonition,details){margin-bottom:1em;margin-top:1em}.md-typeset :-webkit-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :is(.admonition,details) .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset :-webkit-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-moz-any(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :is(.admonition,details) .md-typeset__table{padding:0 .6rem}.md-typeset :-webkit-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :-moz-any(.admonition,details)>.tabbed-set:only-child{margin-top:0}.md-typeset :is(.admonition,details)>.tabbed-set:only-child{margin-top:0}html .md-typeset :-webkit-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :-moz-any(.admonition,details)>:last-child{margin-bottom:.6rem}html .md-typeset :is(.admonition,details)>:last-child{margin-bottom:.6rem}.md-typeset :-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}.md-typeset :-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){margin-left:-.8rem;margin-right:-.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){margin-left:-.6rem;margin-right:-.8rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){padding-left:2.2rem;padding-right:.6rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){padding-left:.6rem;padding-right:2.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-left-width:.2rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-left-width:.2rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-right-width:.2rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-right-width:.2rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-top-left-radius:.1rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-top-right-radius:.1rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary){border-top-right-radius:.1rem}[dir=ltr] .md-typeset :is(.admonition-title,summary){border-top-right-radius:.1rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary){border-top-left-radius:.1rem}[dir=rtl] .md-typeset :is(.admonition-title,summary){border-top-left-radius:.1rem}.md-typeset :is(.admonition-title,summary){background-color:rgba(68,138,255,.1);border:none;font-weight:700;margin-bottom:0;margin-top:0;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset :-webkit-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :-moz-any(.admonition-title,summary):last-child{margin-bottom:0}html .md-typeset :is(.admonition-title,summary):last-child{margin-bottom:0}.md-typeset :-webkit-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-moz-any(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;mask-image:var(--md-admonition-icon--note);mask-position:center;mask-repeat:no-repeat;mask-size:contain;position:absolute;top:.625em;width:1rem}[dir=ltr] .md-typeset :-webkit-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :-moz-any(.admonition-title,summary):before{left:.8rem}[dir=ltr] .md-typeset :is(.admonition-title,summary):before{left:.8rem}[dir=rtl] .md-typeset :-webkit-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :-moz-any(.admonition-title,summary):before{right:.8rem}[dir=rtl] .md-typeset :is(.admonition-title,summary):before{right:.8rem}.md-typeset :is(.admonition-title,summary):before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.note){border-color:#448aff}.md-typeset :-moz-any(.admonition,details):-moz-any(.note){border-color:#448aff}.md-typeset :is(.admonition,details):is(.note){border-color:#448aff}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :is(.note)>:is(.admonition-title,summary){background-color:rgba(68,138,255,.1)}.md-typeset :-webkit-any(.note)>:-webkit-any(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset :-moz-any(.note)>:-moz-any(.admonition-title,summary):before{background-color:#448aff;mask-image:var(--md-admonition-icon--note)}.md-typeset :is(.note)>:is(.admonition-title,summary):before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-moz-any(.admonition,details):-moz-any(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :is(.admonition,details):is(.abstract,.summary,.tldr){border-color:#00b0ff}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary){background-color:rgba(0,176,255,.1)}.md-typeset :-webkit-any(.abstract,.summary,.tldr)>:-webkit-any(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset :-moz-any(.abstract,.summary,.tldr)>:-moz-any(.admonition-title,summary):before{background-color:#00b0ff;mask-image:var(--md-admonition-icon--abstract)}.md-typeset :is(.abstract,.summary,.tldr)>:is(.admonition-title,summary):before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.info,.todo){border-color:#00b8d4}.md-typeset :-moz-any(.admonition,details):-moz-any(.info,.todo){border-color:#00b8d4}.md-typeset :is(.admonition,details):is(.info,.todo){border-color:#00b8d4}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary){background-color:rgba(0,184,212,.1)}.md-typeset :-webkit-any(.info,.todo)>:-webkit-any(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset :-moz-any(.info,.todo)>:-moz-any(.admonition-title,summary):before{background-color:#00b8d4;mask-image:var(--md-admonition-icon--info)}.md-typeset :is(.info,.todo)>:is(.admonition-title,summary):before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-moz-any(.admonition,details):-moz-any(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :is(.admonition,details):is(.tip,.hint,.important){border-color:#00bfa5}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary){background-color:rgba(0,191,165,.1)}.md-typeset :-webkit-any(.tip,.hint,.important)>:-webkit-any(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset :-moz-any(.tip,.hint,.important)>:-moz-any(.admonition-title,summary):before{background-color:#00bfa5;mask-image:var(--md-admonition-icon--tip)}.md-typeset :is(.tip,.hint,.important)>:is(.admonition-title,summary):before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.success,.check,.done){border-color:#00c853}.md-typeset :-moz-any(.admonition,details):-moz-any(.success,.check,.done){border-color:#00c853}.md-typeset :is(.admonition,details):is(.success,.check,.done){border-color:#00c853}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary){background-color:rgba(0,200,83,.1)}.md-typeset :-webkit-any(.success,.check,.done)>:-webkit-any(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset :-moz-any(.success,.check,.done)>:-moz-any(.admonition-title,summary):before{background-color:#00c853;mask-image:var(--md-admonition-icon--success)}.md-typeset :is(.success,.check,.done)>:is(.admonition-title,summary):before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :-moz-any(.admonition,details):-moz-any(.question,.help,.faq){border-color:#64dd17}.md-typeset :is(.admonition,details):is(.question,.help,.faq){border-color:#64dd17}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary){background-color:rgba(100,221,23,.1)}.md-typeset :-webkit-any(.question,.help,.faq)>:-webkit-any(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset :-moz-any(.question,.help,.faq)>:-moz-any(.admonition-title,summary):before{background-color:#64dd17;mask-image:var(--md-admonition-icon--question)}.md-typeset :is(.question,.help,.faq)>:is(.admonition-title,summary):before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-moz-any(.admonition,details):-moz-any(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :is(.admonition,details):is(.warning,.caution,.attention){border-color:#ff9100}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary){background-color:rgba(255,145,0,.1)}.md-typeset :-webkit-any(.warning,.caution,.attention)>:-webkit-any(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset :-moz-any(.warning,.caution,.attention)>:-moz-any(.admonition-title,summary):before{background-color:#ff9100;mask-image:var(--md-admonition-icon--warning)}.md-typeset :is(.warning,.caution,.attention)>:is(.admonition-title,summary):before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-moz-any(.admonition,details):-moz-any(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :is(.admonition,details):is(.failure,.fail,.missing){border-color:#ff5252}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary){background-color:rgba(255,82,82,.1)}.md-typeset :-webkit-any(.failure,.fail,.missing)>:-webkit-any(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset :-moz-any(.failure,.fail,.missing)>:-moz-any(.admonition-title,summary):before{background-color:#ff5252;mask-image:var(--md-admonition-icon--failure)}.md-typeset :is(.failure,.fail,.missing)>:is(.admonition-title,summary):before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.danger,.error){border-color:#ff1744}.md-typeset :-moz-any(.admonition,details):-moz-any(.danger,.error){border-color:#ff1744}.md-typeset :is(.admonition,details):is(.danger,.error){border-color:#ff1744}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary){background-color:rgba(255,23,68,.1)}.md-typeset :-webkit-any(.danger,.error)>:-webkit-any(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset :-moz-any(.danger,.error)>:-moz-any(.admonition-title,summary):before{background-color:#ff1744;mask-image:var(--md-admonition-icon--danger)}.md-typeset :is(.danger,.error)>:is(.admonition-title,summary):before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.bug){border-color:#f50057}.md-typeset :-moz-any(.admonition,details):-moz-any(.bug){border-color:#f50057}.md-typeset :is(.admonition,details):is(.bug){border-color:#f50057}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :is(.bug)>:is(.admonition-title,summary){background-color:rgba(245,0,87,.1)}.md-typeset :-webkit-any(.bug)>:-webkit-any(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset :-moz-any(.bug)>:-moz-any(.admonition-title,summary):before{background-color:#f50057;mask-image:var(--md-admonition-icon--bug)}.md-typeset :is(.bug)>:is(.admonition-title,summary):before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.example){border-color:#7c4dff}.md-typeset :-moz-any(.admonition,details):-moz-any(.example){border-color:#7c4dff}.md-typeset :is(.admonition,details):is(.example){border-color:#7c4dff}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :is(.example)>:is(.admonition-title,summary){background-color:rgba(124,77,255,.1)}.md-typeset :-webkit-any(.example)>:-webkit-any(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset :-moz-any(.example)>:-moz-any(.admonition-title,summary):before{background-color:#7c4dff;mask-image:var(--md-admonition-icon--example)}.md-typeset :is(.example)>:is(.admonition-title,summary):before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset :-webkit-any(.admonition,details):-webkit-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :-moz-any(.admonition,details):-moz-any(.quote,.cite){border-color:#9e9e9e}.md-typeset :is(.admonition,details):is(.quote,.cite){border-color:#9e9e9e}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary){background-color:hsla(0,0%,62%,.1)}.md-typeset :-webkit-any(.quote,.cite)>:-webkit-any(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}.md-typeset :-moz-any(.quote,.cite)>:-moz-any(.admonition-title,summary):before{background-color:#9e9e9e;mask-image:var(--md-admonition-icon--quote)}.md-typeset :is(.quote,.cite)>:is(.admonition-title,summary):before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:-webkit-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:-moz-any(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li:is(:hover,:target) .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :-webkit-any(:hover,:target)>.headerlink{opacity:1;-webkit-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :-moz-any(:hover,:target)>.headerlink{opacity:1;-moz-transition:color .25s,opacity 125ms;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset :is(:hover,:target)>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:-webkit-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:-moz-any(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset .headerlink:is(:focus,:hover),.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset :-webkit-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :-moz-any(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset :is(h1,h2,h3):target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.9375em){.md-typeset div.arithmatex{margin:0 -.8rem}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto;width:-webkit-min-content;width:-moz-min-content;width:min-content}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset :-webkit-any(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset :-moz-any(del,ins,.comment).critic{box-decoration-break:clone}.md-typeset :is(del,ins,.comment).critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :is(.emojione,.twemoji,.gemoji){display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset :-webkit-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :-moz-any(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.md-typeset :is(.emojione,.twemoji,.gemoji) svg{fill:currentcolor;max-height:100%;width:1.125em}.highlight :-webkit-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :-moz-any(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight :is(.o,.ow){color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight :-webkit-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-moz-any(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :is(.cpf,.l,.s,.sb,.sc,.s2,.si,.s1,.ss){color:var(--md-code-hl-string-color)}.highlight :-webkit-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-moz-any(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :is(.cp,.se,.sh,.sr,.sx){color:var(--md-code-hl-special-color)}.highlight :-webkit-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-moz-any(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :is(.m,.mb,.mf,.mh,.mi,.il,.mo){color:var(--md-code-hl-number-color)}.highlight :-webkit-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :is(.k,.kd,.kn,.kp,.kr,.kt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-moz-any(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :is(.kc,.n){color:var(--md-code-hl-name-color)}.highlight :-webkit-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-moz-any(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :is(.no,.nb,.bp){color:var(--md-code-hl-constant-color)}.highlight :-webkit-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-moz-any(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :is(.nc,.ne,.nf,.nn){color:var(--md-code-hl-function-color)}.highlight :-webkit-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-moz-any(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :is(.nd,.ni,.nl,.nt){color:var(--md-code-hl-keyword-color)}.highlight :-webkit-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-moz-any(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :is(.c,.cm,.c1,.ch,.cs,.sd){color:var(--md-code-hl-comment-color)}.highlight :-webkit-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-moz-any(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :is(.na,.nv,.vc,.vg,.vi){color:var(--md-code-hl-variable-color)}.highlight :-webkit-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-moz-any(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :is(.ge,.gr,.gh,.go,.gp,.gs,.gu,.gt){color:var(--md-code-hl-generic-color)}.highlight :-webkit-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :-moz-any(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight :is(.gd,.gi){border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color);display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:-webkit-sticky;position:sticky;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable :-webkit-any(tbody,td){display:block;padding:0}.highlighttable :-moz-any(tbody,td){display:block;padding:0}.highlighttable :is(tbody,td){display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;padding-right:.5882352941em}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable>tbody>tr>.code>div>pre>code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset .highlight+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset .highlight+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.9375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight>.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.code>div>pre>code,.md-content__inner>.highlight>.highlighttable>tbody>tr>.filename span.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.linenos,.md-content__inner>.highlight>pre>code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}}.md-typeset .keys kbd:-webkit-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:-moz-any(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys kbd:is(:before,:after){-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}:root{--md-tabbed-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-tabbed-icon--next:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-accent-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid transparent;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-margin-inline-start:1rem;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-accent-fg-color)}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre,.md-typeset .tabbed-block>pre:first-child{margin:0}.md-typeset .tabbed-block>.highlight:first-child>pre>code,.md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child>.filename{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable{margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.filename span.filename,.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.linenos{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.code>div>pre>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child+.result{margin-top:-.125em}.md-typeset .tabbed-block>.tabbed-set{margin:0}.md-typeset .tabbed-button{align-self:center;border-radius:100%;color:var(--md-default-fg-color--light);cursor:pointer;display:block;height:.9rem;margin-top:.1rem;pointer-events:auto;transition:background-color .25s;width:.9rem}.md-typeset .tabbed-button:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset .tabbed-button:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-tabbed-icon--prev);mask-image:var(--md-tabbed-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color .25s,transform .25s;width:100%}.md-typeset .tabbed-control{background:linear-gradient(to right,var(--md-default-bg-color) 60%,transparent);display:flex;height:1.9rem;justify-content:start;pointer-events:none;position:absolute;transition:opacity 125ms;width:1.2rem}[dir=rtl] .md-typeset .tabbed-control{transform:rotate(180deg)}.md-typeset .tabbed-control[hidden]{opacity:0}.md-typeset .tabbed-control--next{background:linear-gradient(to left,var(--md-default-bg-color) 60%,transparent);justify-content:end;right:0}.md-typeset .tabbed-control--next .tabbed-button:after{-webkit-mask-image:var(--md-tabbed-icon--next);mask-image:var(--md-tabbed-icon--next)}@media screen and (max-width:44.9375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-left:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-right:-.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{width:2rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-right:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-left:-.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{width:2rem}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-accent-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){background-color:var(--md-accent-fg-color--transparent)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color)}.mermaid{line-height:normal;margin:1em 0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{float:left}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=ltr] .md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}} \ No newline at end of file diff --git a/assets/stylesheets/main.80dcb947.min.css.map b/assets/stylesheets/main.80dcb947.min.css.map new file mode 100644 index 00000000..a32399b5 --- /dev/null +++ b/assets/stylesheets/main.80dcb947.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","../../../src/assets/stylesheets/main.scss","src/assets/stylesheets/main/_resets.scss","src/assets/stylesheets/main/_colors.scss","src/assets/stylesheets/main/_icons.scss","src/assets/stylesheets/main/_typeset.scss","src/assets/stylesheets/utilities/_break.scss","src/assets/stylesheets/main/layout/_banner.scss","src/assets/stylesheets/main/layout/_base.scss","src/assets/stylesheets/main/layout/_clipboard.scss","src/assets/stylesheets/main/layout/_consent.scss","src/assets/stylesheets/main/layout/_content.scss","src/assets/stylesheets/main/layout/_dialog.scss","src/assets/stylesheets/main/layout/_feedback.scss","src/assets/stylesheets/main/layout/_footer.scss","src/assets/stylesheets/main/layout/_form.scss","src/assets/stylesheets/main/layout/_header.scss","src/assets/stylesheets/main/layout/_nav.scss","src/assets/stylesheets/main/layout/_search.scss","src/assets/stylesheets/main/layout/_select.scss","src/assets/stylesheets/main/layout/_sidebar.scss","src/assets/stylesheets/main/layout/_source.scss","src/assets/stylesheets/main/layout/_tabs.scss","src/assets/stylesheets/main/layout/_tag.scss","src/assets/stylesheets/main/layout/_tooltip.scss","src/assets/stylesheets/main/layout/_top.scss","src/assets/stylesheets/main/layout/_version.scss","src/assets/stylesheets/main/extensions/markdown/_admonition.scss","node_modules/material-design-color/material-color.scss","src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/assets/stylesheets/main/extensions/markdown/_toc.scss","src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/assets/stylesheets/main/integrations/_mermaid.scss","src/assets/stylesheets/main/_modifiers.scss"],"names":[],"mappings":"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yFE,iEACE,oB1BmyFJ,C0BpyFE,2DACE,oB1BmyFJ,C0BpyFE,+CACE,oB1BmyFJ,C0B/xFE,wEACE,oC1BkyFJ,C0BnyFE,kEACE,oC1BkyFJ,C0BnyFE,sDACE,oC1BkyFJ,C0B/xFI,+EACE,wBAnBG,CAoBH,kDAAA,CAAA,0C1BiyFN,C0BnyFI,yEACE,wBAnBG,CAoBH,0C1BiyFN,C0BnyFI,6DACE,wBAnBG,CAoBH,kDAAA,CAAA,0C1BiyFN,C0B5yFE,oFACE,oB1B+yFJ,C0BhzFE,8EACE,oB1B+yFJ,C0BhzFE,kEACE,oB1B+yFJ,C0B3yFE,2FACE,mC1B8yFJ,C0B/yFE,qFACE,mC1B8yFJ,C0B/yFE,yEACE,mC1B8yFJ,C0B3yFI,kGACE,wBAnBG,CAoBH,sDAAA,CAAA,8C1B6yFN,C0B/yFI,4FACE,wBAnBG,CAoBH,8C1B6yFN,C0B/yFI,gFACE,wBAnBG,CAoBH,sDAAA,CAAA,8C1B6yFN,C0BxzFE,uEACE,oB1B2zFJ,C0B5zFE,iEACE,oB1B2zFJ,C0B5zFE,qDACE,oB1B2zFJ,C0BvzFE,8EACE,mC1B0zFJ,C0B3zFE,wEACE,mC1B0zFJ,C0B3zFE,4DACE,mC1B0zFJ,C0BvzFI,qFACE,wBAnBG,CAoBH,kDAAA,CAAA,0C1ByzFN,C0B3zFI,+EACE,wBAnBG,CAoBH,0C1ByzFN,C0B3zFI,mEACE,wBAnBG,CAoBH,kDAAA,CAAA,0C1ByzFN,C0Bp0FE,iFACE,oB1Bu0FJ,C0Bx0FE,2EACE,oB1Bu0FJ,C0Bx0FE,+DACE,oB1Bu0FJ,C0Bn0FE,wFACE,mC1Bs0FJ,C0Bv0FE,kFACE,mC1Bs0FJ,C0Bv0FE,sEACE,mC1Bs0FJ,C0Bn0FI,+FACE,wBAnBG,CAoBH,iDAAA,CAAA,yC1Bq0FN,C0Bv0FI,yFACE,wBAnBG,CAoBH,yC1Bq0FN,C0Bv0FI,6EACE,wBAnBG,CAoBH,iDAAA,CAAA,yC1Bq0FN,C0Bh1FE,iFACE,oB1Bm1FJ,C0Bp1FE,2EACE,oB1Bm1FJ,C0Bp1FE,+DACE,oB1Bm1FJ,C0B/0FE,wFACE,kC1Bk1FJ,C0Bn1FE,kFACE,kC1Bk1FJ,C0Bn1FE,sEACE,kC1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","file":"main.css"} \ No newline at end of file diff --git a/assets/stylesheets/palette.cbb835fc.min.css b/assets/stylesheets/palette.cbb835fc.min.css new file mode 100644 index 00000000..30f9264c --- /dev/null +++ b/assets/stylesheets/palette.cbb835fc.min.css @@ -0,0 +1 @@ +@media screen{[data-md-color-scheme=slate]{--md-hue:232;--md-default-fg-color:hsla(var(--md-hue),75%,95%,1);--md-default-fg-color--light:hsla(var(--md-hue),75%,90%,0.62);--md-default-fg-color--lighter:hsla(var(--md-hue),75%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),75%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,21%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,21%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,21%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,21%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,1);--md-code-bg-color:hsla(var(--md-hue),15%,15%,1);--md-code-hl-color:rgba(66,135,255,.15);--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:rgba(66,135,255,.3);--md-typeset-kbd-color:hsla(var(--md-hue),15%,94%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,94%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-table-color:hsla(var(--md-hue),75%,95%,0.12);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,12%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,10%,1);--md-shadow-z1:0 0.2rem 0.5rem rgba(0,0,0,.2),0 0 0.05rem rgba(0,0,0,.1);--md-shadow-z2:0 0.2rem 0.5rem rgba(0,0,0,.3),0 0 0.05rem rgba(0,0,0,.25);--md-shadow-z3:0 0.2rem 0.5rem rgba(0,0,0,.4),0 0 0.05rem rgba(0,0,0,.35)}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate] img[src$="#gh-dark-mode-only"],[data-md-color-scheme=slate] img[src$="#only-dark"]{display:initial}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#bd78c9}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a682e3}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#6c91d5}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff9575}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c7846b}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#6c91d5}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:rgba(255,25,71,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:rgba(245,0,86,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:rgba(223,65,251,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:rgba(124,77,255,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:rgba(82,108,254,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:rgba(66,135,255,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:rgba(0,145,235,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:rgba(0,186,214,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:rgba(0,189,164,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:rgba(0,199,83,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:rgba(99,222,23,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:rgba(176,235,0,.1);--md-accent-bg-color:rgba(0,0,0,.87);--md-accent-bg-color--light:rgba(0,0,0,.54)}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:rgba(255,213,0,.1);--md-accent-bg-color:rgba(0,0,0,.87);--md-accent-bg-color--light:rgba(0,0,0,.54)}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:rgba(255,170,0,.1);--md-accent-bg-color:rgba(0,0,0,.87);--md-accent-bg-color--light:rgba(0,0,0,.54)}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:rgba(255,145,0,.1);--md-accent-bg-color:rgba(0,0,0,.87);--md-accent-bg-color--light:rgba(0,0,0,.54)}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:rgba(255,110,66,.1);--md-accent-bg-color:#fff;--md-accent-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:rgba(0,0,0,.87);--md-primary-bg-color--light:rgba(0,0,0,.54)}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:rgba(0,0,0,.87);--md-primary-bg-color--light:rgba(0,0,0,.54)}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:rgba(0,0,0,.87);--md-primary-bg-color--light:rgba(0,0,0,.54)}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:rgba(0,0,0,.87);--md-primary-bg-color--light:rgba(0,0,0,.54)}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7)}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:#fff;--md-primary-fg-color--light:hsla(0,0%,100%,.7);--md-primary-fg-color--dark:rgba(0,0,0,.07);--md-primary-bg-color:rgba(0,0,0,.87);--md-primary-bg-color--light:rgba(0,0,0,.54);--md-typeset-a-color:#4051b5}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:rgba(0,0,0,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:rgba(0,0,0,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:rgba(0,0,0,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid rgba(0,0,0,.07)}}[data-md-color-primary=black]{--md-primary-fg-color:#000;--md-primary-fg-color--light:rgba(0,0,0,.54);--md-primary-fg-color--dark:#000;--md-primary-bg-color:#fff;--md-primary-bg-color--light:hsla(0,0%,100%,.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-header{background-color:#000}@media screen and (max-width:59.9375em){[data-md-color-primary=black] .md-nav__source{background-color:rgba(0,0,0,.87)}}@media screen and (min-width:60em){[data-md-color-primary=black] .md-search__form{background-color:hsla(0,0%,100%,.12)}[data-md-color-primary=black] .md-search__form:hover{background-color:hsla(0,0%,100%,.3)}}@media screen and (max-width:76.1875em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:#000}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:#000}} \ No newline at end of file diff --git a/assets/stylesheets/palette.cbb835fc.min.css.map b/assets/stylesheets/palette.cbb835fc.min.css.map new file mode 100644 index 00000000..96e380c8 --- /dev/null +++ b/assets/stylesheets/palette.cbb835fc.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/assets/stylesheets/palette/_scheme.scss","../../../src/assets/stylesheets/palette.scss","src/assets/stylesheets/palette/_accent.scss","src/assets/stylesheets/palette/_primary.scss","src/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"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","file":"palette.css"} \ No newline at end of file diff --git a/docs/digests/ansible-semanticmediawiki-install-notes/index.html b/docs/digests/ansible-semanticmediawiki-install-notes/index.html new file mode 100644 index 00000000..529bed22 --- /dev/null +++ b/docs/digests/ansible-semanticmediawiki-install-notes/index.html @@ -0,0 +1,3387 @@ + + + + + + + + + + + + + + + + Ansible Semanticmediawiki Install Notes - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Installing Semantic Mediawiki with Ansible

    +

    Requirements:

    +
      +
    1. Use old mediawiki production database (upgrade?)
    2. +
    3. Manage installation
    4. +
    5. Manage upgrades
    6. +
    7. Open Source (contribute back for other hackerspaces and other wikis)
    8. +
    9. Manage backups
    10. +
    11. Testable processes
    12. +
    13. Automatically upgrade/configure/manage semantic mediawiki extension and other extensions
    14. +
    +

    Requirements

    +
      +
    1. We want to use our old database.
    2. +
    3. It would be nice to use semantic mediawiki.
    4. +
    5. We should be able to upgrade and add extensions by redeploying the ansible playbook (idempotency retained)
    6. +
    7. We should install all this stuff with composer +
    8. +
    +

    Questions

    +
      +
    • What RDBMS are we using now?
    • +
    • What WikiMedia version are we using now?
    • +
    • What WikiMedia extensions are we using now?
    • +
    • How does the wiki upgrade process work? Special Considerations?
    • +
    +

    Alternatives to our own ansible playbook

    +

    WikiMedia has an initiative to simplify wiki deployments called CloudVPS.

    +

    It is OpenStack powered infrastructure. We want to self-host, but might be able to use their images?

    +

    A Noisebridge Wiki Upgrade Plan

    +

    Patrick: "no more snowflakes"

    +

    Trent's Plan

    +
      +
    1. Use my servers.yml playbook as a base, available here.
    2. +
    3. Add a premade playbook
    4. +
    5. Make significant modifications to accomodate our needs
    6. +
    +

    Hunting for a premade role

    + +

    A google search for "ansible role semantic mediawiki" seemed promising and is summarized below.

    +

    There are probably more results available by trying more searches.

    +

    EMWCon Spring 2017

    +

    Found here: Using Ansible to create and manage a wiki/wiki farm examples.

    + +

    BlueSpice Enterprise

    +

    This may be helpful to look over.

    + +

    Some Random Playbooks/Roles

    + +

    Failed: Ansible Galaxy

    +

    The playbooks I found here were incomplete and outdated, as usual.

    +

    Extra

    +
      +
    • +

      ToolForge

      +
      +

      a hosting environment for developers working on services that provide value to the Wikimedia movement. These services allow developers to easily do ad hoc analytics, administer bots, run webservices, and generally create tools to help editors and other volunteers in their work. The environment also includes access to a variety of data services.

      +
      +
    • +
    +

    References

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/artofwar13_spies/index.html b/docs/digests/artofwar13_spies/index.html new file mode 100644 index 00000000..8cbbc906 --- /dev/null +++ b/docs/digests/artofwar13_spies/index.html @@ -0,0 +1,3180 @@ + + + + + + + + + + + + + + + + Artofwar13 Spies - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Artofwar13 Spies

    + +

    Chapter 13: Spies

    +

    A summary of Sun Tzu Chapter 13.

    +

    Source: https://suntzusaid.com/book/13

    +

    More footnotes: http://www.sacred-texts.com/tao/aow/aow21.htm

    +

    Also try to find the remarks of Frederick the Great on spies.

    +

    Also see the Military Memoirs and maxims of Marshal Turenne.

    +

    Notes

    +

    The word 'spy' is not an excellent translation for this chapter, te term is broader.

    +

    Apparently there is some history between the chinese word for "spy" and the word for "a crack in the door between which the moonlight can slip". So the context of this document must be adjusted. Additionally, there is something about it meaing "a crack or a chink", so this is probably related to the modern computer concepts of bugs and cracking an enemy's loyalty strategies and other parts of his personnell substrate not fully under his control.

    +

    "Divine Manipulation" == Control. This definition probably relates to the definitions of control we give to performers rather than coercive power.

    +

    Another translation recommends that 'doomed' spies are also enemy spies who are fed false information, but this is disputed.

    +

    Another translation of "pay spies generously" is to also "show them complete trust in their work"

    +

    Tu Mu added a warning: "Just as water, which carries a boat from bank to bank, may also be the means of sinking it, so reliance on spies, while productive of great results, is oft-times the cause of utter destruction."

    +

    Chia Lin added: "An army without spies is like a man without ears or eyes."

    +

    Summary

    +

    If your objective has a high ongoing and total cost, don't try to save a fraction of the daily cost in payments, e.g. "emoluments" and "honors" for information.

    +

    Foreknowledge of an opponent cannot come from calculation, mystics, or experience.

    +

    Foreknowledge of an opponent can only come from other people.

    +
      +
    1. Five Classes of Spies
    2. +
    3. local: inhabitants of a opponent district
    4. +
    5. inward: officials of the opponent
    6. +
    7. converted: enemy spies turned by bribe carrot or stick
    8. +
    9. doomed: deceive your own spies who are then captured by the enemy and report false information. the enemy will kill this spy when their information is found to be false.
    10. +
    11. surviving: a traditional spy, seek and bring back news from the enemy camp
        +
      • an apparent fool with a will of iron and keen intellect
      • +
      • active, robust, strng, courageous
      • +
      • accustomed to dirty work, able to endure hunger and cold
      • +
      • able to put up with and ignominy
      • +
      +
    12. +
    +

    The "divine manipulation of the threads" is having all five kinds of spies at work at once. Claimed to be "the soverign's most precious faculty" as well as "an undiscoverable secret system".

    +

    The relationship with spies is the most intimate in the army. They should be the most well rewarded and should have the highest level of secrecy.

    +

    Employ spies with wisdom, Manage them with benevolence and straightforwardness as necessary.

    +

    Without "subtle ingenuity" you cannot trust your spies. Use your spies for every kind of business. "Be subtle! Be Subtle!"

    +

    If a spy reveals news before you need it, kill the spy and the recepient of the knowledge.

    +
      +
    • Get the names of:
        +
      • attendants
      • +
      • aides-de-camp
      • +
      • door-keepers and sentries of the leader
      • +
      +
    • +
    +

    The 'converted' spy has information which is the source of 'inward' and 'local' spies.

    +

    Create 'converted' spies with bribes, housing.

    +

    Goal: Knowledge of your opponent.

    +

    The 'converted' spy is the foundation of this knowledge. Therefore, the 'converted' spy is treated with the "utmost liberality".

    +

    Spies are a more important element in water because the army's ability to move depends on them.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/becoming_a_magician/index.html b/docs/digests/becoming_a_magician/index.html new file mode 100644 index 00000000..3f3a33a5 --- /dev/null +++ b/docs/digests/becoming_a_magician/index.html @@ -0,0 +1,3189 @@ + + + + + + + + + + + + + + + + Becoming A Magician - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Becoming A Magician

    +

    Inspired by

    +
      +
    • +

      Becoming a Magician

      +
    • +
    • +

      any significantly advanced technologist seems like a magician

      +
    • +
    • imagine a version of myself that i cannot yet understand
    • +
    • you would simply have to step back and build something completely different altogether
    • +
    • magic is competence is so far advanced from your confidence with such alien mental models that you cannot predict the outcome of the models at all.
    • +
    • people typically try to "double down on what worked" which means wringing more value out of the same mental models, tools, and processes
    • +
    +
    +

    The way to extraordinary growth and changes often involves a fundamental ontological or ‘lens’ shift in how you see the world. Magicians are wearing not just better, but fundamentally differently shaped lenses to the rest of us.

    +

    Meeting magicians is the first step to becoming one – when you are attempting to learn implicit knowledge that by definition you don’t understand, it is important to have a bunch of examples in front of you to feed your brain’s pattern-recognition systems.

    +

    Concrete steps I take to find them include asking my most interesting friends to introduce me to their most interesting friends, going down similar rabbit holes with the bibliographies of books that excite me, and generally living in ‘explore’ mode at various points in life, while recognising that not every avenue will lead to a jackpot.

    +

    Questions I like to ask myself include: +- ‘What is the most capable version of me that I can imagine?’ +- ‘What would I be like/spend my time doing if all my current major problems had been solved?’ +- ‘What are the things I say I value but don’t act as if I value, and what would my life feel like on inside if I actually acted as if I valued those things?’ +- ‘What am I afraid of doing, and what would my life be like if I wasn’t afraid of doing those things?’.

    +
    +
      +
    • author refers to a "nonlinear strategy", what they mean is a strategy that cannot be extrapolated from your current artifacts, methods, language, and training (engelbart H-LAM/T)
    • +
    +

    Conclusions

    +
      +
    • daily grow/explore your graph of interesting people deeply and broadly
    • +
    • build an engine to build new whole sets of mental models
    • +
    • generate new language and artifacts and methods and training
    • +
    • i think i stick to methods too much, i need to be inventive with all 4
    • +
    • surround myself with magicians who do the magic i want to do
    • +
    +

    References

    + +

    naive Vision for myself

    +

    Before taking the advice of the post, here are some thoughts about what I would value. The post explains that you have to write a version of yourself you cannot imagine, so you cannot write within your existing constraints. Therefore, the below goals are naively small and close to who I am and what I could start doing today.

    +
      +
    • reimplementing and contributing to core oss tools, lisps and vim etc.
    • +
    • breaking new ground on terminal and tui as a first class citizen of a graphical window manager
    • +
    • no constraints from physical space to walk in and start drafting 3d art in some scad-clj derivative or composite tools
    • +
    • no frustrating time constraints to learn the needed skills to produce art
    • +
    • no frustrating time constraints to maintain a 90 minute x 6 day fitness routine with low impact and no real risk of injury (not running outdoors)
    • +
    • need to add an elliptical at home, eventually a treadmill?
    • +
    • increase my transit range while still maintaining the level of simplicity, increase access to tools
    • +
    • live somewhere turnkey, never want to think about stress or logistics or traffic or weather if possible
    • +
    • expand my thinking more, sure i have done that a lot, but on what dimensions haven't i (beginner's mind and assimilating new skills)
    • +
    • pick up inspiring old ideas and write them out to their blockers
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.aux b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.aux new file mode 100644 index 00000000..d583baf6 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.aux @@ -0,0 +1,17 @@ +\relax +\@writefile{toc}{\contentsline {section}{Problem 1}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 2}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 3}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 4}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 5}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 6}{4}{}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces DFA, \(A\), this is really beautiful, ya know?}}{4}{}\protected@file@percent } +\newlabel{fig:multiple5}{{1}{4}} +\@writefile{toc}{\contentsline {section}{Problem 7}{4}{}\protected@file@percent } +\@writefile{loa}{\contentsline {algorithm}{\numberline {1}{\ignorespaces Start of QuickSort}}{4}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 8}{5}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 9}{7}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 18}{8}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 19}{8}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 6}{8}{}\protected@file@percent } +\gdef \@abspage@last{8} diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fdb_latexmk b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fdb_latexmk new file mode 100644 index 00000000..3126c417 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fdb_latexmk @@ -0,0 +1,155 @@ +# Fdb version 3 +["pdflatex"] 1652492872 "0.diagnostic_A.algebra.tex" "0.diagnostic_A.algebra.pdf" "0.diagnostic_A.algebra" 1652492873 + "/usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm" 1246382020 916 f87d7c45f9c908e672703b83b72241a3 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm" 1246382020 924 9904cf1d39e9767e7a3622f2a125a565 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm" 1246382020 928 2dc8d444221b7a635bb58038579b861a "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm" 1246382020 908 2921f8a10601f252058503cc6570e581 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm" 1246382020 940 75ac932a52f80982a9f8ea75d03a34cf "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm" 1246382020 940 228d6584342e91276bf566bcf9716b83 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm" 1136768653 1328 c834bbb027764024c09d3d2bf908b5f0 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm" 1136768653 1324 c910af8c371558dc20f2d7822f66fe64 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx8.tfm" 1136768653 1332 1fde11373e221473104d6cc5993f046e "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm" 1136768653 1300 63a6111ee6274895728663cf4b4e7e81 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmex10.tfm" 1136768653 992 662f679a0b3d2d53c1b94050fdaa3f50 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm" 1136768653 1524 4414a8315f39513458b80dfc63bff03a "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm" 1136768653 1512 f21f83efb36853c0b70002322c1ab3ad "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm" 1136768653 1520 eccf95517727cb11801f4f1aee3a21b4 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr6.tfm" 1136768653 1300 b62933e007d01cfd073f79b963c01526 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr8.tfm" 1136768653 1292 21c1c5bfeaebccffdb478fd231a0997d "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr9.tfm" 1136768653 1292 6b21b9c2c7bebb38aa2273f7ca0fb3af "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm" 1136768653 1116 933a60c408fc0a863a92debe84b2d294 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm" 1136768653 1120 8b7d695260f3cff42e636090a8002094 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti10.tfm" 1136768653 1480 aa8e34af0eb6a2941b776984cf1dfdc4 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti12.tfm" 1136768653 1484 ed72f8f5cf654cda15ecc8e32bfcbee5 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb" 1248133631 34811 78b52f49e893bcba91bd7581cdc144c0 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb" 1248133631 32080 340ef9bf63678554ee606688e7b5339d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx8.pfb" 1248133631 32166 b0c356b15f19587482a9217ce1d8fa67 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmcsc10.pfb" 1248133631 32001 6aeea3afe875097b1eb0da29acd61e28 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb" 1248133631 30251 6afa5cb1d0204815a708a080681d4674 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb" 1248133631 36281 c355509802a035cadc5f15869451dcee "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb" 1248133631 35469 70d41d2b9ea31d5d813066df7c99281c "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb" 1248133631 35752 024fb6c41858982481f6968b5fc26508 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb" 1248133631 32722 d7379af29a190c3f453aba36302ff5a9 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb" 1248133631 31809 8670ca339bf94e56da1fc21c80635e2a "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb" 1248133631 32762 224316ccc9ad3ca0423a14971cfa7fc1 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb" 1248133631 32726 0a1aea6fcd6468ee2cf64d891f5c43c8 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb" 1248133631 33993 9b89b85fd2d9df0482bd47194d1d3bf3 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1248133631 32569 5e5ddc8df908dea60932f3c484a54c0d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy5.pfb" 1248133631 32915 7bf7720c61a5b3a7ff25b0964421c9b6 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb" 1248133631 32716 08e384dc442464e7285e891af9f45947 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb" 1248133631 37944 359e864bd06cde3b1cf57bb20757fb06 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb" 1248133631 36118 fad905eba93cff5bce1e185fe980a177 "" + "/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex" 1601326656 992 855ff26741653ab54814101ca36e153c "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex" 1601326656 43820 1fef971b75380574ab35a0d37fd92608 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex" 1601326656 19324 f4e4c6403dd0f1605fd20ed22fa79dea "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex" 1601326656 6038 ccb406740cc3f03bbfb58ad504fe8c27 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex" 1601326656 6944 e12f8f7a7364ddf66f93ba30fb3a3742 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex" 1601326656 4883 42daaf41e27c3735286e23e48d2d7af9 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex" 1601326656 2544 8c06d2a7f0f469616ac9e13db6d2f842 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex" 1601326656 44195 5e390c414de027626ca5e2df888fa68d "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex" 1601326656 17311 2ef6b2e29e2fc6a2fc8d6d652176e257 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex" 1601326656 21302 788a79944eb22192a4929e46963a3067 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex" 1601326656 9690 01feb7cde25d4293ef36eef45123eb80 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex" 1601326656 33335 dd1fa4814d4e51f18be97d88bf0da60c "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex" 1601326656 2965 4c2b1f4e0826925746439038172e5d6f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex" 1601326656 5196 2cc249e0ee7e03da5f5f6589257b1e5b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex" 1601326656 20726 d4c8db1e2e53b72721d29916314a22ea "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex" 1601326656 35249 abd4adf948f960299a4b3d27c5dddf46 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex" 1601326656 21989 fdc867d05d228316de137a9fc5ec3bbe "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex" 1601326656 8893 e851de2175338fdf7c17f3e091d94618 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex" 1601326656 3986 90961e1e824ee04363a83e4b53cbd527 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex" 1601326656 3937 3f208572dd82c71103831da976d74f1a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex" 1601326656 919 938802205ca20d7c36615aabc4d34be2 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex" 1608933718 11518 738408f795261b70ce8dd47459171309 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex" 1621110968 186007 6e7dfe0bd57520fd5f91641aa72dcac8 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex" 1601326656 32995 ac577023e12c0e4bd8aa420b2e852d1a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex" 1601326656 62281 aff261ef10ba6cbe8e3c872a38c05a61 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex" 1557692582 3063 8c415c68a0f3394e45cfeca0b65f6ee6 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex" 1601326656 521 8e224a7af69b7fee4451d1bf76b46654 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex" 1601326656 13391 84d29568c13bdce4133ab4a214711112 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex" 1601326656 104935 184ed87524e76d4957860df4ce0cd1c3 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex" 1601326656 10165 cec5fa73d49da442e56efc2d605ef154 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex" 1601326656 28178 41c17713108e0795aac6fef3d275fbca "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex" 1601326656 9989 c55967bf45126ff9b061fa2ca0c4694f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex" 1601326656 3865 ac538ab80c5cf82b345016e474786549 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex" 1557692582 3177 27d85c44fbfe09ff3b2cf2879e3ea434 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex" 1621110968 11024 0179538121bc2dba172013a3ef89519f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex" 1608933718 7854 4176998eeefd8745ac6d2d4bd9c98451 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex" 1601326656 3379 781797a101f647bab82741a99944a229 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex" 1601326656 92405 f515f31275db273f97b9d8f52e1b0736 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex" 1601326656 37376 11cd75aac3da1c1b152b2848f30adc14 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex" 1601326656 8471 c2883569d03f69e8e1cabfef4999cfd7 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex" 1601326656 21201 08d231a2386e2b61d64641c50dc15abd "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex" 1601326656 16121 346f9013d34804439f7436ff6786cef7 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex" 1621110968 44784 cedaa399d15f95e68e22906e2cc09ef8 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex" 1621110968 465 d68603f8b820ea4a08cce534944db581 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg" 1601326656 926 2963ea0dcf6cc6c0a770b69ec46a477b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def" 1601326656 5546 f3f24d7898386cb7daac70bdd2c4d6dc "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def" 1601326656 12601 4786e597516eddd82097506db7cfa098 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex" 1621110968 61163 9b2eefc24e021323e0fc140e9826d016 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex" 1601326656 1896 b8e0ca0ac371d74c0ca05583f6313c91 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex" 1601326656 7778 53c8b5623d80238f6a20aa1df1868e63 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex" 1606168878 23997 a4bed72405fa644418bea7eac2887006 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex" 1621110968 37060 797782f0eb50075c9bc952374d9a659a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex" 1601326656 37431 9abe862035de1b29c7a677f3205e3d9f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex" 1601326656 4494 af17fb7efeafe423710479858e42fa7e "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex" 1601326656 7251 fb18c67117e09c64de82267e12cd8aa4 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex" 1621110968 29274 e15c5b7157d21523bd9c9f1dfa146b8e "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def" 1621110968 6825 a2b0ea5b539dda0625e99dd15785ab59 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty" 1160617237 26750 ce139c05a983e19ddca355b43e29c395 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty" 1160617237 3457 d9077efe6b74c5a094199256af8d7d9a "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty" 1251330371 3249 15763257e50278eef5db1952ccde229c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty" 1591045760 12594 0d51ac3a545aaaa555021326ff22a6cc "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty" 1359763108 5949 3f3fd50a8cc94c3d4cbf4fc66cd3df1c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd" 1359763108 961 6518c6525a34feb5e8250ffa91731cff "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd" 1359763108 961 d02606146ba5601b5645f987c92e6193 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty" 1622667781 2222 da905dc1db75412efd2d8f67739f0596 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty" 1622667781 4173 bc0410bcccdff806d6132d3c1ef35481 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty" 1636758526 87648 07fbb6e9169e00cb2a2f40b31b2dbf3c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty" 1636758526 4128 8eea906621b6639f7ba476a472036bbe "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty" 1636758526 2444 926f379cc60fcf0c6e3fee2223b4370d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls" 1636758526 20144 8a7de377ae7a11ee924a7499611f5a9d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty" 1622581934 5157 f308c7c04889e16c588e78aa42599fae "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo" 1636758526 8448 96f18c76bf608a36ee6fbf021ac1dd32 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty" 1579991033 13886 d1306dcf79a944f6988e688c1785f9ce "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty" 1612734021 3131 63fa3429cc10864383493f8b120bce11 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty" 1612734021 17086 7ed8cbc4d361ec87392817e0dd4f65ec "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty" 1137110151 6749 16d2656a1984957e674b149555f1ea1d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg" 1459978653 1213 620bba36b25224fa9b7e1ccb4ecb76fd "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg" 1465944070 1224 978390e9c2234eab29404bc21b268d1e "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def" 1601931164 19103 48d29b6e2a64cb717117ef65f107b404 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty" 1622581934 18399 7e40f80366dffb22c0e7b70517db5cb4 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty" 1636758526 7996 a8fb260d598dcaf305a7ae7b9c3e3229 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty" 1622581934 2671 4de6781a30211fe0ea4c672e4a2a8166 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty" 1636758526 4009 187ea2dc3194cd5a76cd99a8d7a6c4d0 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1644269979 29921 d0acc05a38bd4aa3af2017f0b7c137ce "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg" 1279039959 678 4792914a8f45be57bb98413425e4c7af "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty" 1601326656 1090 bae35ef70b3168089ef166db3e66f5b2 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty" 1601326656 410 615550c46f918fcbee37641b02a862d9 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty" 1601326656 21013 f4ff83d25bb56552493b030f27c075ae "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty" 1601326656 989 c49c8ae06d96f8b15869da7428047b1e "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty" 1601326656 339 c2e180022e3afdb99c7d0ea5ce469b7d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty" 1601326656 306 c56a323ca5bf9242f54474ced10fca71 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty" 1601326656 443 8c872229db56122037e86bcda49e14f3 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty" 1601326656 348 ee405e64380c11319f0e249fed57e6c5 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty" 1601326656 274 5ae372b7df79135d240456a1c6f2cf9a "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty" 1601326656 325 f9f16d12354225b7dd52a3321f085955 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty" 1635798903 56029 3f7889dab51d620aa43177c391b7b190 "" + "/usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf" 1646502317 40171 cdab547de63d26590bebb3baff566530 "" + "/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map" 1647878959 4410336 7d30a02e9fa9a16d7d1f8d037ba69641 "" + "/usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt" 1652326579 2826440 ad4e2d767fc79c480c2262486c0f8a02 "" + "/usr/local/texlive/2022/texmf.cnf" 1647878952 577 209b46be99c9075fd74d4c0369380e8c "" + "0.diagnostic_A.algebra.aux" 1652492873 1324 cba3f8276ffed668c77ee642445defb6 "pdflatex" + "0.diagnostic_A.algebra.tex" 1652492872 16017 57c386492179471746b5f9b461c1d6df "" + (generated) + "0.diagnostic_A.algebra.aux" + "0.diagnostic_A.algebra.log" + "0.diagnostic_A.algebra.pdf" diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fls b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fls new file mode 100644 index 00000000..1ef553e1 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.fls @@ -0,0 +1,564 @@ +PWD /Users/robbintt/code/outlines/digests/calculus_early_transcendentals_9th_stewart/1_chapter +INPUT /usr/local/texlive/2022/texmf.cnf +INPUT /usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf +INPUT /usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt +INPUT 0.diagnostic_A.algebra.tex +OUTPUT 0.diagnostic_A.algebra.log +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT ./0.diagnostic_A.algebra.aux +INPUT 0.diagnostic_A.algebra.aux +INPUT 0.diagnostic_A.algebra.aux +OUTPUT 0.diagnostic_A.algebra.aux +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr17.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr9.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmex10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm +OUTPUT 0.diagnostic_A.algebra.pdf +INPUT /usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti10.tfm +INPUT 0.diagnostic_A.algebra.aux +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmcsc10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy5.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.log b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.log new file mode 100644 index 00000000..2758aded --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.log @@ -0,0 +1,520 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.5.11) 13 MAY 2022 18:47 +entering extended mode + restricted \write18 enabled. + file:line:error style messages enabled. + %&-line parsing enabled. +**0.diagnostic_A.algebra.tex +(./0.diagnostic_A.algebra.tex +LaTeX2e <2021-11-15> patch level 1 +L3 programming layer <2022-02-24> (/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +Document Class: article 2021/10/04 v1.4n Standard LaTeX document class +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2021/10/04 v1.4n Standard LaTeX file (size option) +) +\c@part=\count185 +\c@section=\count186 +\c@subsection=\count187 +\c@subsubsection=\count188 +\c@paragraph=\count189 +\c@subparagraph=\count190 +\c@figure=\count191 +\c@table=\count192 +\abovecaptionskip=\skip47 +\belowcaptionskip=\skip48 +\bibindent=\dimen138 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +Package: fancyhdr 2021/01/28 v4.0.1 Extensive control of page headers and footers +\f@nch@headwidth=\skip49 +\f@nch@O@elh=\skip50 +\f@nch@O@erh=\skip51 +\f@nch@O@olh=\skip52 +\f@nch@O@orh=\skip53 +\f@nch@O@elf=\skip54 +\f@nch@O@erf=\skip55 +\f@nch@O@olf=\skip56 +\f@nch@O@orf=\skip57 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +Package: extramarks 2021/01/28 v4.0.1 Extra marks for LaTeX +\@temptokenb=\toks16 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +Package: amsmath 2021/10/15 v2.17l AMS math features +\@mathmargin=\skip58 + +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +Package: amstext 2021/08/26 v2.01 AMS text + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks17 +\ex@=\dimen139 +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen140 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +Package: amsopn 2021/08/26 v2.02 operator names +) +\inf@bad=\count193 +LaTeX Info: Redefining \frac on input line 234. +\uproot@=\count194 +\leftroot@=\count195 +LaTeX Info: Redefining \overline on input line 399. +\classnum@=\count196 +\DOTSCASE@=\count197 +LaTeX Info: Redefining \ldots on input line 496. +LaTeX Info: Redefining \dots on input line 499. +LaTeX Info: Redefining \cdots on input line 620. +\Mathstrutbox@=\box50 +\strutbox@=\box51 +\big@size=\dimen141 +LaTeX Font Info: Redeclaring font encoding OML on input line 743. +LaTeX Font Info: Redeclaring font encoding OMS on input line 744. +\macc@depth=\count198 +\c@MaxMatrixCols=\count199 +\dotsspace@=\muskip16 +\c@parentequation=\count266 +\dspbrk@lvl=\count267 +\tag@help=\toks18 +\row@=\count268 +\column@=\count269 +\maxfields@=\count270 +\andhelp@=\toks19 +\eqnshift@=\dimen142 +\alignsep@=\dimen143 +\tagshift@=\dimen144 +\tagwidth@=\dimen145 +\totwidth@=\dimen146 +\lineht@=\dimen147 +\@envbody=\toks20 +\multlinegap=\skip59 +\multlinetaggap=\skip60 +\mathdisplay@stack=\toks21 +LaTeX Info: Redefining \[ on input line 2938. +LaTeX Info: Redefining \] on input line 2939. +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +Package: amsthm 2020/05/29 v2.20.6 +\thm@style=\toks22 +\thm@bodyfont=\toks23 +\thm@headfont=\toks24 +\thm@notefont=\toks25 +\thm@headpunct=\toks26 +\thm@preskip=\skip61 +\thm@postskip=\skip62 +\thm@headsep=\skip63 +\dth@everypar=\toks27 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +\pgfutil@everybye=\toks28 +\pgfutil@tempdima=\dimen148 +\pgfutil@tempdimb=\dimen149 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +\pgfutil@abb=\box52 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex) +Package: pgfrcs 2021/05/15 v3.1.9a (3.1.9a) +)) +Package: pgf 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks29 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +Package: trig 2021/08/11 v1.11 sin cos tan (DPC) +) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 107. + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex +)) +\Gin@req@height=\dimen150 +\Gin@req@width=\dimen151 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +Package: pgfsys 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +\pgfkeys@pathtoks=\toks30 +\pgfkeys@temptoks=\toks31 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex +\pgfkeys@tmptoks=\toks32 +)) +\pgf@x=\dimen152 +\pgf@y=\dimen153 +\pgf@xa=\dimen154 +\pgf@ya=\dimen155 +\pgf@xb=\dimen156 +\pgf@yb=\dimen157 +\pgf@xc=\dimen158 +\pgf@yc=\dimen159 +\pgf@xd=\dimen160 +\pgf@yd=\dimen161 +\w@pgf@writea=\write3 +\r@pgf@reada=\read2 +\c@pgf@counta=\count271 +\c@pgf@countb=\count272 +\c@pgf@countc=\count273 +\c@pgf@countd=\count274 +\t@pgf@toka=\toks33 +\t@pgf@tokb=\toks34 +\t@pgf@tokc=\toks35 +\pgf@sys@id@count=\count275 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg +File: pgf.cfg 2021/05/15 v3.1.9a (3.1.9a) +) +Driver file for pgf: pgfsys-pdftex.def + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +File: pgfsys-pdftex.def 2021/05/15 v3.1.9a (3.1.9a) + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def +File: pgfsys-common-pdf.def 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +File: pgfsyssoftpath.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfsyssoftpath@smallbuffer@items=\count276 +\pgfsyssoftpath@bigbuffer@items=\count277 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +File: pgfsysprotocol.code.tex 2021/05/15 v3.1.9a (3.1.9a) +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +File: color.cfg 2016/01/02 v1.6 sample color configuration +) +Package xcolor Info: Driver file: pdftex.def on input line 227. +Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1352. +Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1356. +Package xcolor Info: Model `RGB' extended on input line 1368. +Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1370. +Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1371. +Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1372. +Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1373. +Package xcolor Info: Model `Gray' substituted by `gray' on input line 1374. +Package xcolor Info: Model `wave' substituted by `hsb' on input line 1375. +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +Package: pgfcore 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +\pgfmath@dimen=\dimen162 +\pgfmath@count=\count278 +\pgfmath@box=\box53 +\pgfmath@toks=\toks36 +\pgfmath@stack@operand=\toks37 +\pgfmath@stack@operation=\toks38 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +\c@pgfmathroundto@lastzeros=\count279 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex +File: pgfcorepoints.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@picminx=\dimen163 +\pgf@picmaxx=\dimen164 +\pgf@picminy=\dimen165 +\pgf@picmaxy=\dimen166 +\pgf@pathminx=\dimen167 +\pgf@pathmaxx=\dimen168 +\pgf@pathminy=\dimen169 +\pgf@pathmaxy=\dimen170 +\pgf@xx=\dimen171 +\pgf@xy=\dimen172 +\pgf@yx=\dimen173 +\pgf@yy=\dimen174 +\pgf@zx=\dimen175 +\pgf@zy=\dimen176 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex +File: pgfcorepathconstruct.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@path@lastx=\dimen177 +\pgf@path@lasty=\dimen178 +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +File: pgfcorepathusage.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@shorten@end@additional=\dimen179 +\pgf@shorten@start@additional=\dimen180 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +File: pgfcorescopes.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfpic=\box54 +\pgf@hbox=\box55 +\pgf@layerbox@main=\box56 +\pgf@picture@serial@count=\count280 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +File: pgfcoregraphicstate.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgflinewidth=\dimen181 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +File: pgfcoretransformations.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@pt@x=\dimen182 +\pgf@pt@y=\dimen183 +\pgf@pt@temp=\dimen184 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex +File: pgfcorequick.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex +File: pgfcoreobjects.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex +File: pgfcorepathprocessing.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +File: pgfcorearrows.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfarrowsep=\dimen185 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex +File: pgfcoreshade.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@max=\dimen186 +\pgf@sys@shading@range@num=\count281 +\pgf@shadingcount=\count282 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex +File: pgfcoreimage.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex +File: pgfcoreexternal.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfexternal@startupbox=\box57 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex +File: pgfcorelayers.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex +File: pgfcoretransparency.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex +File: pgfcorepatterns.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex +File: pgfcorerdf.code.tex 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +File: pgfmoduleshapes.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfnodeparttextbox=\box58 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +File: pgfmoduleplot.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +Package: pgfcomp-version-0-65 2021/05/15 v3.1.9a (3.1.9a) +\pgf@nodesepstart=\dimen187 +\pgf@nodesepend=\dimen188 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +Package: pgfcomp-version-1-18 2021/05/15 v3.1.9a (3.1.9a) +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +Package: pgffor 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex) +\pgffor@iter=\dimen189 +\pgffor@skip=\dimen190 +\pgffor@stack=\toks39 +\pgffor@toks=\toks40 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +Package: tikz 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +File: pgflibraryplothandlers.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@plot@mark@count=\count283 +\pgfplotmarksize=\dimen191 +) +\tikz@lastx=\dimen192 +\tikz@lasty=\dimen193 +\tikz@lastxsaved=\dimen194 +\tikz@lastysaved=\dimen195 +\tikz@lastmovetox=\dimen196 +\tikz@lastmovetoy=\dimen197 +\tikzleveldistance=\dimen198 +\tikzsiblingdistance=\dimen199 +\tikz@figbox=\box59 +\tikz@figbox@bg=\box60 +\tikz@tempbox=\box61 +\tikz@tempbox@bg=\box62 +\tikztreelevel=\count284 +\tikznumberofchildren=\count285 +\tikznumberofcurrentchild=\count286 +\tikz@fig@count=\count287 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex +File: pgfmodulematrix.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfmatrixcurrentrow=\count288 +\pgfmatrixcurrentcolumn=\count289 +\pgf@matrix@numberofcolumns=\count290 +) +\tikz@expandcount=\count291 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +File: tikzlibrarytopaths.code.tex 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +Package: algorithm 2009/08/24 v0.1 Document Style `algorithm' - floating environment + (/usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +Package: float 2001/11/08 v1.3d Float enhancements (AL) +\c@float@type=\count292 +\float@exts=\toks41 +\float@box=\box63 +\@float@everytoks=\toks42 +\@floatcapt=\box64 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +Package: ifthen 2020/11/24 v1.1c Standard LaTeX ifthen package (DPC) +) +\@float@every@algorithm=\toks43 +\c@algorithm=\count293 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +Package: algpseudocode + (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +Package: algorithmicx 2005/04/27 v1.2 Algorithmicx + +Document Style algorithmicx 1.2 - a greatly improved `algorithmic' style +\c@ALG@line=\count294 +\c@ALG@rem=\count295 +\c@ALG@nested=\count296 +\ALG@tlm=\skip64 +\ALG@thistlm=\skip65 +\c@ALG@Lnr=\count297 +\c@ALG@blocknr=\count298 +\c@ALG@storecount=\count299 +\c@ALG@tmpcounter=\count300 +\ALG@tmplength=\skip66 +) +Document Style - pseudocode environments for use with the `algorithmicx' style +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +File: tikzlibraryautomata.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +File: tikzlibraryshapes.multipart.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +File: pgflibraryshapes.multipart.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfnodepartlowerbox=\box65 +\pgfnodeparttwobox=\box66 +\pgfnodepartthreebox=\box67 +\pgfnodepartfourbox=\box68 +\pgfnodeparttwentybox=\box69 +\pgfnodepartnineteenbox=\box70 +\pgfnodeparteighteenbox=\box71 +\pgfnodepartseventeenbox=\box72 +\pgfnodepartsixteenbox=\box73 +\pgfnodepartfifteenbox=\box74 +\pgfnodepartfourteenbox=\box75 +\pgfnodepartthirteenbox=\box76 +\pgfnodeparttwelvebox=\box77 +\pgfnodepartelevenbox=\box78 +\pgfnodeparttenbox=\box79 +\pgfnodepartninebox=\box80 +\pgfnodeparteightbox=\box81 +\pgfnodepartsevenbox=\box82 +\pgfnodepartsixbox=\box83 +\pgfnodepartfivebox=\box84 +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +File: tikzlibrarypositioning.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) +\c@partCounter=\count301 +\c@homeworkProblemCounter=\count302 + (/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count303 +\l__pdf_internal_box=\box85 +) (./0.diagnostic_A.algebra.aux) +\openout1 = `0.diagnostic_A.algebra.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. + (/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count304 +\scratchdimen=\dimen256 +\scratchbox=\box86 +\nofMPsegments=\count305 +\nofMParguments=\count306 +\everyMPshowfont=\toks44 +\MPscratchCnt=\count307 +\MPscratchDim=\dimen257 +\MPnumerator=\count308 +\makeMPintoPDFobject=\count309 +\everyMPtoPDFconversion=\toks45 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 485. + (/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live +)) +LaTeX Font Info: Trying to load font information for U+msa on input line 140. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Trying to load font information for U+msb on input line 140. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) [1 + +{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] +Underfull \hbox (badness 10000) in paragraph at lines 217--220 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 235--237 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 256--258 + + [] + +[3] +Underfull \hbox (badness 10000) in paragraph at lines 278--281 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 315--317 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 318--324 + + [] + + +LaTeX Font Warning: Font shape `OT1/cmr/bx/sc' undefined +(Font) using `OT1/cmr/bx/n' instead on input line 349. + + +LaTeX Warning: No positions in optional float specifier. + Default added (so using `htbp') on input line 351. + +[4] +Underfull \hbox (badness 10000) in paragraph at lines 369--374 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 376--380 + + [] + +[5] +Underfull \hbox (badness 10000) in paragraph at lines 431--435 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 478--481 + + [] + +[6] +Underfull \hbox (badness 10000) in paragraph at lines 548--554 + + [] + +[7] [8] (./0.diagnostic_A.algebra.aux) + +LaTeX Font Warning: Some font shapes were not available, defaults substituted. + + ) +Here is how much of TeX's memory you used: + 14363 strings out of 478268 + 300044 string characters out of 5846347 + 581676 words of memory out of 5000000 + 32314 multiletter control sequences out of 15000+600000 + 479633 words of font info for 67 fonts, out of 8000000 for 9000 + 1141 hyphenation exceptions out of 8191 + 100i,17n,104p,432b,981s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on 0.diagnostic_A.algebra.pdf (8 pages, 223517 bytes). +PDF statistics: + 129 PDF objects out of 1000 (max. 8388607) + 80 compressed objects within 1 object stream + 0 named destinations out of 1000 (max. 500000) + 13 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.pdf b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.pdf new file mode 100644 index 00000000..b065b7b1 Binary files /dev/null and b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.pdf differ diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.synctex.gz b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.synctex.gz new file mode 100644 index 00000000..4230d46a Binary files /dev/null and b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.synctex.gz differ diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.tex b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.tex new file mode 100644 index 00000000..856e9db9 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/0.diagnostic_A.algebra.tex @@ -0,0 +1,600 @@ +\documentclass{article} + +\usepackage{fancyhdr} +\usepackage{extramarks} +\usepackage{amsmath} +\usepackage{amsthm} +\usepackage{amsfonts} +\usepackage{tikz} +\usepackage[plain]{algorithm} +\usepackage{algpseudocode} + +\usetikzlibrary{automata,positioning} + +% +% Basic Document Settings +% + +\topmargin=-0.45in +\evensidemargin=0in +\oddsidemargin=0in +\textwidth=6.5in +\textheight=9.0in +\headsep=0.25in + +\linespread{1.1} + +\pagestyle{fancy} +\lhead{\hmwkAuthorName} +\chead{\ \hmwkBook\ (\hmwkBookInstructor): \hmwkTitle} +\rhead{\firstxmark} +\lfoot{\lastxmark} +\cfoot{\thepage} + +\renewcommand\headrulewidth{0.4pt} +\renewcommand\footrulewidth{0.4pt} + +\setlength\parindent{0pt} + +% +% Create Problem Sections +% + +\newcommand{\enterProblemHeader}[1]{ + \nobreak\extramarks{}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} +} + +\newcommand{\exitProblemHeader}[1]{ + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \stepcounter{#1} + \nobreak\extramarks{Problem \arabic{#1}}{}\nobreak{} +} + +\setcounter{secnumdepth}{0} +\newcounter{partCounter} +\newcounter{homeworkProblemCounter} +\setcounter{homeworkProblemCounter}{1} +\nobreak\extramarks{Problem \arabic{homeworkProblemCounter}}{}\nobreak{} + +% +% Homework Problem Environment +% +% This environment takes an optional argument. When given, it will adjust the +% problem counter. This is useful for when the problems given for your +% assignment aren't sequential. See the last 3 problems of this template for an +% example. +% +\newenvironment{homeworkProblem}[1][-1]{ + \ifnum#1>0 + \setcounter{homeworkProblemCounter}{#1} + \fi + \section{Problem \arabic{homeworkProblemCounter}} + \setcounter{partCounter}{1} + \enterProblemHeader{homeworkProblemCounter} +}{ + \exitProblemHeader{homeworkProblemCounter} +} + +% +% Homework Details +% - Title +% - Completed date +% - Book +% - Section/Time +% - Instructor +% - Author +% + +\newcommand{\hmwkTitle}{Diagnostic A: Algebra} +\newcommand{\hmwkCompletedDate}{May 13, 2022} +\newcommand{\hmwkBook}{Calculus: Early Transcendentals, 9th Ed.} +\newcommand{\hmwkBookInstructor}{Stewart} +\newcommand{\hmwkAuthorName}{Trent Robbins} + +% +% Title Page +% + +\title{ + \vspace{2in} + \textmd{\textbf{\hmwkBook}}\\ + \textmd{\textbf{\hmwkTitle}}\\ + \normalsize\vspace{0.1in}\small{Completed\ on\ \hmwkCompletedDate}\\ + \vspace{0.1in}\large{\textit{\hmwkBookInstructor}} + \vspace{3in} +} + +\author{\hmwkAuthorName} +\date{} + +\renewcommand{\part}[1]{\textbf{\large Part \Alph{partCounter}}\stepcounter{partCounter}\\} + +% +% Various Helper Commands +% + +% Useful for algorithms +\newcommand{\alg}[1]{\textsc{\bfseries \footnotesize #1}} + +% For derivatives +\newcommand{\deriv}[1]{\frac{\mathrm{d}}{\mathrm{d}x} (#1)} + +% For partial derivatives +\newcommand{\pderiv}[2]{\frac{\partial}{\partial #1} (#2)} + +% Integral dx +\newcommand{\dx}{\mathrm{d}x} + +% Alias for the Solution section header +\newcommand{\solution}{\textbf{\large Solution}} + +% Probability commands: Expectation, Variance, Covariance, Bias +\newcommand{\E}{\mathrm{E}} +\newcommand{\Var}{\mathrm{Var}} +\newcommand{\Cov}{\mathrm{Cov}} +\newcommand{\Bias}{\mathrm{Bias}} + +\begin{document} + +\maketitle + +\pagebreak + +\begin{homeworkProblem} + Evaluate each expression without using a calculator. + + \begin{enumerate} + \item \((-3)^4 = 81\) + \item \(-3^4 = -81\) + \item \(3^{-4} = 1/3^4 = 1/81\) + \item \(5^{23}/5^{21} = 5^{23-21} = 5^2 = 25\) + \item \((2/3)^{-2} = (2/3)^{-1*2} = (3/2)^2 = 9/4 \) + \item \(16^{-3/4} = \displaystyle(16^{\frac{3}{4}})^{-1} = \displaystyle(\frac{1}{16^{\frac{3}{4}}}) = \displaystyle\frac{1}{(\sqrt[4]{16})^3} = \frac{1}{2^3} = \frac{1}{8} \) + \end{enumerate} + +\end{homeworkProblem} + +\begin{homeworkProblem} + Simplify each expression. Write your answer without negative exponents. + + \begin{enumerate} + \item \( \sqrt{200} - \sqrt{32} = \sqrt{100*2} - \sqrt{16*2} = 100 * \sqrt{100*2} - 8 * \sqrt{16*2} = 10 * \sqrt{2} - 4 * sqrt{2} = 6*\sqrt{2} \) + \begin{enumerate} + \item note that 32 is a power of 2; we can get a clean factor + \item since \( 100 * 2 \) is also a perfect square factor of 200 + \item many factors of 200: \(1, 2, 4, 5, 10, 20, 40, 50, 100, 200\) + \end{enumerate} + \item \((3a^3b^3)(4ab^2)^2 = 3*4*4*a^3*a*a*b^3*b^2*b^2 = 48a^5b^7 \) + \item \( \displaystyle(\frac{3x^{3/2}y^3}{x^2y^{\frac{-1}{2}}})^{-2} = \displaystyle\frac{(x^2y^{\frac{-1}{2}})^2}{(3x^{3/2}y^3)^2} = \displaystyle\frac{x^4y^{-1}}{9x^3y^6} = \displaystyle\frac{x}{9y^7} \) + + \end{enumerate} + +\end{homeworkProblem} + +\begin{homeworkProblem} + Expand and simplify + + \begin{enumerate} + \item \( 3(x+6)+4(2x-5) = 3x+3*6+8x-20 = 11x-2 \) + \item \( (\sqrt{a} + \sqrt{b})(\sqrt{a}-\sqrt{b}) = a-b \) + \item \( (x + 3)(4x - 5) = 4x^2+7x-15 \) + \item \( (2x+3)^2 = 4x^2 + 12x + 9 \) + \item \( (x+2)^3 = = (x+2)(x+2)(x+2) = x^3 + 6x^2 + 12x+ 8 \) + \end{enumerate} + +\end{homeworkProblem} + +\begin{homeworkProblem} + Factor each expression. + + \begin{enumerate} + \item \( 4x^2 - 25 = (2x - 5)(2x + 5) \) + \item \( 2x^2+5x-12 = (2x - 3)(1x + 4) \) - solved by factor and brute force + \begin{enumerate} + \item System of equations... hmm - how can we solve below? + \item \( a,b,c,d : b*d=-12, a*c=2, a*d+b*c=5 \) + \end{enumerate} + \item \( x^3-3x^2-4x+12 \) + \end{enumerate} + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Give an appropriate positive constant \(c\) such that \(f(n) \leq c \cdot + g(n)\) for all \(n > 1\). + + \begin{enumerate} + \item \(f(n) = n^2 + n + 1\), \(g(n) = 2n^3\) + \item \(f(n) = n\sqrt{n} + n^2\), \(g(n) = n^2\) + \item \(f(n) = n^2 - n + 1\), \(g(n) = n^2 / 2\) + \end{enumerate} + + \textbf{Solution} + + We solve each solution algebraically to determine a possible constant + \(c\). + \\ + + \textbf{Part One} + + \[ + \begin{split} + n^2 + n + 1 &= + \\ + &\leq n^2 + n^2 + n^2 + \\ + &= 3n^2 + \\ + &\leq c \cdot 2n^3 + \end{split} + \] + + Thus a valid \(c\) could be when \(c = 2\). + \\ + + \textbf{Part Two} + + \[ + \begin{split} + n^2 + n\sqrt{n} &= + \\ + &= n^2 + n^{3/2} + \\ + &\leq n^2 + n^{4/2} + \\ + &= n^2 + n^2 + \\ + &= 2n^2 + \\ + &\leq c \cdot n^2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + \\ + + \textbf{Part Three} + + \[ + \begin{split} + n^2 - n + 1 &= + \\ + &\leq n^2 + \\ + &\leq c \cdot n^2/2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Let \(\Sigma = \{0, 1\}\). Construct a DFA \(A\) that recognizes the + language that consists of all binary numbers that can be divided by 5. + \\ + + Let the state \(q_k\) indicate the remainder of \(k\) divided by 5. For + example, the remainder of 2 would correlate to state \(q_2\) because \(7 + \mod 5 = 2\). + + \begin{figure}[h] + \centering + \begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto] + \node[state, accepting, initial] (q_0) {$q_0$}; + \node[state] (q_1) [right=of q_0] {$q_1$}; + \node[state] (q_2) [right=of q_1] {$q_2$}; + \node[state] (q_3) [right=of q_2] {$q_3$}; + \node[state] (q_4) [right=of q_3] {$q_4$}; + \path[->] + (q_0) + edge [loop above] node {0} (q_0) + edge node {1} (q_1) + (q_1) + edge node {0} (q_2) + edge [bend right=-30] node {1} (q_3) + (q_2) + edge [bend left] node {1} (q_0) + edge [bend right=-30] node {0} (q_4) + (q_3) + edge node {1} (q_2) + edge [bend left] node {0} (q_1) + (q_4) + edge node {0} (q_3) + edge [loop below] node {1} (q_4); + \end{tikzpicture} + \caption{DFA, \(A\), this is really beautiful, ya know?} + \label{fig:multiple5} + \end{figure} + + \textbf{Justification} + \\ + + Take a given binary number, \(x\). Since there are only two inputs to our + state machine, \(x\) can either become \(x0\) or \(x1\). When a 0 comes + into the state machine, it is the same as taking the binary number and + multiplying it by two. When a 1 comes into the machine, it is the same as + multipying by two and adding one. + \\ + + Using this knowledge, we can construct a transition table that tell us + where to go: + + \begin{table}[ht] + \centering + \begin{tabular}{c || c | c | c | c | c} + & \(x \mod 5 = 0\) + & \(x \mod 5 = 1\) + & \(x \mod 5 = 2\) + & \(x \mod 5 = 3\) + & \(x \mod 5 = 4\) + \\ + \hline + \(x0\) & 0 & 2 & 4 & 1 & 3 \\ + \(x1\) & 1 & 3 & 0 & 2 & 4 \\ + \end{tabular} + \end{table} + + Therefore on state \(q_0\) or (\(x \mod 5 = 0\)), a transition line should + go to state \(q_0\) for the input 0 and a line should go to state \(q_1\) + for input 1. Continuing this gives us the Figure~\ref{fig:multiple5}. +\end{homeworkProblem} + +\begin{homeworkProblem} + Write part of \alg{Quick-Sort($list, start, end$)} + + \begin{algorithm}[] + \begin{algorithmic}[1] + \Function{Quick-Sort}{$list, start, end$} + \If{$start \geq end$} + \State{} \Return{} + \EndIf{} + \State{} $mid \gets \Call{Partition}{list, start, end}$ + \State{} \Call{Quick-Sort}{$list, start, mid - 1$} + \State{} \Call{Quick-Sort}{$list, mid + 1, end$} + \EndFunction{} + \end{algorithmic} + \caption{Start of QuickSort} + \end{algorithm} +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Suppose we would like to fit a straight line through the origin, i.e., + \(Y_i = \beta_1 x_i + e_i\) with \(i = 1, \ldots, n\), \(\E [e_i] = 0\), + and \(\Var [e_i] = \sigma^2_e\) and \(\Cov[e_i, e_j] = 0, \forall i \neq + j\). + \\ + + \part + + Find the least squares esimator for \(\hat{\beta_1}\) for the slope + \(\beta_1\). + \\ + + \solution + + To find the least squares estimator, we should minimize our Residual Sum + of Squares, RSS: + + \[ + \begin{split} + RSS &= \sum_{i = 1}^{n} {(Y_i - \hat{Y_i})}^2 + \\ + &= \sum_{i = 1}^{n} {(Y_i - \hat{\beta_1} x_i)}^2 + \end{split} + \] + + By taking the partial derivative in respect to \(\hat{\beta_1}\), we get: + + \[ + \pderiv{ + \hat{\beta_1} + }{RSS} + = -2 \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + = 0 + \] + + This gives us: + + \[ + \begin{split} + \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + &= \sum_{i = 1}^{n} {x_i Y_i} - \sum_{i = 1}^{n} \hat{\beta_1} x_i^2 + \\ + &= \sum_{i = 1}^{n} {x_i Y_i} - \hat{\beta_1}\sum_{i = 1}^{n} x_i^2 + \end{split} + \] + + Solving for \(\hat{\beta_1}\) gives the final estimator for \(\beta_1\): + + \[ + \begin{split} + \hat{\beta_1} + &= \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + } + \end{split} + \] + + \pagebreak + + \part + + Calculate the bias and the variance for the estimated slope + \(\hat{\beta_1}\). + \\ + + \solution + + For the bias, we need to calculate the expected value + \(\E[\hat{\beta_1}]\): + + \[ + \begin{split} + \E[\hat{\beta_1}] + &= \E \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= \frac{ + \sum {x_i \E[Y_i]} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i (\beta_1 x_i)} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 + \end{split} + \] + + Thus since our estimator's expected value is \(\beta_1\), we can conclude + that the bias of our estimator is 0. + \\ + + For the variance: + + \[ + \begin{split} + \Var[\hat{\beta_1}] + &= \Var \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \sigma^2 + \\ + &= + \frac{ + \sigma^2 + }{ + \sum x_i^2 + } + \end{split} + \] + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Prove a polynomial of degree \(k\), \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + + a_1n^1 + a_0n^0\) is a member of \(\Theta(n^k)\) where \(a_k \hdots a_0\) + are nonnegative constants. + + \begin{proof} + To prove that \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + + a_0n^0\), we must show the following: + + \[ + \exists c_1 \exists c_2 \forall n \geq n_0,\ {c_1 \cdot g(n) \leq + f(n) \leq c_2 \cdot g(n)} + \] + + For the first inequality, it is easy to see that it holds because no + matter what the constants are, \(n^k \leq a_kn^k + a_{k - 1}n^{k - 1} + + \hdots + a_1n^1 + a_0n^0\) even if \(c_1 = 1\) and \(n_0 = 1\). This + is because \(n^k \leq c_1 \cdot a_kn^k\) for any nonnegative constant, + \(c_1\) and \(a_k\). + \\ + + Taking the second inequality, we prove it in the following way. + By summation, \(\sum\limits_{i=0}^k a_i\) will give us a new constant, + \(A\). By taking this value of \(A\), we can then do the following: + + \[ + \begin{split} + a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + a_0n^0 &= + \\ + &\leq (a_k + a_{k - 1} \hdots a_1 + a_0) \cdot n^k + \\ + &= A \cdot n^k + \\ + &\leq c_2 \cdot n^k + \end{split} + \] + + where \(n_0 = 1\) and \(c_2 = A\). \(c_2\) is just a constant. Thus the + proof is complete. + \end{proof} +\end{homeworkProblem} + +\pagebreak + +% +% Non sequential homework problems +% + +% Jump to problem 18 +\begin{homeworkProblem}[18] + Evaluate \(\sum_{k=1}^{5} k^2\) and \(\sum_{k=1}^{5} (k - 1)^2\). +\end{homeworkProblem} + +% Continue counting to 19 +\begin{homeworkProblem} + Find the derivative of \(f(x) = x^4 + 3x^2 - 2\) +\end{homeworkProblem} + +% Go back to where we left off +\begin{homeworkProblem}[6] + Evaluate the integrals + \(\int_0^1 (1 - x^2) \dx\) + and + \(\int_1^{\infty} \frac{1}{x^2} \dx\). +\end{homeworkProblem} + +\end{document} diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.aux b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.aux new file mode 100644 index 00000000..a63be404 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.aux @@ -0,0 +1,14 @@ +\relax +\@writefile{toc}{\contentsline {section}{Problem 1}{2}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 2}{3}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 3}{4}{}\protected@file@percent } +\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces DFA, \(A\), this is really beautiful, ya know?}}{4}{}\protected@file@percent } +\newlabel{fig:multiple5}{{1}{4}} +\@writefile{toc}{\contentsline {section}{Problem 4}{4}{}\protected@file@percent } +\@writefile{loa}{\contentsline {algorithm}{\numberline {1}{\ignorespaces Start of QuickSort}}{4}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 5}{5}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 6}{7}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 18}{8}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 19}{8}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{Problem 6}{8}{}\protected@file@percent } +\gdef \@abspage@last{8} diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fdb_latexmk b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fdb_latexmk new file mode 100644 index 00000000..3c3a7999 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fdb_latexmk @@ -0,0 +1,154 @@ +# Fdb version 3 +["pdflatex"] 1652470464 "1.1.tex" "1.1.pdf" "1.1" 1652470465 + "/usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm" 1246382020 916 f87d7c45f9c908e672703b83b72241a3 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm" 1246382020 924 9904cf1d39e9767e7a3622f2a125a565 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm" 1246382020 928 2dc8d444221b7a635bb58038579b861a "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm" 1246382020 908 2921f8a10601f252058503cc6570e581 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm" 1246382020 940 75ac932a52f80982a9f8ea75d03a34cf "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm" 1246382020 940 228d6584342e91276bf566bcf9716b83 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm" 1136768653 1328 c834bbb027764024c09d3d2bf908b5f0 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm" 1136768653 1324 c910af8c371558dc20f2d7822f66fe64 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx8.tfm" 1136768653 1332 1fde11373e221473104d6cc5993f046e "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm" 1136768653 1300 63a6111ee6274895728663cf4b4e7e81 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmex10.tfm" 1136768653 992 662f679a0b3d2d53c1b94050fdaa3f50 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm" 1136768653 1524 4414a8315f39513458b80dfc63bff03a "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm" 1136768653 1512 f21f83efb36853c0b70002322c1ab3ad "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm" 1136768653 1520 eccf95517727cb11801f4f1aee3a21b4 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr6.tfm" 1136768653 1300 b62933e007d01cfd073f79b963c01526 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr8.tfm" 1136768653 1292 21c1c5bfeaebccffdb478fd231a0997d "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr9.tfm" 1136768653 1292 6b21b9c2c7bebb38aa2273f7ca0fb3af "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm" 1136768653 1116 933a60c408fc0a863a92debe84b2d294 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm" 1136768653 1120 8b7d695260f3cff42e636090a8002094 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti10.tfm" 1136768653 1480 aa8e34af0eb6a2941b776984cf1dfdc4 "" + "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti12.tfm" 1136768653 1484 ed72f8f5cf654cda15ecc8e32bfcbee5 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb" 1248133631 34811 78b52f49e893bcba91bd7581cdc144c0 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb" 1248133631 32080 340ef9bf63678554ee606688e7b5339d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx8.pfb" 1248133631 32166 b0c356b15f19587482a9217ce1d8fa67 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmcsc10.pfb" 1248133631 32001 6aeea3afe875097b1eb0da29acd61e28 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb" 1248133631 30251 6afa5cb1d0204815a708a080681d4674 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb" 1248133631 36281 c355509802a035cadc5f15869451dcee "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb" 1248133631 35469 70d41d2b9ea31d5d813066df7c99281c "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb" 1248133631 35752 024fb6c41858982481f6968b5fc26508 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb" 1248133631 32722 d7379af29a190c3f453aba36302ff5a9 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb" 1248133631 31809 8670ca339bf94e56da1fc21c80635e2a "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb" 1248133631 32762 224316ccc9ad3ca0423a14971cfa7fc1 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb" 1248133631 32726 0a1aea6fcd6468ee2cf64d891f5c43c8 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb" 1248133631 33993 9b89b85fd2d9df0482bd47194d1d3bf3 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1248133631 32569 5e5ddc8df908dea60932f3c484a54c0d "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb" 1248133631 32716 08e384dc442464e7285e891af9f45947 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb" 1248133631 37944 359e864bd06cde3b1cf57bb20757fb06 "" + "/usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb" 1248133631 36118 fad905eba93cff5bce1e185fe980a177 "" + "/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex" 1601326656 992 855ff26741653ab54814101ca36e153c "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex" 1601326656 43820 1fef971b75380574ab35a0d37fd92608 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex" 1601326656 19324 f4e4c6403dd0f1605fd20ed22fa79dea "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex" 1601326656 6038 ccb406740cc3f03bbfb58ad504fe8c27 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex" 1601326656 6944 e12f8f7a7364ddf66f93ba30fb3a3742 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex" 1601326656 4883 42daaf41e27c3735286e23e48d2d7af9 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex" 1601326656 2544 8c06d2a7f0f469616ac9e13db6d2f842 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex" 1601326656 44195 5e390c414de027626ca5e2df888fa68d "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex" 1601326656 17311 2ef6b2e29e2fc6a2fc8d6d652176e257 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex" 1601326656 21302 788a79944eb22192a4929e46963a3067 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex" 1601326656 9690 01feb7cde25d4293ef36eef45123eb80 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex" 1601326656 33335 dd1fa4814d4e51f18be97d88bf0da60c "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex" 1601326656 2965 4c2b1f4e0826925746439038172e5d6f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex" 1601326656 5196 2cc249e0ee7e03da5f5f6589257b1e5b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex" 1601326656 20726 d4c8db1e2e53b72721d29916314a22ea "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex" 1601326656 35249 abd4adf948f960299a4b3d27c5dddf46 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex" 1601326656 21989 fdc867d05d228316de137a9fc5ec3bbe "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex" 1601326656 8893 e851de2175338fdf7c17f3e091d94618 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex" 1601326656 3986 90961e1e824ee04363a83e4b53cbd527 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex" 1601326656 3937 3f208572dd82c71103831da976d74f1a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex" 1601326656 919 938802205ca20d7c36615aabc4d34be2 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex" 1608933718 11518 738408f795261b70ce8dd47459171309 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex" 1621110968 186007 6e7dfe0bd57520fd5f91641aa72dcac8 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex" 1601326656 32995 ac577023e12c0e4bd8aa420b2e852d1a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex" 1601326656 62281 aff261ef10ba6cbe8e3c872a38c05a61 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex" 1557692582 3063 8c415c68a0f3394e45cfeca0b65f6ee6 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex" 1601326656 521 8e224a7af69b7fee4451d1bf76b46654 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex" 1601326656 13391 84d29568c13bdce4133ab4a214711112 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex" 1601326656 104935 184ed87524e76d4957860df4ce0cd1c3 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex" 1601326656 10165 cec5fa73d49da442e56efc2d605ef154 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex" 1601326656 28178 41c17713108e0795aac6fef3d275fbca "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex" 1601326656 9989 c55967bf45126ff9b061fa2ca0c4694f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex" 1601326656 3865 ac538ab80c5cf82b345016e474786549 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex" 1557692582 3177 27d85c44fbfe09ff3b2cf2879e3ea434 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex" 1621110968 11024 0179538121bc2dba172013a3ef89519f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex" 1608933718 7854 4176998eeefd8745ac6d2d4bd9c98451 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex" 1601326656 3379 781797a101f647bab82741a99944a229 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex" 1601326656 92405 f515f31275db273f97b9d8f52e1b0736 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex" 1601326656 37376 11cd75aac3da1c1b152b2848f30adc14 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex" 1601326656 8471 c2883569d03f69e8e1cabfef4999cfd7 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex" 1601326656 21201 08d231a2386e2b61d64641c50dc15abd "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex" 1601326656 16121 346f9013d34804439f7436ff6786cef7 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex" 1621110968 44784 cedaa399d15f95e68e22906e2cc09ef8 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex" 1621110968 465 d68603f8b820ea4a08cce534944db581 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg" 1601326656 926 2963ea0dcf6cc6c0a770b69ec46a477b "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def" 1601326656 5546 f3f24d7898386cb7daac70bdd2c4d6dc "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def" 1601326656 12601 4786e597516eddd82097506db7cfa098 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex" 1621110968 61163 9b2eefc24e021323e0fc140e9826d016 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex" 1601326656 1896 b8e0ca0ac371d74c0ca05583f6313c91 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex" 1601326656 7778 53c8b5623d80238f6a20aa1df1868e63 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex" 1606168878 23997 a4bed72405fa644418bea7eac2887006 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex" 1621110968 37060 797782f0eb50075c9bc952374d9a659a "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex" 1601326656 37431 9abe862035de1b29c7a677f3205e3d9f "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex" 1601326656 4494 af17fb7efeafe423710479858e42fa7e "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex" 1601326656 7251 fb18c67117e09c64de82267e12cd8aa4 "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex" 1621110968 29274 e15c5b7157d21523bd9c9f1dfa146b8e "" + "/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def" 1621110968 6825 a2b0ea5b539dda0625e99dd15785ab59 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty" 1160617237 26750 ce139c05a983e19ddca355b43e29c395 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty" 1160617237 3457 d9077efe6b74c5a094199256af8d7d9a "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty" 1251330371 3249 15763257e50278eef5db1952ccde229c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty" 1591045760 12594 0d51ac3a545aaaa555021326ff22a6cc "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty" 1359763108 5949 3f3fd50a8cc94c3d4cbf4fc66cd3df1c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd" 1359763108 961 6518c6525a34feb5e8250ffa91731cff "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd" 1359763108 961 d02606146ba5601b5645f987c92e6193 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty" 1622667781 2222 da905dc1db75412efd2d8f67739f0596 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty" 1622667781 4173 bc0410bcccdff806d6132d3c1ef35481 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty" 1636758526 87648 07fbb6e9169e00cb2a2f40b31b2dbf3c "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty" 1636758526 4128 8eea906621b6639f7ba476a472036bbe "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty" 1636758526 2444 926f379cc60fcf0c6e3fee2223b4370d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls" 1636758526 20144 8a7de377ae7a11ee924a7499611f5a9d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty" 1622581934 5157 f308c7c04889e16c588e78aa42599fae "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo" 1636758526 8448 96f18c76bf608a36ee6fbf021ac1dd32 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty" 1579991033 13886 d1306dcf79a944f6988e688c1785f9ce "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty" 1612734021 3131 63fa3429cc10864383493f8b120bce11 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty" 1612734021 17086 7ed8cbc4d361ec87392817e0dd4f65ec "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty" 1137110151 6749 16d2656a1984957e674b149555f1ea1d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg" 1459978653 1213 620bba36b25224fa9b7e1ccb4ecb76fd "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg" 1465944070 1224 978390e9c2234eab29404bc21b268d1e "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def" 1601931164 19103 48d29b6e2a64cb717117ef65f107b404 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty" 1622581934 18399 7e40f80366dffb22c0e7b70517db5cb4 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty" 1636758526 7996 a8fb260d598dcaf305a7ae7b9c3e3229 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty" 1622581934 2671 4de6781a30211fe0ea4c672e4a2a8166 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty" 1636758526 4009 187ea2dc3194cd5a76cd99a8d7a6c4d0 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1644269979 29921 d0acc05a38bd4aa3af2017f0b7c137ce "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg" 1279039959 678 4792914a8f45be57bb98413425e4c7af "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty" 1601326656 1090 bae35ef70b3168089ef166db3e66f5b2 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty" 1601326656 410 615550c46f918fcbee37641b02a862d9 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty" 1601326656 21013 f4ff83d25bb56552493b030f27c075ae "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty" 1601326656 989 c49c8ae06d96f8b15869da7428047b1e "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty" 1601326656 339 c2e180022e3afdb99c7d0ea5ce469b7d "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty" 1601326656 306 c56a323ca5bf9242f54474ced10fca71 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty" 1601326656 443 8c872229db56122037e86bcda49e14f3 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty" 1601326656 348 ee405e64380c11319f0e249fed57e6c5 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty" 1601326656 274 5ae372b7df79135d240456a1c6f2cf9a "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty" 1601326656 325 f9f16d12354225b7dd52a3321f085955 "" + "/usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty" 1635798903 56029 3f7889dab51d620aa43177c391b7b190 "" + "/usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf" 1646502317 40171 cdab547de63d26590bebb3baff566530 "" + "/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map" 1647878959 4410336 7d30a02e9fa9a16d7d1f8d037ba69641 "" + "/usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt" 1652326579 2826440 ad4e2d767fc79c480c2262486c0f8a02 "" + "/usr/local/texlive/2022/texmf.cnf" 1647878952 577 209b46be99c9075fd74d4c0369380e8c "" + "1.1.aux" 1652470465 1078 01d5da729077fa36e5c79a1b43234695 "pdflatex" + "1.1.tex" 1652470464 13755 85985586d48ee68809190c4186cf0203 "" + (generated) + "1.1.aux" + "1.1.log" + "1.1.pdf" diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fls b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fls new file mode 100644 index 00000000..90e9d24d --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.fls @@ -0,0 +1,563 @@ +PWD /Users/robbintt/code/outlines/digests/calculus_early_transcendentals_9th_stewart/1_chapter +INPUT /usr/local/texlive/2022/texmf.cnf +INPUT /usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf +INPUT /usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt +INPUT 1.1.tex +OUTPUT 1.1.log +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT ./1.1.aux +INPUT 1.1.aux +INPUT 1.1.aux +OUTPUT 1.1.aux +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr17.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr9.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmmi6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmex10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm +OUTPUT 1.1.pdf +INPUT /usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmr12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx8.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmcsc10.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm +INPUT /usr/local/texlive/2022/texmf-dist/fonts/tfm/public/cm/cmti10.tfm +INPUT 1.1.aux +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmcsc10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmex10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr5.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy7.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb +INPUT /usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti12.pfb diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.log b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.log new file mode 100644 index 00000000..f0d4b38d --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.log @@ -0,0 +1,520 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.5.11) 13 MAY 2022 12:34 +entering extended mode + restricted \write18 enabled. + file:line:error style messages enabled. + %&-line parsing enabled. +**1.1.tex +(./1.1.tex +LaTeX2e <2021-11-15> patch level 1 +L3 programming layer <2022-02-24> (/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls +Document Class: article 2021/10/04 v1.4n Standard LaTeX document class +(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2021/10/04 v1.4n Standard LaTeX file (size option) +) +\c@part=\count185 +\c@section=\count186 +\c@subsection=\count187 +\c@subsubsection=\count188 +\c@paragraph=\count189 +\c@subparagraph=\count190 +\c@figure=\count191 +\c@table=\count192 +\abovecaptionskip=\skip47 +\belowcaptionskip=\skip48 +\bibindent=\dimen138 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +Package: fancyhdr 2021/01/28 v4.0.1 Extensive control of page headers and footers +\f@nch@headwidth=\skip49 +\f@nch@O@elh=\skip50 +\f@nch@O@erh=\skip51 +\f@nch@O@olh=\skip52 +\f@nch@O@orh=\skip53 +\f@nch@O@elf=\skip54 +\f@nch@O@erf=\skip55 +\f@nch@O@olf=\skip56 +\f@nch@O@orf=\skip57 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/fancyhdr/extramarks.sty +Package: extramarks 2021/01/28 v4.0.1 Extra marks for LaTeX +\@temptokenb=\toks16 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsmath.sty +Package: amsmath 2021/10/15 v2.17l AMS math features +\@mathmargin=\skip58 + +For additional information on amsmath, use the `?' option. +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty +Package: amstext 2021/08/26 v2.01 AMS text + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks17 +\ex@=\dimen139 +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen140 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +Package: amsopn 2021/08/26 v2.02 operator names +) +\inf@bad=\count193 +LaTeX Info: Redefining \frac on input line 234. +\uproot@=\count194 +\leftroot@=\count195 +LaTeX Info: Redefining \overline on input line 399. +\classnum@=\count196 +\DOTSCASE@=\count197 +LaTeX Info: Redefining \ldots on input line 496. +LaTeX Info: Redefining \dots on input line 499. +LaTeX Info: Redefining \cdots on input line 620. +\Mathstrutbox@=\box50 +\strutbox@=\box51 +\big@size=\dimen141 +LaTeX Font Info: Redeclaring font encoding OML on input line 743. +LaTeX Font Info: Redeclaring font encoding OMS on input line 744. +\macc@depth=\count198 +\c@MaxMatrixCols=\count199 +\dotsspace@=\muskip16 +\c@parentequation=\count266 +\dspbrk@lvl=\count267 +\tag@help=\toks18 +\row@=\count268 +\column@=\count269 +\maxfields@=\count270 +\andhelp@=\toks19 +\eqnshift@=\dimen142 +\alignsep@=\dimen143 +\tagshift@=\dimen144 +\tagwidth@=\dimen145 +\totwidth@=\dimen146 +\lineht@=\dimen147 +\@envbody=\toks20 +\multlinegap=\skip59 +\multlinetaggap=\skip60 +\mathdisplay@stack=\toks21 +LaTeX Info: Redefining \[ on input line 2938. +LaTeX Info: Redefining \] on input line 2939. +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsthm.sty +Package: amsthm 2020/05/29 v2.20.6 +\thm@style=\toks22 +\thm@bodyfont=\toks23 +\thm@headfont=\toks24 +\thm@notefont=\toks25 +\thm@headpunct=\toks26 +\thm@preskip=\skip61 +\thm@postskip=\skip62 +\thm@headsep=\skip63 +\dth@everypar=\toks27 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +\pgfutil@everybye=\toks28 +\pgfutil@tempdima=\dimen148 +\pgfutil@tempdimb=\dimen149 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def +\pgfutil@abb=\box52 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex) +Package: pgfrcs 2021/05/15 v3.1.9a (3.1.9a) +)) +Package: pgf 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks29 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty +Package: trig 2021/08/11 v1.11 sin cos tan (DPC) +) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 107. + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def +File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex +)) +\Gin@req@height=\dimen150 +\Gin@req@width=\dimen151 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex +Package: pgfsys 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +\pgfkeys@pathtoks=\toks30 +\pgfkeys@temptoks=\toks31 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex +\pgfkeys@tmptoks=\toks32 +)) +\pgf@x=\dimen152 +\pgf@y=\dimen153 +\pgf@xa=\dimen154 +\pgf@ya=\dimen155 +\pgf@xb=\dimen156 +\pgf@yb=\dimen157 +\pgf@xc=\dimen158 +\pgf@yc=\dimen159 +\pgf@xd=\dimen160 +\pgf@yd=\dimen161 +\w@pgf@writea=\write3 +\r@pgf@reada=\read2 +\c@pgf@counta=\count271 +\c@pgf@countb=\count272 +\c@pgf@countc=\count273 +\c@pgf@countd=\count274 +\t@pgf@toka=\toks33 +\t@pgf@tokb=\toks34 +\t@pgf@tokc=\toks35 +\pgf@sys@id@count=\count275 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg +File: pgf.cfg 2021/05/15 v3.1.9a (3.1.9a) +) +Driver file for pgf: pgfsys-pdftex.def + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def +File: pgfsys-pdftex.def 2021/05/15 v3.1.9a (3.1.9a) + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def +File: pgfsys-common-pdf.def 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +File: pgfsyssoftpath.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfsyssoftpath@smallbuffer@items=\count276 +\pgfsyssoftpath@bigbuffer@items=\count277 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +File: pgfsysprotocol.code.tex 2021/05/15 v3.1.9a (3.1.9a) +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty +Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK) + (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg +File: color.cfg 2016/01/02 v1.6 sample color configuration +) +Package xcolor Info: Driver file: pdftex.def on input line 227. +Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1352. +Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1356. +Package xcolor Info: Model `RGB' extended on input line 1368. +Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1370. +Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1371. +Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1372. +Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1373. +Package xcolor Info: Model `Gray' substituted by `gray' on input line 1374. +Package xcolor Info: Model `wave' substituted by `hsb' on input line 1375. +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +Package: pgfcore 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +\pgfmath@dimen=\dimen162 +\pgfmath@count=\count278 +\pgfmath@box=\box53 +\pgfmath@toks=\toks36 +\pgfmath@stack@operand=\toks37 +\pgfmath@stack@operation=\toks38 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +\c@pgfmathroundto@lastzeros=\count279 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex +File: pgfcorepoints.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@picminx=\dimen163 +\pgf@picmaxx=\dimen164 +\pgf@picminy=\dimen165 +\pgf@picmaxy=\dimen166 +\pgf@pathminx=\dimen167 +\pgf@pathmaxx=\dimen168 +\pgf@pathminy=\dimen169 +\pgf@pathmaxy=\dimen170 +\pgf@xx=\dimen171 +\pgf@xy=\dimen172 +\pgf@yx=\dimen173 +\pgf@yy=\dimen174 +\pgf@zx=\dimen175 +\pgf@zy=\dimen176 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex +File: pgfcorepathconstruct.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@path@lastx=\dimen177 +\pgf@path@lasty=\dimen178 +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +File: pgfcorepathusage.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@shorten@end@additional=\dimen179 +\pgf@shorten@start@additional=\dimen180 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +File: pgfcorescopes.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfpic=\box54 +\pgf@hbox=\box55 +\pgf@layerbox@main=\box56 +\pgf@picture@serial@count=\count280 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +File: pgfcoregraphicstate.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgflinewidth=\dimen181 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +File: pgfcoretransformations.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@pt@x=\dimen182 +\pgf@pt@y=\dimen183 +\pgf@pt@temp=\dimen184 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex +File: pgfcorequick.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex +File: pgfcoreobjects.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex +File: pgfcorepathprocessing.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +File: pgfcorearrows.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfarrowsep=\dimen185 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex +File: pgfcoreshade.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@max=\dimen186 +\pgf@sys@shading@range@num=\count281 +\pgf@shadingcount=\count282 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex +File: pgfcoreimage.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex +File: pgfcoreexternal.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfexternal@startupbox=\box57 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex +File: pgfcorelayers.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex +File: pgfcoretransparency.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex +File: pgfcorepatterns.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex +File: pgfcorerdf.code.tex 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +File: pgfmoduleshapes.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfnodeparttextbox=\box58 +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +File: pgfmoduleplot.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +Package: pgfcomp-version-0-65 2021/05/15 v3.1.9a (3.1.9a) +\pgf@nodesepstart=\dimen187 +\pgf@nodesepend=\dimen188 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +Package: pgfcomp-version-1-18 2021/05/15 v3.1.9a (3.1.9a) +)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +Package: pgffor 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex) +\pgffor@iter=\dimen189 +\pgffor@skip=\dimen190 +\pgffor@stack=\toks39 +\pgffor@toks=\toks40 +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +Package: tikz 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex +File: pgflibraryplothandlers.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgf@plot@mark@count=\count283 +\pgfplotmarksize=\dimen191 +) +\tikz@lastx=\dimen192 +\tikz@lasty=\dimen193 +\tikz@lastxsaved=\dimen194 +\tikz@lastysaved=\dimen195 +\tikz@lastmovetox=\dimen196 +\tikz@lastmovetoy=\dimen197 +\tikzleveldistance=\dimen198 +\tikzsiblingdistance=\dimen199 +\tikz@figbox=\box59 +\tikz@figbox@bg=\box60 +\tikz@tempbox=\box61 +\tikz@tempbox@bg=\box62 +\tikztreelevel=\count284 +\tikznumberofchildren=\count285 +\tikznumberofcurrentchild=\count286 +\tikz@fig@count=\count287 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex +File: pgfmodulematrix.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfmatrixcurrentrow=\count288 +\pgfmatrixcurrentcolumn=\count289 +\pgf@matrix@numberofcolumns=\count290 +) +\tikz@expandcount=\count291 + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex +File: tikzlibrarytopaths.code.tex 2021/05/15 v3.1.9a (3.1.9a) +))) (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithms/algorithm.sty +Package: algorithm 2009/08/24 v0.1 Document Style `algorithm' - floating environment + (/usr/local/texlive/2022/texmf-dist/tex/latex/float/float.sty +Package: float 2001/11/08 v1.3d Float enhancements (AL) +\c@float@type=\count292 +\float@exts=\toks41 +\float@box=\box63 +\@float@everytoks=\toks42 +\@floatcapt=\box64 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/base/ifthen.sty +Package: ifthen 2020/11/24 v1.1c Standard LaTeX ifthen package (DPC) +) +\@float@every@algorithm=\toks43 +\c@algorithm=\count293 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algpseudocode.sty +Package: algpseudocode + (/usr/local/texlive/2022/texmf-dist/tex/latex/algorithmicx/algorithmicx.sty +Package: algorithmicx 2005/04/27 v1.2 Algorithmicx + +Document Style algorithmicx 1.2 - a greatly improved `algorithmic' style +\c@ALG@line=\count294 +\c@ALG@rem=\count295 +\c@ALG@nested=\count296 +\ALG@tlm=\skip64 +\ALG@thistlm=\skip65 +\c@ALG@Lnr=\count297 +\c@ALG@blocknr=\count298 +\c@ALG@storecount=\count299 +\c@ALG@tmpcounter=\count300 +\ALG@tmplength=\skip66 +) +Document Style - pseudocode environments for use with the `algorithmicx' style +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryautomata.code.tex +File: tikzlibraryautomata.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibraryshapes.multipart.code.tex +File: tikzlibraryshapes.multipart.code.tex 2021/05/15 v3.1.9a (3.1.9a) + (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/shapes/pgflibraryshapes.multipart.code.tex +File: pgflibraryshapes.multipart.code.tex 2021/05/15 v3.1.9a (3.1.9a) +\pgfnodepartlowerbox=\box65 +\pgfnodeparttwobox=\box66 +\pgfnodepartthreebox=\box67 +\pgfnodepartfourbox=\box68 +\pgfnodeparttwentybox=\box69 +\pgfnodepartnineteenbox=\box70 +\pgfnodeparteighteenbox=\box71 +\pgfnodepartseventeenbox=\box72 +\pgfnodepartsixteenbox=\box73 +\pgfnodepartfifteenbox=\box74 +\pgfnodepartfourteenbox=\box75 +\pgfnodepartthirteenbox=\box76 +\pgfnodeparttwelvebox=\box77 +\pgfnodepartelevenbox=\box78 +\pgfnodeparttenbox=\box79 +\pgfnodepartninebox=\box80 +\pgfnodeparteightbox=\box81 +\pgfnodepartsevenbox=\box82 +\pgfnodepartsixbox=\box83 +\pgfnodepartfivebox=\box84 +))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarypositioning.code.tex +File: tikzlibrarypositioning.code.tex 2021/05/15 v3.1.9a (3.1.9a) +) +\c@partCounter=\count301 +\c@homeworkProblemCounter=\count302 + (/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count303 +\l__pdf_internal_box=\box85 +) (./1.1.aux) +\openout1 = `1.1.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 138. +LaTeX Font Info: ... okay on input line 138. + (/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count304 +\scratchdimen=\dimen256 +\scratchbox=\box86 +\nofMPsegments=\count305 +\nofMParguments=\count306 +\everyMPshowfont=\toks44 +\MPscratchCnt=\count307 +\MPscratchDim=\dimen257 +\MPnumerator=\count308 +\makeMPintoPDFobject=\count309 +\everyMPtoPDFconversion=\toks45 +) (/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 485. + (/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live +)) +LaTeX Font Info: Trying to load font information for U+msa on input line 140. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Trying to load font information for U+msb on input line 140. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) [1 + +{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] +Underfull \hbox (badness 10000) in paragraph at lines 161--164 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 179--181 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 200--202 + + [] + +[3] +Underfull \hbox (badness 10000) in paragraph at lines 222--225 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 259--261 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 262--268 + + [] + + +LaTeX Font Warning: Font shape `OT1/cmr/bx/sc' undefined +(Font) using `OT1/cmr/bx/n' instead on input line 293. + + +LaTeX Warning: No positions in optional float specifier. + Default added (so using `htbp') on input line 295. + +[4] +Underfull \hbox (badness 10000) in paragraph at lines 313--318 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 320--324 + + [] + +[5] +Underfull \hbox (badness 10000) in paragraph at lines 375--379 + + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 422--425 + + [] + +[6] +Underfull \hbox (badness 10000) in paragraph at lines 492--498 + + [] + +[7] [8] (./1.1.aux) + +LaTeX Font Warning: Some font shapes were not available, defaults substituted. + + ) +Here is how much of TeX's memory you used: + 14363 strings out of 478268 + 299835 string characters out of 5846347 + 581637 words of memory out of 5000000 + 32314 multiletter control sequences out of 15000+600000 + 479633 words of font info for 67 fonts, out of 8000000 for 9000 + 1141 hyphenation exceptions out of 8191 + 100i,17n,104p,413b,981s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on 1.1.pdf (8 pages, 210618 bytes). +PDF statistics: + 124 PDF objects out of 1000 (max. 8388607) + 77 compressed objects within 1 object stream + 0 named destinations out of 1000 (max. 500000) + 13 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.pdf b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.pdf new file mode 100644 index 00000000..2adf08df Binary files /dev/null and b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.pdf differ diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.synctex.gz b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.synctex.gz new file mode 100644 index 00000000..bcbf92dc Binary files /dev/null and b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.synctex.gz differ diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.tex b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.tex new file mode 100644 index 00000000..d9f94988 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/1.1.tex @@ -0,0 +1,544 @@ +\documentclass{article} + +\usepackage{fancyhdr} +\usepackage{extramarks} +\usepackage{amsmath} +\usepackage{amsthm} +\usepackage{amsfonts} +\usepackage{tikz} +\usepackage[plain]{algorithm} +\usepackage{algpseudocode} + +\usetikzlibrary{automata,positioning} + +% +% Basic Document Settings +% + +\topmargin=-0.45in +\evensidemargin=0in +\oddsidemargin=0in +\textwidth=6.5in +\textheight=9.0in +\headsep=0.25in + +\linespread{1.1} + +\pagestyle{fancy} +\lhead{\hmwkAuthorName} +\chead{\ \hmwkBook\ (\hmwkBookInstructor): \hmwkTitle} +\rhead{\firstxmark} +\lfoot{\lastxmark} +\cfoot{\thepage} + +\renewcommand\headrulewidth{0.4pt} +\renewcommand\footrulewidth{0.4pt} + +\setlength\parindent{0pt} + +% +% Create Problem Sections +% + +\newcommand{\enterProblemHeader}[1]{ + \nobreak\extramarks{}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} +} + +\newcommand{\exitProblemHeader}[1]{ + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \stepcounter{#1} + \nobreak\extramarks{Problem \arabic{#1}}{}\nobreak{} +} + +\setcounter{secnumdepth}{0} +\newcounter{partCounter} +\newcounter{homeworkProblemCounter} +\setcounter{homeworkProblemCounter}{1} +\nobreak\extramarks{Problem \arabic{homeworkProblemCounter}}{}\nobreak{} + +% +% Homework Problem Environment +% +% This environment takes an optional argument. When given, it will adjust the +% problem counter. This is useful for when the problems given for your +% assignment aren't sequential. See the last 3 problems of this template for an +% example. +% +\newenvironment{homeworkProblem}[1][-1]{ + \ifnum#1>0 + \setcounter{homeworkProblemCounter}{#1} + \fi + \section{Problem \arabic{homeworkProblemCounter}} + \setcounter{partCounter}{1} + \enterProblemHeader{homeworkProblemCounter} +}{ + \exitProblemHeader{homeworkProblemCounter} +} + +% +% Homework Details +% - Title +% - Completed date +% - Book +% - Section/Time +% - Instructor +% - Author +% + +\newcommand{\hmwkTitle}{Section 1.1} +\newcommand{\hmwkCompletedDate}{February 12, 2014} +\newcommand{\hmwkBook}{Calculus: Early Transcendentals, 9th Edition} +\newcommand{\hmwkBookInstructor}{Stewart} +\newcommand{\hmwkAuthorName}{Trent Robbins} + +% +% Title Page +% + +\title{ + \vspace{2in} + \textmd{\textbf{\hmwkBook}}\\ + \textmd{\textbf{\hmwkTitle}}\\ + \normalsize\vspace{0.1in}\small{Completed\ on\ \hmwkCompletedDate}\\ + \vspace{0.1in}\large{\textit{\hmwkBookInstructor}} + \vspace{3in} +} + +\author{\hmwkAuthorName} +\date{} + +\renewcommand{\part}[1]{\textbf{\large Part \Alph{partCounter}}\stepcounter{partCounter}\\} + +% +% Various Helper Commands +% + +% Useful for algorithms +\newcommand{\alg}[1]{\textsc{\bfseries \footnotesize #1}} + +% For derivatives +\newcommand{\deriv}[1]{\frac{\mathrm{d}}{\mathrm{d}x} (#1)} + +% For partial derivatives +\newcommand{\pderiv}[2]{\frac{\partial}{\partial #1} (#2)} + +% Integral dx +\newcommand{\dx}{\mathrm{d}x} + +% Alias for the Solution section header +\newcommand{\solution}{\textbf{\large Solution}} + +% Probability commands: Expectation, Variance, Covariance, Bias +\newcommand{\E}{\mathrm{E}} +\newcommand{\Var}{\mathrm{Var}} +\newcommand{\Cov}{\mathrm{Cov}} +\newcommand{\Bias}{\mathrm{Bias}} + +\begin{document} + +\maketitle + +\pagebreak + +\begin{homeworkProblem} +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Give an appropriate positive constant \(c\) such that \(f(n) \leq c \cdot + g(n)\) for all \(n > 1\). + + \begin{enumerate} + \item \(f(n) = n^2 + n + 1\), \(g(n) = 2n^3\) + \item \(f(n) = n\sqrt{n} + n^2\), \(g(n) = n^2\) + \item \(f(n) = n^2 - n + 1\), \(g(n) = n^2 / 2\) + \end{enumerate} + + \textbf{Solution} + + We solve each solution algebraically to determine a possible constant + \(c\). + \\ + + \textbf{Part One} + + \[ + \begin{split} + n^2 + n + 1 &= + \\ + &\leq n^2 + n^2 + n^2 + \\ + &= 3n^2 + \\ + &\leq c \cdot 2n^3 + \end{split} + \] + + Thus a valid \(c\) could be when \(c = 2\). + \\ + + \textbf{Part Two} + + \[ + \begin{split} + n^2 + n\sqrt{n} &= + \\ + &= n^2 + n^{3/2} + \\ + &\leq n^2 + n^{4/2} + \\ + &= n^2 + n^2 + \\ + &= 2n^2 + \\ + &\leq c \cdot n^2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + \\ + + \textbf{Part Three} + + \[ + \begin{split} + n^2 - n + 1 &= + \\ + &\leq n^2 + \\ + &\leq c \cdot n^2/2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Let \(\Sigma = \{0, 1\}\). Construct a DFA \(A\) that recognizes the + language that consists of all binary numbers that can be divided by 5. + \\ + + Let the state \(q_k\) indicate the remainder of \(k\) divided by 5. For + example, the remainder of 2 would correlate to state \(q_2\) because \(7 + \mod 5 = 2\). + + \begin{figure}[h] + \centering + \begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto] + \node[state, accepting, initial] (q_0) {$q_0$}; + \node[state] (q_1) [right=of q_0] {$q_1$}; + \node[state] (q_2) [right=of q_1] {$q_2$}; + \node[state] (q_3) [right=of q_2] {$q_3$}; + \node[state] (q_4) [right=of q_3] {$q_4$}; + \path[->] + (q_0) + edge [loop above] node {0} (q_0) + edge node {1} (q_1) + (q_1) + edge node {0} (q_2) + edge [bend right=-30] node {1} (q_3) + (q_2) + edge [bend left] node {1} (q_0) + edge [bend right=-30] node {0} (q_4) + (q_3) + edge node {1} (q_2) + edge [bend left] node {0} (q_1) + (q_4) + edge node {0} (q_3) + edge [loop below] node {1} (q_4); + \end{tikzpicture} + \caption{DFA, \(A\), this is really beautiful, ya know?} + \label{fig:multiple5} + \end{figure} + + \textbf{Justification} + \\ + + Take a given binary number, \(x\). Since there are only two inputs to our + state machine, \(x\) can either become \(x0\) or \(x1\). When a 0 comes + into the state machine, it is the same as taking the binary number and + multiplying it by two. When a 1 comes into the machine, it is the same as + multipying by two and adding one. + \\ + + Using this knowledge, we can construct a transition table that tell us + where to go: + + \begin{table}[ht] + \centering + \begin{tabular}{c || c | c | c | c | c} + & \(x \mod 5 = 0\) + & \(x \mod 5 = 1\) + & \(x \mod 5 = 2\) + & \(x \mod 5 = 3\) + & \(x \mod 5 = 4\) + \\ + \hline + \(x0\) & 0 & 2 & 4 & 1 & 3 \\ + \(x1\) & 1 & 3 & 0 & 2 & 4 \\ + \end{tabular} + \end{table} + + Therefore on state \(q_0\) or (\(x \mod 5 = 0\)), a transition line should + go to state \(q_0\) for the input 0 and a line should go to state \(q_1\) + for input 1. Continuing this gives us the Figure~\ref{fig:multiple5}. +\end{homeworkProblem} + +\begin{homeworkProblem} + Write part of \alg{Quick-Sort($list, start, end$)} + + \begin{algorithm}[] + \begin{algorithmic}[1] + \Function{Quick-Sort}{$list, start, end$} + \If{$start \geq end$} + \State{} \Return{} + \EndIf{} + \State{} $mid \gets \Call{Partition}{list, start, end}$ + \State{} \Call{Quick-Sort}{$list, start, mid - 1$} + \State{} \Call{Quick-Sort}{$list, mid + 1, end$} + \EndFunction{} + \end{algorithmic} + \caption{Start of QuickSort} + \end{algorithm} +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Suppose we would like to fit a straight line through the origin, i.e., + \(Y_i = \beta_1 x_i + e_i\) with \(i = 1, \ldots, n\), \(\E [e_i] = 0\), + and \(\Var [e_i] = \sigma^2_e\) and \(\Cov[e_i, e_j] = 0, \forall i \neq + j\). + \\ + + \part + + Find the least squares esimator for \(\hat{\beta_1}\) for the slope + \(\beta_1\). + \\ + + \solution + + To find the least squares estimator, we should minimize our Residual Sum + of Squares, RSS: + + \[ + \begin{split} + RSS &= \sum_{i = 1}^{n} {(Y_i - \hat{Y_i})}^2 + \\ + &= \sum_{i = 1}^{n} {(Y_i - \hat{\beta_1} x_i)}^2 + \end{split} + \] + + By taking the partial derivative in respect to \(\hat{\beta_1}\), we get: + + \[ + \pderiv{ + \hat{\beta_1} + }{RSS} + = -2 \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + = 0 + \] + + This gives us: + + \[ + \begin{split} + \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + &= \sum_{i = 1}^{n} {x_i Y_i} - \sum_{i = 1}^{n} \hat{\beta_1} x_i^2 + \\ + &= \sum_{i = 1}^{n} {x_i Y_i} - \hat{\beta_1}\sum_{i = 1}^{n} x_i^2 + \end{split} + \] + + Solving for \(\hat{\beta_1}\) gives the final estimator for \(\beta_1\): + + \[ + \begin{split} + \hat{\beta_1} + &= \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + } + \end{split} + \] + + \pagebreak + + \part + + Calculate the bias and the variance for the estimated slope + \(\hat{\beta_1}\). + \\ + + \solution + + For the bias, we need to calculate the expected value + \(\E[\hat{\beta_1}]\): + + \[ + \begin{split} + \E[\hat{\beta_1}] + &= \E \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= \frac{ + \sum {x_i \E[Y_i]} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i (\beta_1 x_i)} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 + \end{split} + \] + + Thus since our estimator's expected value is \(\beta_1\), we can conclude + that the bias of our estimator is 0. + \\ + + For the variance: + + \[ + \begin{split} + \Var[\hat{\beta_1}] + &= \Var \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \sigma^2 + \\ + &= + \frac{ + \sigma^2 + }{ + \sum x_i^2 + } + \end{split} + \] + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Prove a polynomial of degree \(k\), \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + + a_1n^1 + a_0n^0\) is a member of \(\Theta(n^k)\) where \(a_k \hdots a_0\) + are nonnegative constants. + + \begin{proof} + To prove that \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + + a_0n^0\), we must show the following: + + \[ + \exists c_1 \exists c_2 \forall n \geq n_0,\ {c_1 \cdot g(n) \leq + f(n) \leq c_2 \cdot g(n)} + \] + + For the first inequality, it is easy to see that it holds because no + matter what the constants are, \(n^k \leq a_kn^k + a_{k - 1}n^{k - 1} + + \hdots + a_1n^1 + a_0n^0\) even if \(c_1 = 1\) and \(n_0 = 1\). This + is because \(n^k \leq c_1 \cdot a_kn^k\) for any nonnegative constant, + \(c_1\) and \(a_k\). + \\ + + Taking the second inequality, we prove it in the following way. + By summation, \(\sum\limits_{i=0}^k a_i\) will give us a new constant, + \(A\). By taking this value of \(A\), we can then do the following: + + \[ + \begin{split} + a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + a_0n^0 &= + \\ + &\leq (a_k + a_{k - 1} \hdots a_1 + a_0) \cdot n^k + \\ + &= A \cdot n^k + \\ + &\leq c_2 \cdot n^k + \end{split} + \] + + where \(n_0 = 1\) and \(c_2 = A\). \(c_2\) is just a constant. Thus the + proof is complete. + \end{proof} +\end{homeworkProblem} + +\pagebreak + +% +% Non sequential homework problems +% + +% Jump to problem 18 +\begin{homeworkProblem}[18] + Evaluate \(\sum_{k=1}^{5} k^2\) and \(\sum_{k=1}^{5} (k - 1)^2\). +\end{homeworkProblem} + +% Continue counting to 19 +\begin{homeworkProblem} + Find the derivative of \(f(x) = x^4 + 3x^2 - 2\) +\end{homeworkProblem} + +% Go back to where we left off +\begin{homeworkProblem}[6] + Evaluate the integrals + \(\int_0^1 (1 - x^2) \dx\) + and + \(\int_1^{\infty} \frac{1}{x^2} \dx\). +\end{homeworkProblem} + +\end{document} diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/pdflatex14095.fls b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/pdflatex14095.fls new file mode 100644 index 00000000..b41f23c9 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/1_chapter/pdflatex14095.fls @@ -0,0 +1,3 @@ +PWD /Users/robbintt/code/outlines/digests/calculus_early_transcendentals_9th_stewart/1_chapter +INPUT /usr/local/texlive/2022/texmf.cnf +INPUT /usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/homework_template.tex b/docs/digests/calculus_early_transcendentals_9th_stewart/homework_template.tex new file mode 100644 index 00000000..872e6f5f --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/homework_template.tex @@ -0,0 +1,539 @@ +\documentclass{article} + +\usepackage{fancyhdr} +\usepackage{extramarks} +\usepackage{amsmath} +\usepackage{amsthm} +\usepackage{amsfonts} +\usepackage{tikz} +\usepackage[plain]{algorithm} +\usepackage{algpseudocode} + +\usetikzlibrary{automata,positioning} + +% +% Basic Document Settings +% + +\topmargin=-0.45in +\evensidemargin=0in +\oddsidemargin=0in +\textwidth=6.5in +\textheight=9.0in +\headsep=0.25in + +\linespread{1.1} + +\pagestyle{fancy} +\lhead{\hmwkAuthorName} +\chead{\hmwkClass\ (\hmwkClassInstructor\ \hmwkClassTime): \hmwkTitle} +\rhead{\firstxmark} +\lfoot{\lastxmark} +\cfoot{\thepage} + +\renewcommand\headrulewidth{0.4pt} +\renewcommand\footrulewidth{0.4pt} + +\setlength\parindent{0pt} + +% +% Create Problem Sections +% + +\newcommand{\enterProblemHeader}[1]{ + \nobreak\extramarks{}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} +} + +\newcommand{\exitProblemHeader}[1]{ + \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{} + \stepcounter{#1} + \nobreak\extramarks{Problem \arabic{#1}}{}\nobreak{} +} + +\setcounter{secnumdepth}{0} +\newcounter{partCounter} +\newcounter{homeworkProblemCounter} +\setcounter{homeworkProblemCounter}{1} +\nobreak\extramarks{Problem \arabic{homeworkProblemCounter}}{}\nobreak{} + +% +% Homework Problem Environment +% +% This environment takes an optional argument. When given, it will adjust the +% problem counter. This is useful for when the problems given for your +% assignment aren't sequential. See the last 3 problems of this template for an +% example. +% +\newenvironment{homeworkProblem}[1][-1]{ + \ifnum#1>0 + \setcounter{homeworkProblemCounter}{#1} + \fi + \section{Problem \arabic{homeworkProblemCounter}} + \setcounter{partCounter}{1} + \enterProblemHeader{homeworkProblemCounter} +}{ + \exitProblemHeader{homeworkProblemCounter} +} + +% +% Homework Details +% - Title +% - Due date +% - Class +% - Section/Time +% - Instructor +% - Author +% + +\newcommand{\hmwkTitle}{Homework\ \#2} +\newcommand{\hmwkDueDate}{February 12, 2014} +\newcommand{\hmwkClass}{Calculus} +\newcommand{\hmwkClassTime}{Section A} +\newcommand{\hmwkClassInstructor}{Professor Isaac Newton} +\newcommand{\hmwkAuthorName}{\textbf{Josh Davis} \and \textbf{Davis Josh}} + +% +% Title Page +% + +\title{ + \vspace{2in} + \textmd{\textbf{\hmwkClass:\ \hmwkTitle}}\\ + \normalsize\vspace{0.1in}\small{Due\ on\ \hmwkDueDate\ at 3:10pm}\\ + \vspace{0.1in}\large{\textit{\hmwkClassInstructor\ \hmwkClassTime}} + \vspace{3in} +} + +\author{\hmwkAuthorName} +\date{} + +\renewcommand{\part}[1]{\textbf{\large Part \Alph{partCounter}}\stepcounter{partCounter}\\} + +% +% Various Helper Commands +% + +% Useful for algorithms +\newcommand{\alg}[1]{\textsc{\bfseries \footnotesize #1}} + +% For derivatives +\newcommand{\deriv}[1]{\frac{\mathrm{d}}{\mathrm{d}x} (#1)} + +% For partial derivatives +\newcommand{\pderiv}[2]{\frac{\partial}{\partial #1} (#2)} + +% Integral dx +\newcommand{\dx}{\mathrm{d}x} + +% Alias for the Solution section header +\newcommand{\solution}{\textbf{\large Solution}} + +% Probability commands: Expectation, Variance, Covariance, Bias +\newcommand{\E}{\mathrm{E}} +\newcommand{\Var}{\mathrm{Var}} +\newcommand{\Cov}{\mathrm{Cov}} +\newcommand{\Bias}{\mathrm{Bias}} + +\begin{document} + +\maketitle + +\pagebreak + +\begin{homeworkProblem} + Give an appropriate positive constant \(c\) such that \(f(n) \leq c \cdot + g(n)\) for all \(n > 1\). + + \begin{enumerate} + \item \(f(n) = n^2 + n + 1\), \(g(n) = 2n^3\) + \item \(f(n) = n\sqrt{n} + n^2\), \(g(n) = n^2\) + \item \(f(n) = n^2 - n + 1\), \(g(n) = n^2 / 2\) + \end{enumerate} + + \textbf{Solution} + + We solve each solution algebraically to determine a possible constant + \(c\). + \\ + + \textbf{Part One} + + \[ + \begin{split} + n^2 + n + 1 &= + \\ + &\leq n^2 + n^2 + n^2 + \\ + &= 3n^2 + \\ + &\leq c \cdot 2n^3 + \end{split} + \] + + Thus a valid \(c\) could be when \(c = 2\). + \\ + + \textbf{Part Two} + + \[ + \begin{split} + n^2 + n\sqrt{n} &= + \\ + &= n^2 + n^{3/2} + \\ + &\leq n^2 + n^{4/2} + \\ + &= n^2 + n^2 + \\ + &= 2n^2 + \\ + &\leq c \cdot n^2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + \\ + + \textbf{Part Three} + + \[ + \begin{split} + n^2 - n + 1 &= + \\ + &\leq n^2 + \\ + &\leq c \cdot n^2/2 + \end{split} + \] + + Thus a valid \(c\) is \(c = 2\). + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Let \(\Sigma = \{0, 1\}\). Construct a DFA \(A\) that recognizes the + language that consists of all binary numbers that can be divided by 5. + \\ + + Let the state \(q_k\) indicate the remainder of \(k\) divided by 5. For + example, the remainder of 2 would correlate to state \(q_2\) because \(7 + \mod 5 = 2\). + + \begin{figure}[h] + \centering + \begin{tikzpicture}[shorten >=1pt,node distance=2cm,on grid,auto] + \node[state, accepting, initial] (q_0) {$q_0$}; + \node[state] (q_1) [right=of q_0] {$q_1$}; + \node[state] (q_2) [right=of q_1] {$q_2$}; + \node[state] (q_3) [right=of q_2] {$q_3$}; + \node[state] (q_4) [right=of q_3] {$q_4$}; + \path[->] + (q_0) + edge [loop above] node {0} (q_0) + edge node {1} (q_1) + (q_1) + edge node {0} (q_2) + edge [bend right=-30] node {1} (q_3) + (q_2) + edge [bend left] node {1} (q_0) + edge [bend right=-30] node {0} (q_4) + (q_3) + edge node {1} (q_2) + edge [bend left] node {0} (q_1) + (q_4) + edge node {0} (q_3) + edge [loop below] node {1} (q_4); + \end{tikzpicture} + \caption{DFA, \(A\), this is really beautiful, ya know?} + \label{fig:multiple5} + \end{figure} + + \textbf{Justification} + \\ + + Take a given binary number, \(x\). Since there are only two inputs to our + state machine, \(x\) can either become \(x0\) or \(x1\). When a 0 comes + into the state machine, it is the same as taking the binary number and + multiplying it by two. When a 1 comes into the machine, it is the same as + multipying by two and adding one. + \\ + + Using this knowledge, we can construct a transition table that tell us + where to go: + + \begin{table}[ht] + \centering + \begin{tabular}{c || c | c | c | c | c} + & \(x \mod 5 = 0\) + & \(x \mod 5 = 1\) + & \(x \mod 5 = 2\) + & \(x \mod 5 = 3\) + & \(x \mod 5 = 4\) + \\ + \hline + \(x0\) & 0 & 2 & 4 & 1 & 3 \\ + \(x1\) & 1 & 3 & 0 & 2 & 4 \\ + \end{tabular} + \end{table} + + Therefore on state \(q_0\) or (\(x \mod 5 = 0\)), a transition line should + go to state \(q_0\) for the input 0 and a line should go to state \(q_1\) + for input 1. Continuing this gives us the Figure~\ref{fig:multiple5}. +\end{homeworkProblem} + +\begin{homeworkProblem} + Write part of \alg{Quick-Sort($list, start, end$)} + + \begin{algorithm}[] + \begin{algorithmic}[1] + \Function{Quick-Sort}{$list, start, end$} + \If{$start \geq end$} + \State{} \Return{} + \EndIf{} + \State{} $mid \gets \Call{Partition}{list, start, end}$ + \State{} \Call{Quick-Sort}{$list, start, mid - 1$} + \State{} \Call{Quick-Sort}{$list, mid + 1, end$} + \EndFunction{} + \end{algorithmic} + \caption{Start of QuickSort} + \end{algorithm} +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Suppose we would like to fit a straight line through the origin, i.e., + \(Y_i = \beta_1 x_i + e_i\) with \(i = 1, \ldots, n\), \(\E [e_i] = 0\), + and \(\Var [e_i] = \sigma^2_e\) and \(\Cov[e_i, e_j] = 0, \forall i \neq + j\). + \\ + + \part + + Find the least squares esimator for \(\hat{\beta_1}\) for the slope + \(\beta_1\). + \\ + + \solution + + To find the least squares estimator, we should minimize our Residual Sum + of Squares, RSS: + + \[ + \begin{split} + RSS &= \sum_{i = 1}^{n} {(Y_i - \hat{Y_i})}^2 + \\ + &= \sum_{i = 1}^{n} {(Y_i - \hat{\beta_1} x_i)}^2 + \end{split} + \] + + By taking the partial derivative in respect to \(\hat{\beta_1}\), we get: + + \[ + \pderiv{ + \hat{\beta_1} + }{RSS} + = -2 \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + = 0 + \] + + This gives us: + + \[ + \begin{split} + \sum_{i = 1}^{n} {x_i (Y_i - \hat{\beta_1} x_i)} + &= \sum_{i = 1}^{n} {x_i Y_i} - \sum_{i = 1}^{n} \hat{\beta_1} x_i^2 + \\ + &= \sum_{i = 1}^{n} {x_i Y_i} - \hat{\beta_1}\sum_{i = 1}^{n} x_i^2 + \end{split} + \] + + Solving for \(\hat{\beta_1}\) gives the final estimator for \(\beta_1\): + + \[ + \begin{split} + \hat{\beta_1} + &= \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + } + \end{split} + \] + + \pagebreak + + \part + + Calculate the bias and the variance for the estimated slope + \(\hat{\beta_1}\). + \\ + + \solution + + For the bias, we need to calculate the expected value + \(\E[\hat{\beta_1}]\): + + \[ + \begin{split} + \E[\hat{\beta_1}] + &= \E \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= \frac{ + \sum {x_i \E[Y_i]} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i (\beta_1 x_i)} + }{ + \sum x_i^2 + } + \\ + &= \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 \frac{ + \sum {x_i^2 \beta_1} + }{ + \sum x_i^2 + } + \\ + &= \beta_1 + \end{split} + \] + + Thus since our estimator's expected value is \(\beta_1\), we can conclude + that the bias of our estimator is 0. + \\ + + For the variance: + + \[ + \begin{split} + \Var[\hat{\beta_1}] + &= \Var \left[ \frac{ + \sum {x_i Y_i} + }{ + \sum x_i^2 + }\right] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + \sum {x_i^2} + }{ + \sum x_i^2 \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \Var[Y_i] + \\ + &= + \frac{ + 1 + }{ + \sum x_i^2 + } \sigma^2 + \\ + &= + \frac{ + \sigma^2 + }{ + \sum x_i^2 + } + \end{split} + \] + +\end{homeworkProblem} + +\pagebreak + +\begin{homeworkProblem} + Prove a polynomial of degree \(k\), \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + + a_1n^1 + a_0n^0\) is a member of \(\Theta(n^k)\) where \(a_k \hdots a_0\) + are nonnegative constants. + + \begin{proof} + To prove that \(a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + + a_0n^0\), we must show the following: + + \[ + \exists c_1 \exists c_2 \forall n \geq n_0,\ {c_1 \cdot g(n) \leq + f(n) \leq c_2 \cdot g(n)} + \] + + For the first inequality, it is easy to see that it holds because no + matter what the constants are, \(n^k \leq a_kn^k + a_{k - 1}n^{k - 1} + + \hdots + a_1n^1 + a_0n^0\) even if \(c_1 = 1\) and \(n_0 = 1\). This + is because \(n^k \leq c_1 \cdot a_kn^k\) for any nonnegative constant, + \(c_1\) and \(a_k\). + \\ + + Taking the second inequality, we prove it in the following way. + By summation, \(\sum\limits_{i=0}^k a_i\) will give us a new constant, + \(A\). By taking this value of \(A\), we can then do the following: + + \[ + \begin{split} + a_kn^k + a_{k - 1}n^{k - 1} + \hdots + a_1n^1 + a_0n^0 &= + \\ + &\leq (a_k + a_{k - 1} \hdots a_1 + a_0) \cdot n^k + \\ + &= A \cdot n^k + \\ + &\leq c_2 \cdot n^k + \end{split} + \] + + where \(n_0 = 1\) and \(c_2 = A\). \(c_2\) is just a constant. Thus the + proof is complete. + \end{proof} +\end{homeworkProblem} + +\pagebreak + +% +% Non sequential homework problems +% + +% Jump to problem 18 +\begin{homeworkProblem}[18] + Evaluate \(\sum_{k=1}^{5} k^2\) and \(\sum_{k=1}^{5} (k - 1)^2\). +\end{homeworkProblem} + +% Continue counting to 19 +\begin{homeworkProblem} + Find the derivative of \(f(x) = x^4 + 3x^2 - 2\) +\end{homeworkProblem} + +% Go back to where we left off +\begin{homeworkProblem}[6] + Evaluate the integrals + \(\int_0^1 (1 - x^2) \dx\) + and + \(\int_1^{\infty} \frac{1}{x^2} \dx\). +\end{homeworkProblem} + +\end{document} diff --git a/docs/digests/calculus_early_transcendentals_9th_stewart/index.html b/docs/digests/calculus_early_transcendentals_9th_stewart/index.html new file mode 100644 index 00000000..98b09b68 --- /dev/null +++ b/docs/digests/calculus_early_transcendentals_9th_stewart/index.html @@ -0,0 +1,3205 @@ + + + + + + + + + + + + + + + + Readme - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Notes on Calculus - Early Transcendentals 9th Ed. by Stewart

    +

    The 8th edition is the first book recommended by https://www.susanrigetti.com/math. However, there is a 9th edition so I got that.

    +

    How to Study by Susan Rigetti:

    +

    I learn the same way as Susan and hope to use LaTeX a lot, but may use a blend based on learning facility with or without tech in the loop.

    +
    +

    Every person learns in their own special way, and knowing your learning style is important: do you learn by reading, by taking notes, by talking, by watching, by doing, or by a combination of some or all of these? For example, I learn by reading and by note-taking, so I read through textbooks very carefully, take copious notes, and summarize each concept in my own words before moving on to something new. Think about this before you begin so that you'll know how to structure your studies.

    +

    Regardless of your learning style, you'll still need to solve the problems in each textbook. Just like in physics, solving problems is the only way to understand mathematics. There's no way around it.

    +

    One tough thing about learning on your own is that you may not know whether you are solving the problems correctly. A number of the textbooks listed below have answers to selected exercises in the back of the book, but these aren’t always adequate for two reasons: (1) they often only show the solutions to the problems, and not the steps taken to get there; and (2) it’s much better to do all of the exercises rather than just a select few. The good news is that many of the solutions (and step-by-step ways to solve them) can be found online with a simple google search. If you are going to google the answers, however, please first try to solve the problems on your own, and try multiple times (you’re not in school trying to get a perfect grade — you’re trying to learn and understand).

    +
    +

    Notes & Assignments with LaTeX

    +

    It is strongly recommended that I take notes using LaTeX.

    +

    Supposedly I can learn enough LaTeX in an afternoon using the LaTeX/Basics wikibook

    +

    I hope github displays latex visually, I will have to test it.

    +

    Vim+LaTeX == lervag/vimtex

    + +

    LaTeX Resources

    +

    I'm planning to work with vim-tex, but am interested in trying gui editors potentially. The integrated skim viewer is a lot like my old macdown workflow so I am excited about it.

    + +

    Versions

    +

    I am reading these and bookmarking them on the kindle app to save bookmarks temporarily between devices using kindle. I suspect all important notes will not require these bookmarks and they are just for convenience.

    +
      +
    • Calculus_EarlyTranscendenals_9th_Solutions_Stewart.pdf
    • +
    • Calculus_EarlyTranscendenals_9th_Stewart.pdf
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/compilers-ch1-the-dragon-book/index.html b/docs/digests/compilers-ch1-the-dragon-book/index.html new file mode 100644 index 00000000..d6a7b770 --- /dev/null +++ b/docs/digests/compilers-ch1-the-dragon-book/index.html @@ -0,0 +1,4080 @@ + + + + + + + + + + + + + + + + Compilers Ch1 The Dragon Book - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Compilers ~ The Dragon Book - 1986

    +

    Chapter 1 - Introduction to Compiling

    +

    On the general subject of compiling.

    +

    Contents

    +
      +
    • components of a compiler
    • +
    • environment in which a compiler does its job
    • +
    • tools to make it easier to build compilers
    • +
    +

    1.1 Compilers

    +

    compiler - a program that reads a program written in the source language and translates it into an equivalent target program in the target language. The compiler reports errors in the source program as error messages.

    +
      +
    • "basic tasks" all compilers perform "are the same"
    • +
    • Thousands of source languages
    • +
    • Target languages include
        +
      • Another programming language
      • +
      • Machine language of any computer (microprocessor to supercomputer)
      • +
      +
    • +
    • Some compiler classifications - based on structure or function
        +
      • single-pass
      • +
      • multi-pass
      • +
      • load-and-go
      • +
      • debugging
      • +
      • optimizing
      • +
      • etc.
      • +
      +
    • +
    • advances in compilers:
        +
      • implementation languages
      • +
      • programming environments
      • +
      • software tools
      • +
      +
    • +
    +

    The Analysis-Synthesis Model of Compilation

    +

    The 2 parts of compilation are analysis and synthesis.

    +
      +
    1. Analysis - Break the source program into pieces and create an intermediate representation of the source program.
    2. +
    3. Synthesis - Construct the target program from the intermediate representation *requires the most specialized techniques
    4. +
    +
    Analysis
    +
      +
    • Operations of source program are determined & recorded in a tree, (hierarchical structure).
    • +
    • Often a syntax tree
        +
      • node == operation
      • +
      • children of node == arguments of operation
      • +
      • in the text diagram, operations can be arguments:
          +
        • position := initial + rate * 60
        • +
        +
      • +
      +
    • +
    • Many software tools that manipulate source programs first perform some kind of analysis
        +
      1. Structure Editors - text editor + autocomplete + linter + static analysis + etc.
          +
        • real-time partial analysis
        • +
        +
      2. +
      3. Pretty Printers - structure viewer for humans
      4. +
      5. Static Checkers - attempt to discover potential bugs without running the program. Similar to optimizing compilers.
          +
        • code that cannot be executed in the course of the program
        • +
        • variable used before defined
        • +
        • catch logical errors (type checking / use real variable as pointer)
        • +
        +
      6. +
      7. Interpreters - Instead of producing target program, perform the operations implied by source program
      8. +
      +
    • +
    +
    Compilers aren't just for machine code
    +

    The analysis portion of compiling shows up in these examples:

    +
      +
    1. Text formatters - Format text for output in a textual format
    2. +
    3. Silicon compilers - Input is a conventional programming source language. Variables represent signals or signal groups in switching circuits. Outputs a circuit design in an appropriate target language
    4. +
    5. Query interpreters - translates a predicate containing relational and boolean operators into commands to search a database for records satisfying the predicate
    6. +
    +

    The Context of a Compiler

    +

    Other programs may be needed to create the executable target program.

    +
      +
    • A preprocessor might:
        +
      • collect parts of the source program stored in separate files
      • +
      • expand macros into source language statements.
      • +
      +
    • +
    +

    See fig 1.3 page 4.

    +
      +
    • A target program may require further processing to run.
        +
      • assembler - translate assembly to machine code
      • +
      • linker - link to library routines
      • +
      +
    • +
    +

    1.2 Analysis of the source program

    +

    Introducing analysis and illustrate its use in some text-formatting languages. Also see chapters 2-4, 6.

    +
    Three Phases of Analysis
    +
      +
    1. Linear Analysis
        +
      • AKA: lexical analysis or scanning
      • +
      • read stream of source program left-to-right and group into tokens, streams of characters, with collective meaning
      • +
      +
    2. +
    3. Hierarchical Analysis
        +
      • AKA: syntax analysis or parsing
      • +
      • hierarchically group characters/tokens into meaningful nested collections
      • +
      +
    4. +
    5. Semantic Analysis
        +
      • find semantic errors, identify operands, type checking
      • +
      • check that components of a program fit together meaningfully
      • +
      +
    6. +
    +

    Lexical Analysis

    +

    Linear analysis is called lexical analysis or scanning. See example page 5.

    +

    Create tokens from the source program stream. Discard separators, e.g. whitespace.

    +

    Syntax Analysis

    +

    Hierarchical Analsysis is called parsing or syntax analysis.

    +

    Group the tokens into grammatical phrases for the compiler to synthesize output. Usually the grammatical phrases are represented by a parse tree or a syntax tree.

    +
      +
    1. parse tree - statements, expressions, and identifers are all nodes. A precise definition is not given, see fig. 1.4, page 6.
    2. +
    3. syntax tree - Compressed representation of a parse tree. Operators appear as interior nodes and operands are the children of that operator's node. See Section 5.2.
    4. +
    +

    There is a good example here, page 6.

    +

    expressions, recursive rules, (nonrecursive) basis rules, and definition rules, and statements are described in the example but not introduced as formal terms.

    +
    +

    The division between lexical and syntactic analysis is somewhat arbitrary. +We usually choose a division that simplifies the overall task of analysis.

    +
    +
    Factors for division between lexical and syntactic analysis:
    +
      +
    1. Is the source language construct recursive or not?
        +
      • Lexical constructs - do not require recursion.
          +
        • identifiers - strings of letters+digits beginning with a letter
        • +
        • recursion not necessary to recognize identifiers, typically scan until non-(letter+number) and group back to beginning
        • +
        • the grouped characters are recorded in a symbol table and removed from the input (so the pointer is back at the beginning)
        • +
        • the next token is then processed.
        • +
        +
      • +
      • Syntactic constructs often require recursion.
          +
        • linear scan cannot analyze expressions or statements
        • +
        • cannot match parentheses in expressions
        • +
        • cannot match begin and end in statements
        • +
        • unless there is a hierarchical or nesting structure ON the input
        • +
        +
      • +
      +
    2. +
    3. Context-free grammars - formalization of recursive rule that can be used to guide syntactic analysis
        +
      • See chapter 2 for introduction, chapter 4 for extensive treatment.
      • +
      +
    4. +
    +
    Syntax-directed translation
    +

    The compiler uses the hierarchical structure on the input to help generate the output.

    +

    See: Chapters 2, 5.

    +

    Semantic Analysis

    +
      +
    • check source program for semantic errors
    • +
    • gather type information for subsequent code-generation phase
    • +
    • +

      use hierarchical structure determined by syntax-analysis phase to identify operators and operands of expressions and statements

      +
    • +
    • +

      type checking: compiler checks that each operator has permitted operands based on source language specification. Must also check for operator coercions.

      +
        +
      • Part of semantic analysis, see ch. 6.
      • +
      • example: binary arithmetic operator applied to integer & real, converts integer to real, see example 1.1 and fig. 1.5 inttoreal
      • +
      +
    • +
    +

    Analysis in Text Formatters

    +

    TEX uses hierarchical arrangement in boxes as part of the syntax analysis to describe the relative position of groups of vertical and horizontal characters. See p.8-9 for fig 1.6-1.7.

    +

    1.3 The Phases of a Compiler

    +
      +
    • A compiler operates in conceptual phases. Each transforms the source program from one representation to another.
    • +
    • Some phases may be grouped together. Intermediate representations between grouped phases need not be explicity constructed.
    • +
    • See fig. 1.9, page 10 for a "typical decomposition of a compiler".
    • +
    +
    Phases
    +

    There are six phases between source program and target program:

    +
      +
    1. Lexical Analyzer
    2. +
    3. Syntax Analyzer
    4. +
    5. Semantic Analyzer
    6. +
    7. Intermediate Code Generator
    8. +
    9. Code Optimizer
    10. +
    11. Code Generator
    12. +
    +

    See figure 1.10 , page 13, for a detailed translation of position := initial + rate * 60.

    +
    Supplementary Phases (used during every phase)
    +
      +
    1. Symbol-table manager
    2. +
    3. Error handler
    4. +
    +

    Symbol-Table Management

    +
      +
    • Symbol Table: data structure containing a record for each identifier with fields for the attributes of the identifier. Quickly find, store, and retrieve data for that identifier.
    • +
    • The identifier is added by the lexical analyzer but the identifier's attributes are typically added and consumed during later phases.
    • +
    • An attribute could be something like storage, scope, type. If the identifier is a procedure: perhaps number and type of arguments, method of passing arguments (by reference, etc.), and type returned, if any.
    • +
    • See chapters: 2, 7 for more about symbol tables.
    • +
    +

    Error Detection and Reporting

    +

    Each phase must encounter and deal with errors, and potentially proceed.

    +
      +
    • The syntax analyzer and semantic analyzer typically handle a large fraction of errors.
    • +
    • The lexical analyzer may encounter errors when remaining characters do not form a token.
    • +
    • The syntax analyser finds errors where the token stream violates the structure rules.
    • +
    • The semantic analyzer can find errors where a meaningless operation occurs, e.g. add an array to the name of a procedure.
    • +
    • Further discussion of errors for each phase is included in the part of the book devoted to that phase.
    • +
    +

    The Analysis Phase

    +
      +
    • As translation progresses, the compiler's representatin of the source program changes.
    • +
    • note: In this diagram and chapter, the intermediate representation is considered/proxied as the syntax tree and symbol table. The data structure for the tree in fig. 1.10 is shown in fig. 1.11b.
    • +
    • Lexical analysis is covered in chapter 3.
    • +
    +

    Intermediate Code Generation

    +
      +
    • Some compilers generate an explicit intermediate representation of the source program, "a program for an abstract machine".
    • +
    • Variety of forms.
    • +
    • Chapter 8 covers principle intermediate representations in compilers. Chapters 5, 8 cover algorithms for generating intermedaite code for typical programming language constructs.
    • +
    +
    Properties of an intermediate representation
    +
      +
    1. easy to produce
    2. +
    3. easy to translate into the target program
    4. +
    +
    Three-address code
    +

    Three-address code consists of a sequence of instructions, each of which has at most three operands.

    +

    Assembly language for a machine in which every memory location can act like a register.

    +

    Code Optimization

    +

    Goal: improve intermediate code.

    +
      +
    • Simple example on pages 14-15.
    • +
    • Chapter 9 discusses simple optimizations.
    • +
    • Chapter 10 gives technology used by most powerful optimizing compilers.
    • +
    +

    Code Generation

    +

    Goal: generate target code from intermediate code.

    +
      +
    • Normally this gives relocateable machine code or assembly code.
    • +
    • A crucial aspect is assignment of variables to registers.
    • +
    • Simple example on pages 15-16.
    • +
    • Chapter 9 covers code generation.
    • +
    +

    1.4 Cousins of the Compiler

    +

    This section is about a compiler's typical operating context.

    +

    Preprocessors

    +

    Produce the input to compilers. Everything here seems to boil down to macros.

    +
      +
    1. Macro processing: allow user to define macros as shorhand for longer constructs.
    2. +
    3. File inclusion: include header files into the program text, e.g. in c language: #include <global.h> is replaced by the contents of global.h
    4. +
    5. "Rational" preprocessors: Add capabilities to a language, especially for flow control and data structures. Same as macros functionally?
    6. +
    7. Language Extensions: More macros, different use. See example in book.
    8. +
    +

    Example 1.2 on page 16.

    +

    Assemblers

    +

    Assembly code is a mnemonic version of machine code, where names are used instead of binary codes for operations. Names are also given to memory addresses.

    +
    +

    It is customary for assembly languages to have macro facilities that are similar to those in the macro preprocessors described above.

    +
    +

    Two-pass Assembly

    +

    Simple assemblers make two passes over the input file, where a pass reads a input file once.

    +
      +
    1. The first pass finds and stores identifiers, assigning storage locations in the symbol table.
    2. +
    3. The second pass translates operation code into the bits representing that operation in machine language. It also translates each identifier intot he address given for that identifier in the symbol table.
    4. +
    +

    The output of the second pass is usually relocateable machine code, which means it can be loaded starting in any memory location, L, in memory. If L is added to all addresses in the code, all references will be correct.

    +
    +

    Thus, the output of the assembler must distinguish those portions of instructions that refer to addresses that can be relocated.

    +
    +

    See example 3, page 18-19.

    + +

    A loader usually performs both loading and link-editing.

    +
      +
    1. loading: Taking relocateable machine code, altering the relocateable address, and placing the altered instructions and data in memory at the proper locations.
    2. +
    3. link-editor: Make a single program from several files of relocateable machine code. Many of the files result from separate compiles, and often are stored in separate locations for system-wide use. e.g. libraries.
    4. +
    5. external reference: code in one file references a location in another file. May be data or an entry point to a procedure.
        +
      • relocateable machine code file must retain the information in the symbol table for:
          +
        • each data location defined in one file and used in another
        • +
        • each entry point of a procedure defined in one file and used in another
        • +
        +
      • +
      • if not known in advance, must include entire symbol table as part of relocateable machine code
      • +
      +
    6. +
    +

    1.5 The Grouping of Phases

    +

    Multiple phases are often grouped together in compiler implementations.

    +

    Front and Back Ends

    +
      +
    1. Front end: largely independent of target machine, based on source language
        +
      • lexical analysis
      • +
      • syntactic analysis
      • +
      • symbol table creation
      • +
      • semantic analysis
      • +
      • generate intermediate code
      • +
      +
    2. +
    3. Back end:
        +
      • code optimization
      • +
      • code generation
      • +
      • error handling
      • +
      • symbol table operations
      • +
      +
    4. +
    +

    Fairly routine: keep the front end of a compiler and redo the back end for another machine. Parts of the back end can even be kept. Further discussion in Chapter 9.

    +
    +

    It is also tempting to compile several different languages into the same intermediate language and use a common back end for the different front ends, thereby obtaining several compilers for one machine. However, because of subtle differences in the viewpoints of different languages, there has been only limited success in this direction.

    +
    +

    Passes

    +

    Many phases can be done in one pass. Organizing phases into passes is complex and discussed for some specific implementations in chapter 12.

    +

    The whole back end may be one pass, immedately producing intermediate code.

    +

    We may think of the syntax analyzer as being 'in charge'. As it discovers grammatical structure, the parser can call intermediate code generation. See chapter 2 for a compiler with this implementation.

    +

    Reducing the Number of Passes

    +

    Goal: Have relatively few passes.

    +

    Goal: Don't use up all the system memory.

    +

    Reconciling these could create tension.

    +
    +

    The interface between the lexical and syntactic analyzers can often be limited to a single token. It is often very hard to perform code generation until the intermediate representation has been completely generated.

    +
    +
      +
    1. backpatching: merge intermediate code and target code generation can often be merged into one pass by creating a slot and filling it once the information becomes available. See the example, page 21.
    2. +
    +

    To ensure you do not use too much space, you can reduce the distance over which backpatching occurs.

    +

    1.6 Compiler-Construction Tools

    +

    Chapter eleven discusses software tools for implementing a compiler.

    +

    There are specialized tools for implementing various phases of a compiler

    +

    These tools are called variously:

    +
      +
    • compiler-compilers
    • +
    • compiler-generators
    • +
    • translator-writing systems
    • +
    +

    Specialized tools are typically oriented around a model of languages and are suitable for languages following that model.

    +

    Tools exist for automatic design of specific compiler components, they use specialized languages for specifying and implementing the component. The most successful hide details of generation algorithm and make components that are easily integrated into the remainder of the compiler.

    +
    A list of compiler construction tools
    +
      +
    1. Parser generators: produce syntax analyzers normally from in put based on context-free grammar. Syntax analysis used to be very time consuming but now is "one of the easiest phases to implement". Often parser generators use parsing algorithms too complex to do by hand.
    2. +
    3. Scanner generators: automatically generate lexical analyzers, normally from a specification based on regular expressions. The lexical analyzer is effectively a finite automaton. See chapter 3, implementations in section 3.5, section 3.8.
    4. +
    5. Syntax-directed translation engines: produce collections of routines that walk the parse tree, generating intermediate code. One or more translations are associated with each node of the parse tree, each translation defined in terms of its neighbor nodes in the tree. See chapter 5.
    6. +
    7. Automatic code generators: take a collection of rules defining intermediate language->target language and replace the intermediate rules with templates that represent sequences of machine instructions. Something about tiling intermediate code without a combinatorial explosion in compiler running time. See chapter 9.
    8. +
    9. Data-flow engines: data flow analysis is used in optimization. How are values transmitted from one part of a program to each other part? Especially as the user defines relationships between intermediate code statements and the information being gathered. See Section 10.11.
    10. +
    +

    Bibliographic Notes

    +

    Lots of parallel discovery, hard to attribute credit. Page 23-24 have references.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/cracking_creativity_michalko/index.html b/docs/digests/cracking_creativity_michalko/index.html new file mode 100644 index 00000000..d9a4ef2c --- /dev/null +++ b/docs/digests/cracking_creativity_michalko/index.html @@ -0,0 +1,3591 @@ + + + + + + + + + + + + + + + + Cracking Creativity Michalko - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Cracking Creativity

    +

    My condensed notes and summaries.

    +

    Intro / Overview

    +

    The book presents thinking strategies of creative giants from: science, arts, industry.

    +

    Advice: Find excellent mentors. It is obvious that creative geniuses successfully transmitted their genius. Fermi's students had 6 nobel prize winners. Bohr's students had 4 nobel prize winners.

    +

    Productive Thinking First (stop using reproductive thinking)

    +

    Feynman proposed schools should teach productive thinking instead of reproductive thinking.

    +
      +
    • Productive Thinking: Creative. Generate as many approaches as you can no matter how likely. look for all the possible needles by dissecting the haystack.
    • +
    • Reproductive Thinking: Not creative. Rehash your experience into solutions. Rigid and narrow. Not competitive, others already thought of it.
    • +
    +

    Idea Goals: Quantify and Qualify

    +
      +
    • Be Productive: Geniuses set concrete numeric goals for their ideas in the short term. Writers set quotas for writing, Edison set goals for small (1 per 10 days) and big inventions (1 per 6 months).
    • +
    • Blind Variations: Produce original and novel variations. This is the core principle.
    • +
    +

    Selecting Ideas to Invest Time Into

    +
      +
    • Within the mileu of ideas, let natural selection make choices. Evolution finds novel paths with a fitness algorithm.
    • +
    • What is the fitness algorithm for our ideas? I suspect the book to be light on this topic.
    • +
    • Place to dig deeper on my own?
    • +
    +

    Practice, Practice, Practice (Productive Thinking)

    +

    Organize your thinking by practicing these 9 strategies. Without practice, you will get no benefit.

    +

    Intro Summaries

    +

    These are summaries of the intro, not the whole book.

    +

    Part 1: Seeing what no one else is seeing.

    +
      +
    1. Knowing How to See
    2. +
    3. Use many unrelated perspectives to reimagine a problem
    4. +
    5. Don't just solve the existing problem, invent new problems and improve the problem space
    6. +
    7. Trent: I often find that the solution is obvious if I use my practical skills to enrich the question space
    8. +
    9. Define new problems as necessary even if they don't seem related.
    10. +
    11. Making Your Thought Visible
    12. +
    13. Use diagrams, mock ups, anything to break out of written and verbal (away from language, math, dialogue)
    14. +
    15. Formulate the subject as many ways as possible, especially with diagrams
    16. +
    +

    Part 2: Thinking What No One Else is Thinking

    +

    Strategy 1 is used to produce a quantity of ideas.

    +

    Strategies 2-6 are for getting "blind variations" demonstrate how to incorporate chance and randomness to destabilize existing patterns of thinking and reorganize thoughts in new ways.

    +

    Strategy 7 is "conditions for effective group brainstorming" and "a selection of world class brainstorm techniques".

    +
      +
    1. Thinking Fluently
    2. +
    3. The most respected scientists produced the most GREAT works -and- the most BAD works.
    4. +
    5. Geniuses produce. Period.
    6. +
    7. Edison had invention quotas: small every 10 days, large every 6 months
    8. +
    9. Bach wrote a Cantana per week, even when exhausted
    10. +
    11. Einstein produced 248+ papers
    12. +
    13. Writers have daily writing quotas, trent: see john steinbeck and stephen king
    14. +
    15. Making Novel Combinations
    16. +
    17. "Combinatory Play" - Einstein's self-proclaimed essential feature in productive thought.
    18. +
    19. Form more novel combinations than anyone else.
    20. +
    21. Constantly combine and recombine from a large pool of parts (like legos)
    22. +
    23. The more you do the more success you will have. Go quickly and thoroughly.
    24. +
    25. Also use your subconscious (diffuse mode) by switching between different idea spaces then entering diffuse mode (meditation, sleep, eating, talking, physical labor, resting, exercise)
    26. +
    27. Connecting the Unconnected
    28. +
    29. Force completely unrealistic connections, see where they work, repeat. The winners will come out.
    30. +
    31. Tesla: the sun aroud the earth and the AC motor (magnet rotates). - example of zany idea yielding creative outcome
    32. +
    33. Da Vinci: The sound of a bell and a stone hitting water (visual & auditory waves)
    34. +
    35. Looking at the Other Side
    36. +
    37. David Bohm: Tolerate ambivalence between opposite or incompatible subjects
    38. +
    39. Niels Bohr: if you hold opposites together, you suspend your thought and your mind moves to a new level
    40. +
    41. Niels Bohr imagined light as both a particle and a wave (incompatible, yet it is still true)
    42. +
    43. Looking in Other Worlds
    44. +
    45. Analogies between unrelated systems
    46. +
    47. Inspiration from toys and nature
    48. +
    49. Finding What You Are Not Looking For
    50. +
    51. First principle of the Creative Accident
    52. +
    53. Answering the question in a novel, unexpected way is the essential creative act
    54. +
    55. B.F. Skinner's first principle for scientific methodologists: "When you find something interesting, drop everything and study it."
    56. +
    57. +

      Drop your preconcieved plan with conviction and study the new thing.

      +
    58. +
    59. +

      Awakening the Collaborative Spirit

      +
    60. +
    61. Principles and conditions for participants to retain their individuality while combining their efforts and talents in a group in ways vital for collaborative synthesis.
    62. +
    63. Collegial. Open & honest collaboration.
    64. +
    +

    Strategy One: Knowing How to See

    +
      +
    • Da Vinci: "saper vedere" is knowing how to see
    • +
    • first perspective is usually wrong
    • +
    • move repeatedly to new perspectives, deepen understanding along the way
    • +
    • "Invitational Stem" - start problem statement with "In what ways may I..." to avoid narrowing the problem statement to one perspective.
    • +
    • Human language plays a role: Verbalize and write out a problem (and other ways) -- do not solve silently -- for better outcomes.
    • +
    • Don't persist with any one perspective.
    • +
    • Try using a whole different system and terms to express the same relationship
    • +
    • Restructuring your problems more makes it more likely you will deepen your perspective
    • +
    +

    Ways to restructure your problem:

    +
      +
    • Global and Specific Abstractions
    • +
    • Separate the parts from the whole
    • +
    • Change the words in some fashion
    • +
    • Make positive action statements
    • +
    • Switch perspective
    • +
    • Use Da Vinci's multiple perspectives
    • +
    • Use Questions
    • +
    +

    Global and Specific Abstractions

    +

    Quip

    +

    "Make it more global and specific."

    +

    Tips

    +
      +
    • To widen your perspective use the "5 whys": Ask why 5 times to your answer to the previous why. Find the level of abstraction that fits.
    • +
    • Ask "Who, what, when, where, why, how?"
    • +
    • The more specifically you define your problem statement, the easier it will be to generate ideas. (tradeoffs)
    • +
    • Trent: Specific statements miss solutions, abstraction may be necessary to discover something great.
    • +
    +

    Summary

    +
      +
    • "Abstraction is a basic principle in restructuring a problem."
    • +
    • "Widening the perspective", at the maximum "globalize" the problem
    • +
    • Find the APPROPRIATE level of abstaction.
    • +
    • "Standard procedure for physical science is abstraction."
    • +
    • Galileo "ideal vacuum" thought experiment imagined a large vacuum existed (none was available)
        +
      • all items fall through a vacuum with the same acceleration regardless of their weight
      • +
      • More abstract version of "what weighs more, a pound of feathers or a pound of bricks?"
      • +
      • removes the pound: "what accelerates faster in a vacuum, a feather or a brick?" (neither)
      • +
      +
    • +
    • Einstein relativity was also unobservable.
    • +
    • "More specific problem statements lead to faster solutions with less conceptual clarity."
    • +
    • oil spill: driveway vs gulf coast
    • +
    • new keyboard design vs new global IT industry niche
    • +
    • Shipping industry too focused on reducing costs of ships
    • +
    • Perspective change, global problem statement: "In what way can the shipping industry lower reduce costs?"
    • +
    • Solution: Separate loading and stowing. Container ships reduced port time, congestion, theft. Ships spend more time traveling
        +
      • ship is "capital equipment" - spends more time doing its unique work of moving)
      • +
      • costs down 60%
      • +
      +
    • +
    +

    Separate the Parts from the Whole

    +

    Move from one detail to another examining it in isolation from the rest.

    +
      +
    • Fishbone Diagram
    • +
    • good for processing a "north star" or large vision
    • +
    • find relationships between causes and effects
    • +
    • use more than one session to work on a diagram
    • +
    • let the diagram cook overnight (in your mind) and then return to find your fresh thoughts & ideas
    • +
    +

    Words and Word Chains

    +
      +
    • Aristotle work titled "On Interpretation" - words and chains of words are powerful tools of thought
    • +
    • both reflect thinking and shape thinking
    • +
    • Words crystallize thought, creating precision and rigidity. (both strength and weakness)
    • +
    +

    Rephrase the Problem / Feynman

    +
      +
    • avoid definitions such as "friction", "energy" (trent: this abstraction can hide important meaning too early)
    • +
    • students should rephrase what they learn in their own language
    • +
    • example of avoiding "friction": shoe soles go flat because notches and bumps in the sidewalk grab pieces and pull them off
    • +
    • +

      trent: now we see the sidewalk-shoe interface is more like a slow table saw, scooping a little rubber from various places each step

      +
    • +
    • +

      Example: Toyota asked employees a question 2 ways, the 1st failed, the 2nd worked:

      +
    • +
    • "How can you be more productive at work?"
    • +
    • "How can you make your job easier?"
    • +
    +

    Change the Words

    +
      +
    • Try changing the verb, it is easier to do.
    • +
    • Play with verbs and nouns:
    • +
    • Transpose the Words
    • +
    • Aristotle "convertibility" - "if every pleasure is good, some good must be pleasure." (questionable)
        +
      • find a "verbal-conceptual chain" to trigger a "different view"
      • +
      +
    • +
    • "How can I get a promotion?" vs "How can I promote myself?"
        +
      • interesting relationship even though it's just a random transposition.
      • +
      +
    • +
    • "How can I learn to use the internet?" vs "How can I use the internet to learn?"
        +
      • 21 years later this one hits spot on, that's a major use of the internet.
      • +
      +
    • +
    • The first word often influences, for example:
    • +
    • "skyscraper prayer temple cathedral" = architectural concepts
    • +
    • "prayer skyscraper temple cathedral" = religious concepts
    • +
    +

    One Word Technique

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/data_portal_dictionary_catalog/index.html b/docs/digests/data_portal_dictionary_catalog/index.html new file mode 100644 index 00000000..5831f945 --- /dev/null +++ b/docs/digests/data_portal_dictionary_catalog/index.html @@ -0,0 +1,3217 @@ + + + + + + + + + + + + + + + + Data Portal Dictionary Catalog - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Data Portal

    +

    Support Pages, Data Catalog, and Data Dictionary.

    +

    Capabilities

    +

    Ideas drawn from DataSF Support Pages

    +

    A set of pages to help people:

    +
      +
    1. Find data
    2. +
    3. Integrate data into their tools
        +
      • excel
      • +
      • tableau
      • +
      • etc.
      • +
      +
    4. +
    +

    Serve as a data catalog and data dictionary.

    +

    Data Catalog

    +

    A searchable list of data sources for discovering available data.

    +

    Resources

    + +

    Data Dictionary

    +

    A set of wiki-like pages that provides information about available data.

    +

    Warby Parker used an internally hosted gitbook to disseminate information about datasets.

    +

    Resources

    +
      +
    • Wikipedia - Data Dictionary
    • +
    • +

      Dan Woods - "Why You Can't Be Data-driven Without A Data Catalog"

      + +
      +

      In conversations with Carl Anderson, director of data science at Warby Parker, I discovered an elegant approach based on creating an integrated model. Anderson and his team did exhaustive research about the concepts used by executives and analysts to describe and understand business activity. Much of this knowledge was embedded in spreadsheet formulas or handcrafted SQL. Anderson and his team worked with each department to create a common definition of concepts like customer, product and revenue. Often, two distinct definitions were needed because marketing and finance think of the customer differently. In the end, Anderson created a shared, integrated and explorable model using Looker, which brought all departments to a common understanding. A data dictionary stored in GitBook described all the data fields and definitions and showed where to find them in Looker. (See “The Warby Parker Data Book” for why GitBook was chosen.) This type of approach is just one of many lessons you can learn from Anderson’s book, Creating a Data Driven Organization.

      +
      + +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/design-patterns-in-python/intro-and-solid-design-principles/index.html b/docs/digests/design-patterns-in-python/intro-and-solid-design-principles/index.html new file mode 100644 index 00000000..3259fd37 --- /dev/null +++ b/docs/digests/design-patterns-in-python/intro-and-solid-design-principles/index.html @@ -0,0 +1,3451 @@ + + + + + + + + + + + + + + + + Intro And Solid Design Principles - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Design Patterns in Python

    +

    Gang of Four book, translated to Python.

    +
      +
    • End-of-section coding exercise.
    • +
    • One Python file per demo.
    • +
    • "Latest" version of Python (as of when?)
    • +
    • liberal use of decorators, metaclasses where applicable
    • +
    • external packages will also be used if valuable
    • +
    +

    Author

    +
      +
    • Dmitri Nesteruk, quant finance professional
    • +
    • Course author on: Pluralsight, Udemy, Elsewhere
    • +
    • Design patterns in: C#, Java, C++, Swift, Python
    • +
    +

    Other Topics

    +
      +
    • Sequence processing (streams/Rx)
    • +
    • Concurrency
    • +
    • Dependency injection
    • +
    +

    Languages picked up these design patterns already

    +
      +
    • C# implementation of observer pattern
    • +
    • Python implementation of decorator
    • +
    • third party libraries
    • +
    +

    Three Categories of Design Patterns

    +

    All from the book.

    +
      +
    • Creational
    • +
    • Builder
    • +
    • Factories (two patterns): Abstract Factory, Factory Method
    • +
    • Prototype
    • +
    • Singleton
    • +
    • Structural
    • +
    • Adapter
    • +
    • Bridge
    • +
    • Composite
    • +
    • Decorator
    • +
    • Facade
    • +
    • Flyweight
    • +
    • Proxy
    • +
    • Behavioral
    • +
    • Chain of Responsibility
    • +
    • Command
    • +
    • Interpreter
    • +
    • Iterator
    • +
    • Mediator
    • +
    • Memento
    • +
    • Observer
    • +
    • State
    • +
    • Strategy
    • +
    • Template Method
    • +
    • Visitor
    • +
    +

    Solid Design Principles

    +
      +
    • +

      Introduced by "Uncle Bob", Robert C. Martin

      +
        +
      • Multiple books, plus blog
      • +
      • There are a rather large number of design principles
      • +
      • 5 selected SOLID
      • +
      +
    • +
    • +

      Single Responsibility Principle (SRP): "Separation of Concerns"

      +
    • +
    • Open-Closed Principle
    • +
    • Liskov Substitution Principle
    • +
    • Interface Segregation Principle
    • +
    • Dependency Inversion Principle
    • +
    +

    1. Single Responsibility Principle (SRP): "Separation of Concerns"

    +

    Example: Journal class that also has persistence (save, load)

    +
    +

    Journal class stores and allows manipulating entries, but then also gets functionality for persistence. This is a bad idea for a number of reasons. Persistence would go in its own class. Instead write a PersistenceManager class with a static save_to_file(j, filename) method.

    +
    +
      +
    • Antipattern: 'God Object', everything into a single class.
    • +
    +

    2. Open-Closed Principle: "Open for Extension, Closed for Modification."

    +

    Example: Product has some properties, size, color.

    +
    +

    How do you filter product by color? Use a for loop to filter by color. But now we want to filter by size. When you add new functionality, add by extension, not modification. Now try filter by color and size... you add a third function for color AND size. This approach is combinatorial. You are also causing a state-space explosion. Add weight and for 3 params you need summation(3) filters: 3+2+1

    +
    +

    Lets add the new filters through modification and use an "enterprise pattern".

    +

    "Enterprise patterns require a separate course."

    +

    Enterprise Pattern: "Specification"

    +
    class Product:
    +    def __init__(self, name, color, size):
    +        self.name = name
    +        self.color = color
    +        self.size = size
    +
    +# OCP = open for extension, closed for modification
    +
    +# see the course resources for the full implementation with some testing
    +class Specification:
    +    ''' determine if an item specifies a criteria
    +
    +    This is a base class. You are intended to override the methods.
    +    '''
    +    def is_satisfied(self, item):
    +        pass
    +    # this is explained later, i think it's foolish and breaks expectations for the reader of the code...
    +    def __and__(self, other):
    +        return AndSpecification(self, other)
    +
    +
    +class Filter:
    +    ''' General method, doesn't specify any particular criteria.
    +
    +    This is a base class. You are intended to override the methods.
    +    '''
    +    def filter(self, items, spec):
    +        pass
    +
    +class ColorSpecification(Specification):
    +    def __init__(self, color):
    +        self.color = color
    +    def is_satisfied(self, item):
    +        return item.color == self.color
    +
    +class SizeSpecification(Specification):
    +    def __init__(self, size):
    +        self.size = size
    +    def is_satisfied(self, item):
    +        return item.size == self.size
    +
    +class BetterFilter(Filter):
    +    def filter(self, items, spec):
    +        for item in items:
    +            if spec.is_satisfied(item):
    +                yield item
    +
    +# How do we implement the combinator `AND` with these?
    +class AndSpecification(Specification):
    +    ''' check that any number of specifications apply
    +    '''
    +    def __init__(self, *args):
    +        self.args = args
    +
    +    def is_satisfied(self, item):
    +        # NB: all() returns True if empty, but false for e.g. [''] or [None]
    +        return all(map(
    +            lambda spec: spec.is_satisfied(item), self.args
    +        ))
    +
    +# This is the combinator
    +large_and_blue = AndSpecification(SizeSpecification(Size.LARGE), ColorSpecification(Color.BLUE))
    +bf = BetterFilter()
    +for p in bf.filter(products, large_and_blue)
    +
    +# we want to simplify large_and_blue though, we can overload the `binary and` operator, `&`
    +# lets do this in `Specification` above, are we breaking the open closed principle? no we would do this at the beginning (trent: not business realistic...)
    +# This is silly, breaks type expectation for reader. Just keep it simple, accumulate and explode a sequence or something
    +large_and_blue = SizeSpecification(Size.LARGE) & ColorSpecification(Color.BLUE)
    +
    + +

    3. Liskov Substitution Principle

    +
      +
    • Named after Barbara Liskov.
    • +
    • If you have an interface named after a base class you should be able to stick a derived class in and everything should work.
    • +
    • Imagine a Rectangle class and a Square class that inherits from rectangle. Square should work wherever rectangle worked.
        +
      • So maybe we expect width*height=area, where class rectangle has each @property: width, height.
      • +
      • so for square, lets just take one dimension, size, since width is height.
          +
        • Now if we set width and height at the same time, both from size, "this looks very innocent"
        • +
        +
      • +
      • now if we use use_it, it only works on a rectangle, because it sets width, height explicitly.
          +
        • We can fix use_it a few ways: don't have a square class (doesn't solve use_it), don't allow the setters
            +
          • trent: avoid square class is the right answer, we should still use @property in Python.
          • +
          • trent: so this means that our descendants are constrained by our downstream implementations? i don't love this...
              +
            • So uh... When we need to refactor, we need to enumerate downstream impelementation before we can subclass something? Well, alright...
            • +
            +
          • +
          +
        • +
        +
      • +
      +
    • +
    +

    4. Interface Segregation Principle

    +
      +
    • If you have a "kitchen sink interface", then individual implementations have a bunch of NOOP methods.
    • +
    • If someone makes an instance of a limited implementation, they try using the NOOP methods.
    • +
    +

    5. Dependency Inversion Principle

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/engelbart_hlamt_1962/index.html b/docs/digests/engelbart_hlamt_1962/index.html new file mode 100644 index 00000000..2c080d7d --- /dev/null +++ b/docs/digests/engelbart_hlamt_1962/index.html @@ -0,0 +1,3544 @@ + + + + + + + + + + + + + + + + Engelbart Hlamt 1962 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    + +
    + + + +
    +
    + + + + + + + + + +

    Engelbart Hlamt 1962

    + +

    Outline for Doug Engelbart's "Augmenting Human Intellect: A Conceptual Framework"

    +

    These notes are typed into an outline from paper notes taken while reading this paper.

    +

    Version: 0.02

    +
    Future:
    +
      +
    1. Try to get the notes structure to match the table of contents.
    2. +
    3. Find another copy to verify against my printed copy, make sure no info was lost.
    4. +
    5. Try to get at least an outline of part 3A together.
    6. +
    7. Part 3B is long and not very helpful but maybe some richer definitions can be pulled from it.
    8. +
    9. Part 4 was research recommendations. Needs summarized to some degree but is very old and may not be useful.
    10. +
    +
    Key References:
    +
      +
    • (1) Kenneth J.L., Putt, G.H. - " Administration of Research in a Research Corporation", RAND Corporation Report P-847 (20 April 1956)
    • +
    • (20) Fein, Louis - "The Computer Related Science (Synnoetics) at a University in the Year 1975"
    • +
    • What is the Whorfian Hypothesis? Neo-Whorfian Hypothesis? See language section in Part II.
    • +
    +
    Outcomes:
    +
      +
    • This paper generates language for approaching the H-LAM/T system. Does it give methodology or artifacts?
    • +
    • Is it my job to keep generating language and start building artifacts and methodology to continue amplifying our intelligence?
    • +
    • Are computers sufficient? Do we write computer programs for 500 years now, progressively generating language and automating more metholology as we spike off as more abstract beings?
    • +
    • This paper wants to "automate external symbol manipulation" - in other words it wants to build giant trees of language which are used to uncover new language. See section on language.
    • +
    +

    Augmenting Human Intellect:

    +
    Abstract:
    +

    "This is an initial summary report of a project taking a new and systematic approach to improving the intellectual effectiveness of the individual human being. A detailed conceptual framekwork explores the nature of the system composed of the individual and the tools, concepts, and methods that match his basic capabilities to his problems. One of the tools that shows the greatest immediate promise is the computer, when it can be harnessed for direct on-line assistance, integrated with new concepts and methods.

    +

    Part I - Introduction

    +
      +
    1. +

      Part 1A - General ( "Terms and Definitions" )

      +
        +
      1. Augmenting Human Intellect = "Increasing a human's ability to..."
          +
        1. Approach a complex problem situation
        2. +
        3. Gain comprehension to suit his needs
        4. +
        5. Derive solutions to problem
        6. +
        +
      2. +
      3. Increased Capabilities
          +
        • "Faster, better, beyond original capabilities"
        • +
        +
      4. +
      5. Complex Situations = "Professional Problems"
          +
        • Problem scale is 20 minutes to 20 years
        • +
        +
      6. +
      7. Means
          +
        • extensions of native sensory, motor, and mental capabilities
        • +
        +
      8. +
      9. Improvement Space
          +
        • Visualize this extending from/with the H-LAM/T Capability Space
        • +
        • Will cover in section 2
        • +
        +
      10. +
      +
    2. +
    3. +

      Part 1B - Objective of the Study

      +
        +
      1. Find: factors that limit effectiveness of the individual's basic information-handling capabilities in meeting society's needs for problem solving in its most general sense
      2. +
      3. Develop: Techniques, Procedures, Systems - "which better match these basic capabilities to the needs, problems, and progress of society"
      4. +
      5. Specifications:
          +
        1. Both long- and short-term research goals in augmentation
        2. +
        3. Specific actions in:
            +
          1. Work Environment
          2. +
          3. Thinking
          4. +
          5. Skills
          6. +
          7. Methods of working
          8. +
          +
        4. +
        5. Framework is a basis for:
            +
          1. evaluating possible relevance of work/knowledge from existing fields
          2. +
          3. assimilate relevant things from those fields
              +
            • "Not be in a vacuum of study"
            • +
            +
          4. +
          +
        6. +
        +
      6. +
      7. Framework is a basis for choosing starting points
          +
        • reveal areas where research can be done
        • +
        • develop methodologies for that research
        • +
        +
      8. +
      9. H-LAM/T Conceptual Framework is a "rudimentary framework"
          +
        • a place to start at and evolve from
        • +
        +
      10. +
      +
    4. +
    +

    Part II - Conceptual Framework

    +
      +
    1. Human has:
        +
      • Motor channels: Transmit information
      • +
      • Sensory channels: Receive information
      • +
      +
    2. +
    3. Human processing:
        +
      • Conscious Processing
      • +
      • Unconscious Processing
      • +
      +
    4. +
    5. Augmentation Means:
        +
      1. Artifacts
      2. +
      3. Language
      4. +
      5. Methodology
          +
        • Organization by methods, procedures, and strategies
        • +
        +
      6. +
      7. Training
      8. +
      +
    6. +
    7. "Process Hierarchies"
        +
      • Structure / Organization of each tiny step
      • +
      +
    8. +
    9. "Augmentation Means"
        +
      • Serve to break down complex problems to tiny steps
      • +
      • "tiny step" = "sub-process"
      • +
      +
    10. +
    11. There is no way to "find the bottom" of the subprocess tree
        +
      • It is not necessary to start at the bottom
      • +
      • A "simple enough" bottom layer will do
          +
        • Does Engelbart mean simple enough to describe wholly or pragmatically? May not matter.
        • +
        +
      • +
      +
    12. +
    13. Begin from basic capabilities:
        +
      1. Sensory-Mental-Motor Process Capabilities
      2. +
      3. Add process capabilities of Artifacts
      4. +
      +
    14. +
    15. Each individual has their own repertoire of process capabilities which are selected and adapted for execution on a process
    16. +
    17. A person and his/her artifacts can be said to have a "toolkit" called a repertoire hierarchy which extends from his basic capabilities
    18. +
    19. 3 categories of process capability:
        +
      1. Explicit-Human
      2. +
      3. Explicit-Artifact
      4. +
      5. Composite (Human to Artifact Interface)
      6. +
      +
    20. +
    21. H-LAM/T System - Definition
        +
      • Human using
      • +
      • Language, Artifacts, and Methodology in which
      • +
      • he is Trained
      • +
      +
    22. +
    23. H/LAM-T System - Terms
        +
      1. has the capability and
      2. +
      3. uses the repertoire to
      4. +
      5. perform the process
      6. +
      +
    24. +
    25. Executive processes embody all methodology of H/LAM-T System.
        +
      • Habit
      • +
      • Strategy
      • +
      • Rules of Thumb
      • +
      • Prejudice
      • +
      • Learned Method - NOTE: implies training is contained in methodology?
      • +
      • Intuition
      • +
      • Unconscious Dictates
      • +
      +
    26. +
    27. NOTE: Methodology is enumerated above, which leaves only artifacts and language.
        +
      • Is this collection (and any similar extensions) along with artifacts, language enough to embody all interactions a human has with his substrate?
      • +
      • Language evolves around systems. Uncovering new systems will resolve new language.
      • +
      • What is training then? It seems to be a subset of method but is included in the acronym.
      • +
      • Maybe training is intended to be an extension of methods but as a special and critical process for onboarding process capabilities in humans (viewing a human as an artifact as well).
      • +
      • There is an analogy Engelbart uses between humans and artifacts, both containing repertoire hierarchies of process capabilities. An artifact is generally designed to execute a process capability. A human can be trained to execute a process capability.
      • +
      +
    28. +
    29. A new innovation ripples/propagates both up and down the capability hierarchy.
    30. +
    31. "Synthesis"
        +
      • New capabilities from old capabiltiies. Calls for a systems engineering approach.
      • +
      • "Synergy and Synthesis" - Use metal allow tensile strength analogy to understand how organizing some capabilities can create a radical new "synthetic capability"
          +
        • NOTE: This is cribbed BY Buckminster Fuller's "Operating Manual for Spaceship Earth". Engelbart was first unless it can be found in an earlier work. Regardless, the idea of alloys having complex new properties is potent. The world still has magic and it is materials engineering.
        • +
        • NOTE: It would be nice to have analogies other than materials engineering otherwise we should all just become materials engineers...
        • +
        +
      • +
      +
    32. +
    33. capabilities are "changeable parts"
        +
      • When changed, capabilities explose latent "synthetic capabilities" in that "repertoire hierarchy"
      • +
      • His idea: by changing interchangeable parts, "side reactions" or new capabilities can be unearthed.
      • +
      • An internal definition for what we call inventing by benevolent mistakes in experiment.
      • +
      +
    34. +
    35. Consider the whole H-LAM/T System as an ongoing experiment.
        +
      • NOTE: All humanity is in a PERMANENT, UNIFIED experiment. All action is data.
      • +
      • Gather data as such (on the interactions in the system)
      • +
      • some data targets: capabilities, effectiveness, etc.
      • +
      +
    36. +
    37. As humans have added tools, our common/shared repertoire hierarchies have grown and formed around us. Radical change is the norm.
        +
      • Can we accelerate radical change with guided research?
      • +
      +
    38. +
    39. "Intelligence Amplifier"
        +
      • Does not imply increasing raw intelligence.
      • +
      • An amplifier makes louder what is already there.
      • +
      • We seek to amplify intelligence by restructuring the H-LAM/T System.
          +
        • NOTE: He doesn't say repertoire hierarchies here, he says restructure the whole system.
        • +
        • NOTE: His hooks for restructure are Language, Artifacts, Methods (including Training).
        • +
        • NOTE: So what does he focus on?
            +
          • We could do:
              +
            • automation - move more and more trained methods into artifacts
            • +
            • science - create and apply new models and language (math?) to describe the universe
            • +
            • applications engineering - human methods seems like the weakest part of H-LAM/T... get a human to do more complex techniques
                +
              • Unless we are already down this rabbit hole and people increasingly program complex capabilities into dynamic artifacts right now
              • +
              +
            • +
            +
          • +
          +
        • +
        +
      • +
      +
    40. +
    41. NOTE: Often H/LAM-T will exist natively in a poorly built and/or poorly maintained state. Retraining may be 80% of the value of amplification.... sometimes.
    42. +
    43. LAM-T Augmentation means represent the amplifier:
        +
      • Simplified using Doug's definitions: "The means by which we augment LAM-T are the amplifier"
      • +
      • Simplified more: "The means are the amplifier"
      • +
      +
    44. +
    45. Man-Artifact Interface:
        +
      • NOTE: Human-Computer Interaction is the field today.
      • +
      • This term is derived from industrial revolution term "man-machine interface"
      • +
      • Two Domains:
          +
        1. Human
        2. +
        3. Artifact
        4. +
        +
      • +
      • Explicit-Human processes often exchange across an interface to Explicit-Artifact processes
      • +
      • Composite Processes - often designed solely for a functional match, "coupling", between the explicit processes.
      • +
      +
    46. +
    47. Language evolves to a situation
        +
      • Language can force its users down a way of thinking. Language does exert a force on its own evolution.
      • +
      • NOTE: Language evolves to describe new concepts, which is a form of mental modeling of phenomena which can reveal new capabilities and thus contribute to novel processes.
      • +
      • NOTE: Human-Language aided thought generates new ways of thinking, new methods, and new processes. These can later be trained or incorporated in artifacts.
      • +
      • Capabilities drive actions and drive language evolution
      • +
      • "We offer the following hypothesis, which is related to the Whorfian Hypothesis: Both the language used by a culture, and the capability for effective intellectual activity, are directly affected during their evolution by the means by which individuals control the external manipulation of symbols."
      • +
      • "Automated external symbol manipulation" - Synmbols which humans represents concepts he is manipulating can be rearranged before his eyes. Essentially giant trees of words and concepts that can uncover new language automatically by processing the base concepts of current language.
      • +
      • Note that in the next paragraph, Doug predicts the action of using google on a smartphone to search a term in real time. To some degree we are already living in a much more fluid-language world.
      • +
      • Question: How would having a complete, fast dictionary impact language evolution?
          +
        • NOTE: See encyclopedia dramatica, urban dictionary. People try to redefine things to what they want them to mean all the time, today. Terminology enters the zeitgeist very quickly but fades as quickly and terms often have different meanings to different clades. See: "Safe Space", 2016 representations and attacks. Organizations have to maintain internal definitions to be able to communicate.
        • +
        +
      • +
      +
    48. +
    49. Two points in designing new repertoire hierarchies:
        +
      1. Materials - fundamental capabilities from which all others must be constructed.
          +
        1. Decomposition Search
            +
          • Decompose capabilities to discover new materials (see: synthetic capabilities)
          • +
          +
        2. +
        3. De Novo - e.g. Materials Engineering (other analogies?)
        4. +
        +
      2. +
      3. Principles - Structures, explicitly synergetic structures
          +
        • "synergism" used by biologists and physicists for a siimilar concept:
            +
          • Webster's Unabridged Dictionary (quote from paper): "...cooperative action of discrete agencies such that the total effect is greater than the sum of the two effects taken independently..."
          • +
          +
        • +
        • Synergy is important because it is the threshold beyond which the means become greater than the sum of their materials.
        • +
        • Five tentative types of structure:
            +
          1. Mental
          2. +
          3. Concept
          4. +
          5. Symbol
          6. +
          7. Process
          8. +
          9. Physical
          10. +
          +
        • +
        +
      4. +
      5. Human contributes many types of capability... "wears many hats"
      6. +
      7. A complex capability has two classes of capability (NOTE: manager vs employee)
          +
        1. Executive class
        2. +
        3. Direct contributive class
        4. +
        +
      8. +
      9. Repertoire Hierarchy (sic)
          +
        • A mountain of white collar talent that sits atop and controls the talens of the "workers"
        • +
        • Goal: Maximize productivity, Gain comprehension, Solve problems.
        • +
        • Engelbart sees the production work as a flat base layer with a pyramid of white collar talent on top
        • +
        • "Theorem" - We could expect significant gains from improving symbol and process structuring.
        • +
        +
      10. +
      11. Finding: Humans switch frequently between one symbol structure and another continuously.
      12. +
      13. "Human Augmentation Means" will require:
          +
        • Training
        • +
        • Mental Tricks
        • +
        • Improved Language
        • +
        • New Methodology
        • +
        • "Unconscious Processes may be important"
        • +
        +
      14. +
      15. A human should be able to draw on explicit artifact capabilities at many levels in the process hierarchy
      16. +
      +
    50. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/golang/index.html b/docs/digests/golang/index.html new file mode 100644 index 00000000..06240868 --- /dev/null +++ b/docs/digests/golang/index.html @@ -0,0 +1,3121 @@ + + + + + + + + + + + + + + + + Golang - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Golang Reference

    +

    Local Docs

    +
      +
    • go install golang.org/x/tools/cmd/godoc@latest
    • +
    • godoc -http=:6060
    • +
    +

    Path & Setup/Install

    +

    This handles go on home path I like. Might replace with asdf or something.

    +

    This also handles go commands installed on $GOPATH, like godoc.

    +
    export GOPATH=$HOME/code/go
    +export PATH=$PATH:$HOME/.go/go/bin # version these maybe or does asdf handle this?
    +export PATH=$PATH:$GOPATH/bin
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/how-to-get-your-point-across-30sec/index.html b/docs/digests/how-to-get-your-point-across-30sec/index.html new file mode 100644 index 00000000..70bf50af --- /dev/null +++ b/docs/digests/how-to-get-your-point-across-30sec/index.html @@ -0,0 +1,3395 @@ + + + + + + + + + + + + + + + + How To Get Your Point Across 30Sec - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Summary: How to get your point across in 30 seconds or less

    +

    Resources

    + +

    Summary of Presentation

    +
      +
    1. +

      Presentation.

      +
    2. +
    3. +

      The presentation is 24 slides.

      +
    4. +
    5. Why 30 seconds? The attention span of a person is 30 seconds.
    6. +
    7. doctors listen to their patients for 19 seconds
    8. +
    9. TV commercials do a good job in 30 seconds
    10. +
    11. if you can't say it in 30 seconds, you likely are not thinking about your message clearly
    12. +
    13. Uses
    14. +
    15. Memos
    16. +
    17. faxes
    18. +
    19. letters
    20. +
    21. thank you notes
    22. +
    23. voicemails, text messages, telephone requests, conversations
    24. +
    25. messages left with a staff person
    26. +
    27. technical abstracts, technical proposals
    28. +
    29. formal presentations at meetings
    30. +
    31. interviews
    32. +
    33. sales pitch
    34. +
    35. complaint
    36. +
    37. social situation with superiors
    38. +
    39. chance meetings
    40. +
    41. giving a toast
    42. +
    +

    Preparation

    +

    note: Message could take an hour or more to prepare, plus speech prep time on top!

    +
      +
    1. OBJECTIVE: What do you want to acheve and why?
    2. +
    3. AUDIENCE: Who is the target of your message?
    4. +
    5. STRATEGY: How can you get what you want?
    6. +
    +

    Preparation Questions

    +
      +
    • Do you have a single, clear-cut specific OBJECTIVE
    • +
    • What does your AUDIENCE want from you?
        +
      • Can you speak in their thinking quadrant?
      • +
      • What benefits can you offer them?
      • +
      +
    • +
    • Brainstorm different STRATEGIES, then select the approach that best meets the objective.
        +
      • What format would be most effective (phone, memo, email, formal presentation, creative presentation, etc.)
      • +
      +
    • +
    +

    Message Content

    +
      +
    1. HOOK: How can you get the audiences attention?
    2. +
    3. SUBJECT: Are you providing all necessary details?
    4. +
    5. CLOSE: Are you asking for a specific action or reaction?
    6. +
    +

    Tips for Coming Up With a Killer Hook

    +
      +
    • Use the first statement as a hook to get attention
    • +
    • Relate the hook to your objective, audience, approach
    • +
    • Your hook can be a dramatic or humorous question or statement.
    • +
    • Your entire message can be a hook
    • +
    • The hook can be non verbal: action, mime, picture, object
    • +
    • Keep a "hook book" of ideas and quotes.
    • +
    +

    Tips for Preparing a Memorable Message

    +
      +
    • Answer who, what, where, when, why, and how - as they relate to the objective
    • +
    • Be brief, be clear, and touch the heart. Use imagery so the message will be remembered.
    • +
    • If you don't know the primary thinking preference of the audience, try to communicate IN ALL FOUR QUADRANTS.
    • +
    • CLARITY: Concise facts for Quadrant A thinkers
    • +
    • ACTION PLAN: Well-organized implementation for Quadrant B
    • +
    • IMAGERY: Creative word pictures for Quadrant D
    • +
    • EMOTIONAL APPEAL: Building relationships, sharing emotions, personal stories for Quadrant C.
    • +
    +

    Tips for an Effective Close

    +
      +
    • You must ask for what you want.
    • +
    • Demand action within a specific time frame.
    • +
    • Or ask for a reaction through the power of suggestion or example.
    • +
    • A message without a specific close or bottom-line is a wasted opportunity.
    • +
    +

    Message Type: Verbal Delivery

    +
      +
    • STYLE: What non-verbal messages are you giving? Monitor your body language.
    • +
    • APPEARANCE: Are you well-groomed?
    • +
    • SPEAKING: Learn to modulate your voice. Use pauses. Be animated.
    • +
    • ACTING: Smile. Use eye contact. Transmit a positive, friendly attitude.
    • +
    +

    Message Type: Written

    +
      +
    • Write legibly and neatly
    • +
    • Use good grammar and correct spelling
    • +
    • Where appropriate, also pay attention to a pleasing layout
    • +
    • Act as required by the situation, maybe one of these:
        +
      • positive and friendly
      • +
      • polite and formal
      • +
      +
    • +
    • Proof read, edit, then proof read again. Then check again. Get it perfect.
    • +
    +

    Tips for giving a Formal Presentation

    +
      +
    1. Start and finish on time
    2. +
    3. Make sure each person on your team is introduced clearly
    4. +
    5. Speak the language of your audience and state the purpose of your presentation
    6. +
    7. Use visual aids so peole will better remember your main ideas
    8. +
    9. Plan time for questions at the end; respond directly to the questions
    10. +
    11. Be yourself; project energy, enthusiasm, and confidence
    12. +
    13. Don't exaggerate or critisize -- don't bad-mouth the competition
    14. +
    15. PRACTICE - make sure you know how to operate your equipment (projector, screen, computers, mikes, lighting, etc.)
    16. +
    +

    How to make your presentation Memorable

    +

    Listeners can only remember 3 to 5 points.

    +
      +
    1. Preview the main points to have listeners anticipate them
    2. +
    3. Continuously tie the points to the structure of the presentation
    4. +
    5. Provide summaries as handouts if you have many details
    6. +
    7. At the end, review or reinforce the main points to provide closure
    8. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/intro_to_grant_proposal_writing_foundation_ctr/index.html b/docs/digests/intro_to_grant_proposal_writing_foundation_ctr/index.html new file mode 100644 index 00000000..c85196a4 --- /dev/null +++ b/docs/digests/intro_to_grant_proposal_writing_foundation_ctr/index.html @@ -0,0 +1,3628 @@ + + + + + + + + + + + + + + + + Intro To Grant Proposal Writing Foundation Ctr - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Intro To Grant Proposal Writing Foundation Ctr

    + +

    Introduction to Proposal Writing Video

    +
      +
    • Notes are from this video
    • +
    • Source: Foundation Center
    • +
    • Speaker:
    • +
    +

    The Proposal Writing Process

    +
      +
    1. Planning
        +
      • what do you need the money for?
      • +
      +
    2. +
    3. Research
        +
      • who will you approach
      • +
      +
    4. +
    5. Writing
        +
      • how you put it all together?
      • +
      +
    6. +
    7. Followup
        +
      • what you do once a decision has been made?
      • +
      +
    8. +
    +

    Planning

    +

    Do you have enough time?

    +

    Not a quick fix, 6-9 months between beginning proposal and receiving funds.

    +

    What are you asking for?

    +

    What kind of support: operations, project, building renovation, equipment.

    +

    Generating a Project Proposal is our focus today

    +

    Research

    +

    Finding the right fit.

    +
      +
    1. How does what you do fit with the funder's interests?
    2. +
    3. The why is just as important as the who
        +
      • Tell them how your project achieves their goals, mission, and priorities.
      • +
      • Through a combination of your program and their resources.
      • +
      +
    4. +
    +

    Writing the Proposal

    +

    Grantwriters are moving to online formats. Limited space and character restrictions.

    +

    Always follow the funder's guidelines.

    +

    Put together a master proposal or base proposal using the format we are about to go over.

    +

    There is a directory of common form grants on the Foundation Center Knowledge Base website.

    +

    Four Typical Proposal Elements

    +

    Executive Summary

    +

    How do I reduce everything to one page? Extract the key information from the full proposal (write the full proposal first).

    +

    They will look at this first to determine if they want to read the rest of the proposal. May not continue reading if they are not interested right away.

    +

    Also used to present your project to the foundation board for consideration.

    +

    This can be used for the letter of inquiry as well.

    +
    Includes:
    +
      +
    1. Statement of Need
    2. +
    3. Brief description project incl goals and objectives
    4. +
    5. Information about your objectives
    6. +
    7. How much money you are asking for
    8. +
    +

    Narrative

    +
    Statement of Need
    +
      +
    1. What specific need are you addressing?
        +
      • fits size and scale of your solution
      • +
      +
    2. +
    3. What audience and community are you serving?
    4. +
    5. What evidence do you have to support the need?
    6. +
    +
    Project Description
    +
      +
    1. What are you trying to achieve?
        +
      • Your outcomes must be measurable
      • +
      +
    2. +
    3. SMART Goals
        +
      • Specific
      • +
      • Measurable
      • +
      • Achievable
      • +
      • Realistic
      • +
      • Time-based
      • +
      +
    4. +
    5. What is your specific plan? Your proposal is your organizing plan.
        +
      • Who will do the work? Both paid and volunteer.
      • +
      • What?
      • +
      • When?
      • +
      • Where?
      • +
      • Why?
      • +
      • How?
      • +
      +
    6. +
    7. Evaluation: How do you know you are successful?
        +
      • Specify program objectives in measurable terms
      • +
      • Identify key indicators of success
      • +
      • Outline data collection and analysis activites
      • +
      • Develop a TIMELINE to monitor the success of the program on an ongoing basis
      • +
      • What you will do with your information
      • +
      +
    8. +
    9. TRACY - Tools and Reseources for Measuring Social Impact (or something like that, i may have mistyped)
    10. +
    11. Why are you the best organization to do this work?
    12. +
    +
    Organization
    +
    Information
    +
    Conclusion
    +

    Budget

    +

    Supporting Materials

    +

    Follow the funder's guidelines.

    +

    Include everything (and very little of anything else).

    +

    For online applications it's ok to add links where possible.

    +
      +
    • Organization's most recent audited financial statements
    • +
    • IRS Form 990
    • +
    • Current Operating Budget and last year's budget versus actual
    • +
    • List of board of director names and professional affiliation
    • +
    • Brief biographical information of key staffers
        +
      • People carrying out your project have sufficient knowledge and experience for success
      • +
      +
    • +
    +

    Other Stuff

    +
      +
    • Grant is the beginning of the relationship with your funder
        +
      • Regular reports, keep them informed!
      • +
      • Significant accomplishment? Send a note or make a phone call.
      • +
      • Having an event? Invite them as a courtesy no matter what, even if you know they cannot or will not go.
      • +
      +
    • +
    +

    Follow Up

    +
      +
    • It's not personal
    • +
    • Find out why
    • +
    • Ask about future funding
    • +
    • Don't just put them on your generic mailing list! Keep them up to date
    • +
    +

    Key Takeaways

    +
      +
    • Start with an outline
    • +
    • Keep the language clear and concise
    • +
    • Focus on the funders' interests
    • +
    • Follow the funders' guidelines
    • +
    • Revise and edit before submitting
    • +
    • Tell them a story
    • +
    • Avoid jargon and acronyms.
    • +
    +

    Additional Resources

    +

    Foundation Center Resources

    +
      +
    • Foundation Center Training
    • +
    • Proposal Writing Workshop - 1 day - In Person
    • +
    • Proposal Writing Bootcamp - 3 day - In Person
    • +
    • There is also an Intro to Writing Grants course.
    • +
    • There is also an Intro to Finding Grants course.
    • +
    • grantspace.org skill space
    • +
    • grantspace.org sample documents (yes sample proposals from funders, including comments as to why they got the grant)
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/learning-how-to-learn/chunking-practice/index.html b/docs/digests/learning-how-to-learn/chunking-practice/index.html new file mode 100644 index 00000000..ec9e7aef --- /dev/null +++ b/docs/digests/learning-how-to-learn/chunking-practice/index.html @@ -0,0 +1,3625 @@ + + + + + + + + + + + + + + + + Chunking Practice - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Chunking, Practice, and Recall

    +

    These notes are my reinterpretation of the material of week 2 (of 4 weeks) of the online course "Learning How to Learn" on Coursera by Dr. Barabra Oakley.

    +

    TODOs

    +

    There are a few in the document.

    +

    Important TODO: "Maintaining a Library of Chunks

    +

    Topics

    +
      +
    • What is a chunk?
    • +
    • How to form a chunk?
    • +
    • Pitfalls
    • +
    • Extending the analogy
    • +
    • A "Library of Chunks"
    • +
    • Additional context
    • +
    +

    What is a chunk?

    +

    Human brains have 4 slots of working memory, you can think of your reasoning as 4 armed octopus able to touch only 4 remembered items at a time.

    +

    A chunk is a collection of memories that form a concept. For example, the snick of a pop bottle opening connects to the word "pop" and the letters "p" "o" "p". One is a qualia, the other is a logical construction through written phoenetic glyphs. You can also sketch a can of pop as a visual qualia for this chunk.

    +

    A chunk can be very large or small. The course says a chunk is like compression but this anaology is flawed, because a chunk itself is more like a nexus of memories and reasonings.

    +

    A chunk is like a summary with hyperlinks to related chunks that might be larger or smaller in size or relationship. A chunk might be tightly related to some chunks and loosely related to other chunks.

    +

    "Conceptual chunk": Mental leap that unites scattered bits through memory.

    +
    +

    Trent: There is a concept of scattered bits of memory that are not worth detailing as their own chunk in your context of study. It may or may not be useful to focus in on any of these scattered bits as chunks themselves. For example, in the "pop" chunk, the letter "p" is a scattered bit, but it has its own chunk with a lot of context, like the vocalization of the letter, it's various forms, "P", 'p", its history through the history of language. But, you probably do not wish to develop that chunk when focusing on a different topic, e.g. the topic at hand, "learning what a chunk is".

    +
    +

    Every discipline is a little different for memories. Imagine: walking, doing a math problem, and telling a story.

    +

    Synthesizing a collection of chunks and creatively integrating two different chunks in a new context are related to the idea of "expertise".

    +

    Transfer: A chunk in one discipline might share commonalities with a chunk in a different discipline.

    +

    Trent's Thought Experiment about connecting unrelated chunks

    +

    This is kind of like mad libs.

    +

    Thought experiment: How are my grandmother's favorite shoes related to household accounting practices? I know my grandmother is good at accounting, and this starts to fire a lot of memories about how she learned these skills since she did not have much education. This road of obtuse reasoning is long. Thought experiments about unrelated chunks can yield interesting connections.

    +

    Expertise and Creative Integration

    +
    +

    Expertise is chunking and performing creative interpretations as you gain fluency.

    +
    +

    How to form a chunk?

    +

    Perform these steps when practicing or studying material.

    +

    1. "Undivided Attention"

    +
      +
    • Turn off all notifications
    • +
    • Any single interruption "uproots" some neural connections being made (weaker foundation)
    • +
    +

    2. "Understand"

    +
      +
    • Get the "main idea" or "gist": "top down learning"
    • +
    • "Superglue" the pieces together
    • +
    • "Broad traces" and "link to other traces you have"
        +
      • Finding links to other knowledge will stimulate dopamine reward
      • +
      +
    • +
    • Do a picture walk through a chapter before reading it
    • +
    +

    3. "Gain Context" - "deliberate practice", "recall", "review", "when to use the chunk"

    +
      +
    • Perform: "deliberate practice":
        +
      • Process: work on primarily difficult problems
          +
        • TODO: How do we identify "difficult problems" in each of the below contexts?
        • +
        +
      • +
      • problem sets (math, sciences, computer science, etc.)
      • +
      • practical experience (medicine, carpentry)
      • +
      • physical techniques (judo, dancing)
      • +
      • songs
      • +
      • foreign language conversations
      • +
      • ... (what else?)
      • +
      +
    • +
    • Perform: "recall"
        +
      • Process:
      • +
      • Remember everything you can with only your brain: simply use your mind, or use a blank docoument
      • +
      • Review your notes against the material, identifying gaps
      • +
      • Mediums:
      • +
      • Mind: Simply recall what you can, then recall what you can about each item
          +
        • Not easy to validate against the notes later, maybe has other benefits?
        • +
        +
      • +
      • Physical: Outline, Diagrams, Notes, Sketches, Paragraphs (paper or digital)
          +
        • Easy to validate your progress/success
        • +
        • Can create a more organized permanent reference
        • +
        +
      • +
      • Recall in a different place to decouple your access to a chunk from where you learned it
      • +
      • Generation Effect: "The generation effect is a phenomenon where information is better remembered if it is generated from one's own mind rather than simply read"
      • +
      • On the first recall, you will prime the generation effect, creating "neural hooks"
      • +
      • On the second recall, you will take advantage of the generation effect.
      • +
      • Wikipedia: Generation Effect
      • +
      • Trent: probably can do this 1x before needing to dip back into "diffuse mode" (workout, sleep, socialize)
      • +
      +
    • +
    • Perform: "review"
        +
      • Perform more "deliberate practice" and "recall" with previous related chunks.
      • +
      • New relationships with the old material and the new material will be stronger
      • +
      • Review the material both "forwards" and "backwards"
      • +
      +
    • +
    • Learn WHEN to use the "chunk"
        +
      • Analogy: when to use a hammer vs a mallet
      • +
      +
    • +
    • "Do a picture walk through a chapter before reading it"
        +
      • Know how the "pieces of the puzzle" fit together (knowledge inside the chunk)
      • +
      +
    • +
    +

    4. "Repair the Flaws"

    +
      +
    • Process: Identify your misunderstandings and repeat "deliberate proactice" with the right ideas
    • +
    • This is part of the same study methods above
    • +
    • It's important enough here to call out as a step
    • +
    +

    5. "Interleaving during Practice"

    +
      +
    • Mix up your learning within a subject or even between multiple subjects
    • +
    • Find other contexts that have this chunk or a similar chunk
        +
      • In a textbook, read through nearby problem sets to find other applications that contain the problem
      • +
      +
    • +
    • Trent: Time intensive? How to get a library of interleaved problems quickly?
    • +
    +

    Example: Learning a guitar song

    +

    I like this analogy because it is easy to "test" if the song sounds right.

    +
      +
    1. "Understand"
    2. +
    3. Listen to the song
    4. +
    5. "Practice"
    6. +
    7. Grasp bits of the song
    8. +
    9. Review chords and notes and be able to play them
    10. +
    11. Join passages until you know all the parts
    12. +
    13. Try the whole song
    14. +
    15. keep improving
    16. +
    +

    Pitfalls

    +
      +
    • Working memory doesn't work as well under stressors: low sleep, stress, sickness, etc.
    • +
    • Rereading material once you have context
    • +
    • Instead use "recall" then compare the material to your recall results
    • +
    • Research supports that this is a comparatively better method for learning
        +
      • Compared to some other methods: concept maps, notes, rereading
      • +
      • Probably still want to take notes, that's done during studying and can be used for recall comparison
      • +
      +
    • +
    • Overlearning
    • +
    • Repeating problems you already learned
    • +
    • Usually a waste of time, instead try to "cover a lot of ground"
        +
      • Instead: Once you get more context with more chunks, then repeat your old problems
      • +
      +
    • +
    • It is useful if you need "the perfect tennis serve"
    • +
    • Can be used positively to combat "text anxiety" but will cost time (tradeoff)
    • +
    • Overtraining for perfect public speaking: "A 20 minute TED Talk can take 70 hours of practice"
    • +
    • Einstellung
    • +
    • Stuck in a way of "focused mode" thinking you already have
    • +
    • Try taking a break, go into "diffuse mode" and reapproach the problem fresh later
    • +
    +

    A "Library of Chunks"

    +
      +
    • To develop expertise in a discipline, build two things:
    • +
    • "a bigger chunk library"
    • +
    • "a more well-practiced chunk library".
    • +
    +

    Extending the analogy

    +

    Consider a chunk as a ribbon of learning. The ribbon will grow wider and longer as you improve at making chunks. +You might listen to the "whispers of the diffuse mode" that will forge a new connection between two distance places on the ribbon.

    +

    Problem: Too much ground to cover!

    +

    There are so many chunks in a discipline, how will you get to them all?

    +

    "Law of Serendipity": Lady luck favors the one who tries.

    +

    Solution: As you form a chunk, nearby chunks will be easier to form. A bigger "library of chunks" will naturally grow.

    +

    But you must practice each chunk to make it "wider" which will make later practice cover more ground. Later practice will not get easier, but it will cover more ground at the same difficulty.

    +

    Practicing related chunks will help you begin to classify "types of chunks" and "classes of concepts". I think these are probably also considred chunks. If you are well studied, you are probably already familiar with a library of "types of problems".

    +

    TODO: Maintaining your "Library of Chunks"

    +

    How can I stay in practice? I might have a group of chunks that I want to have front-of-mind.

    +

    One shortcut would be to carefully maintain the library of problems I used to develop that chunk and periodically repeat solving those problems.

    +

    Other parts of the founding material of chunks: primary readings, primary practices, related problems, related readings.

    +

    How would a graph representation work for managing the inputs to developing a group of related chunks representing a discipline?

    +

    Additional context

    +
      +
    • "Sequential Reasoning" are focused mode reasonings
    • +
    • "Holistic Intution" are diffuse mode ideas
    • +
    • You MUST carefully verify "holistic intuition" with "sequential reasoning"
    • +
    +
    +

    Trent: Even modern physics has 2 incompatible models, I have enocuntered many people that try to use deductive logic on their mental models. Mental models are generally not sufficient to form a closed system. Deductive reasoning needs to be backed up with inductive facts if possible, otherwise it is generally too leaky and insufficient, especially in highly technical black box systems.

    +
    +

    Neurochemistry

    +
      +
    • acetylcholine
    • +
    • form new long term memory, synaptic plasticity, "projects widely"
    • +
    • TODO Question: Does this mean this chemical helps form broader connections between topics?
    • +
    • dopamine
    • +
    • decision making, which sensory input your brain values (perception),
    • +
    • released after unexpected reward (unexpected connection between two topics (chunk linking)
    • +
    • serotonin
    • +
    • risk taking, depression, loneliness, low perceived social rank causes high risk taking
    • +
    • prozac is a prescription to increase serotonin
    • +
    +

    Neurochemistry: how to control it for "higher quality learning"

    +
      +
    • basic shared controls:
    • +
    • sleep
    • +
    • nutrition
    • +
    • exercise
    • +
    • acetylcholine
    • +
    • TODO ??
    • +
    • dopamine
    • +
    • "understand" connections to existing knowledge to release dopamine
    • +
    • Celebrate: reward yourself after learning - releases dopamine
        +
      • mental pat on the back
      • +
      • vocalized verbal celebration "Yeah!"
      • +
      +
    • +
    • serotonin
    • +
    • maintain a healthy social structure that fits your needs
    • +
    • focus on mental wellness and mental health
        +
      • therapy, medicine, sleep, exercise, nutrition
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/index.html b/docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/index.html new file mode 100644 index 00000000..9c6c72b0 --- /dev/null +++ b/docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/index.html @@ -0,0 +1,3478 @@ + + + + + + + + + + + + + + + + Old Reviseme Learning How To Learn Coursera - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Learning How to Learn

    +

    Learn the basics of how the brain works to learn more easily and be less frustrated.

    +

    The course has 4 modules over 4 weeks.

    +

    Information

    +
      +
    • Source: coursera.org
    • +
    • Speaker: Barbara Oakley, Terrence Sejnowski
    • +
    • Basis: "A Mind for Numbers" by Barbara Oakley
        +
      • the book formed the basis for this MOOC
      • +
      • audible audio or paper/ebook
      • +
      +
    • +
    +

    Course Videos

    +

    You'll gain insight into how we learn by using a variety of different approaches, ranging from personal stories, to insights from cognitive psychology, to an examination of deep neuroscience.

    +

    Course Activities

    +
      +
    • In-video Quizzes
    • +
    • Graded Quiz in each Module
    • +
    • Peer-evaluated assignments (optional)
    • +
    +

    Course Objectives

    +

    By the end of the course, we expect you to be able to do the following:

    +
      +
    • Explain the difference between focused and diffuse modes of thinking.
    • +
    • Explain what a chunk is, and how and why you can and should enhance your chunking skills.
    • +
    • Explain how working memory and long term memory differ from one another.
    • +
    • Describe key techniques to help students learn most efficiently such as:
        +
      • the Pomodoro
      • +
      • metaphor
      • +
      • story
      • +
      • visualization
      • +
      • deliberate practice
      • +
      • interleaving
      • +
      +
    • +
    • Describe actions that hinder students from learning most effectively, such as:
        +
      • procrastination
      • +
      • over-learning
      • +
      • Einstellung
      • +
      • choking
      • +
      • multi-tasking
      • +
      • illusions of learning
      • +
      • lack of sleep
      • +
      +
    • +
    • Describe the most important aspects of proper test preparation.
    • +
    • Explain the importance of “mindset” in learning.
    • +
    +

    Video 1: Introduction to the Focused and Diffuse modes

    +

    There are 4 papers referenced at the end of this video.

    +

    Two Different Modes of Thinking.

    +

    The focused and diffuse modes of thinking are fundamentally different.

    +
      +
    1. Focused Mode of Thinking
        +
      • Focusing: concentrate intently on what you are trying to understand
      • +
      +
    2. +
    3. Diffuse Mode of Thinking
        +
      • Relaxed: related to a set of neural resting states
      • +
      +
    4. +
    +

    Metaphor and analogy are very helpful when learning something new.

    +

    Analogy: Pinball Game

    +

    Think of the brain as an array of pinball bumpers.

    +

    The focused mode has mamy, tightly packed bumpers. The diffuse mode has fewer, broadly spaced bumpers.

    +

    The path of a ball between a number of bumpers is a familiar way of thinking.

    +

    If you haven't thought a thought before, how will you know the path of the ball? How will you get the ball to the new thought pattern?

    +

    As far as neural scientists know right now, you are either in focused or diffuse mode of thinking. You can see one side of the coin, or the other, but not both at the same time. Being in one mode limits your access to the other mode of thinking.

    +

    Video 2: Introduction to the Course Structure

    +

    Goal: Reframe how you think about learning.

    +

    The course is especially useful for learning math and science.

    +

    Experts from many professions who give tips about learning.

    +

    You will see how you can fool yourself about whether you actually know the material.

    +

    Discover new ways to hold your focus and embed the material more deeply and powerfully in your mind.

    +

    Condense key ideas you are learning about so you can grasp them more easily.

    +

    Master the simple approaches outlined here, including simple tips to help prevent procrastination, and you'll be able to learn more effectively and with less frustration.

    +

    Video 3: sing the Focused and Diffuse Modes--Or, a Little Dali will do You

    +

    Your mind needs to go back and forth between the two learning modes, that's what makes you learn effectively.

    +

    Analogy: Lifting weights. You can't work out like a fiend the day before a weightlifting competition. Neural structure is like a muscle, gradually grow a neural scaffold to hang your thinking on.

    +

    Learning something difficult takes time.

    +

    Salvador Dali - the very definition of "a wild and crazy guy"

    +

    Thomas Edison - One of the most brilliant inventors ever

    +

    Dali's technique

    +
      +
    • Relax in a chair and let his mind go free.
    • +
    • Dangle a key in his hand just above the floor.
    • +
    • And just as he drifted into his dreams, falling asleep he would drop the key, waking himself up.
    • +
    • Just in time to gather the diffuse mode connections and ideas in his mind
    • +
    • And back he would go into the focused mode, bringing with him the new connections he made in the diffuse mode
    • +
    +

    Edison Technique

    +

    According to legend...

    +
      +
    • Relax in his chair, holding ball-bearings in his hand
    • +
    • His mind would run free and noodle back in a relaxed way to what he would focus on
    • +
    • The ball bearings drop and clatter to the ground - same as Dali
    • +
    • He is awakened! Off he would go with his ideas in the diffuse mode, ready to build on them in the focused mode
    • +
    +

    Week 1: What is Learning?

    +

    Some Context

    +
      +
    • Brain weighs 3 lbs. Consumes 10x more energy by weight than rest of body.
    • +
    • Most complex device in the known universe.
    • +
    • We are not consciously aware of how our brains work. Brains evolved to help us navigate complex environments. Most of heavy lifting is below consciousness.
    • +
    • Surprised to find out that running, reaching, seeing, hearing are much more complex problems than we thought (than chess and math) and still out of the reach of raw computer processing.
    • +
    • Much of heavy lifting below the level of consciousness and we don't need to know how it's done to survive
    • +
    • We are only aware of a tiny fraction of events in the mind
    • +
    • There are areas of the brain that are active during focused states, and other areas of the brain that are active during resting states.
    • +
    • Brain connectivity is dynamic and remains so even after it matures. New synapses form and others disappear.
    • +
    • How do memories remain stable over so many years?
    • +
    • Viewing a dendritic branch on a neuron. After learning and sleep the dendrite has new synapses.
    • +
    • Synapses < 1 micron diameter; human hair is 20 microns diameter. Near the limit of light microscopy.
    • +
    • You are not the same person you were after a nap or night sleep. Upgrade!
    • +
    • Shakespeare: Macbeth laments insomnia, sleep knits up your experiences into the tapestry of your life story.
    • +
    • Check out www.brainfacts.org.
    • +
    • There are a million billion synapses in the brain.
    • +
    +

    There are references at the end of the video.

    +

    Introductory Quiz Notes

    +
      +
    1. There is a coursera mobile app...
    2. +
    +

    10,000

    +

    Video: A procrastination Preview

    +

    Trent on 10+10 Rules of Studying

    +
      +
    1. Recalling what you just read is a validation test. You can verify the work product of your reading. The work product is that you learned the material.
    2. +
    3. Another major plug for flashcards and spaced repetition. Maybe I should just keep a paper system of mixed flashcards that I can rebase as neeed. Electronic ones are not working.
    4. +
    5. Use outside resources early and often. Identify helpful people and don't waste your time on people that aren't successful at teaching you.
    6. +
    7. Airplane Mode: Every text message pulls up the roots of your attempt to learn.
    8. +
    9. Sleep is the foundation of learning and survival.
    10. +
    +

    10 Rules of Studying

    +

    These rules form a synthesis of some of the main ideas of the course--they are excerpted from the book A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014. Feel free to copy these rules and redistribute them, as long as you keep the original wording and this citation.

    +

    10 Rules of Good Studying

    +
      +
    1. Use recall. After you read a page, look away and recall the main ideas. Highlight very little, and never highlight anything you haven’t put in your mind first by recalling. Try recalling main ideas when you are walking to class or in a different room from where you originally learned it. An ability to recall—to generate the ideas from inside yourself—is one of the key indicators of good learning.
    2. +
    3. Test yourself. On everything. All the time. Flash cards are your friend.
    4. +
    5. Chunk your problems. Chunking is understanding and practicing with a problem solution so that it can all come to mind in a flash. After you solve a problem, rehearse it. Make sure you can solve it cold—every step. Pretend it’s a song and learn to play it over and over again in your mind, so the information combines into one smooth chunk you can pull up whenever you want.
    6. +
    7. Space your repetition. Spread out your learning in any subject a little every day, just like an athlete. Your brain is like a muscle—it can handle only a limited amount of exercise on one subject at a time.
    8. +
    9. Alternate different problem-solving techniques during your practice. Never practice too long at any one session using only one problem-solving technique—after a while, you are just mimicking what you did on the previous problem. Mix it up and work on different types of problems. This teaches you both how and when to use a technique. (Books generally are not set up this way, so you’ll need to do this on your own.) After every assignment and test, go over your errors, make sure you understand why you made them, and then rework your solutions. To study most effectively, handwrite (don’t type) a problem on one side of a flash card and the solution on the other. (Handwriting builds stronger neural structures in memory than typing.) You might also photograph the card if you want to load it into a study app on your smartphone. Quiz yourself randomly on different types of problems. Another way to do this is to randomly flip through your book, pick out a problem, and see whether you can solve it cold.
    10. +
    11. Take breaks. It is common to be unable to solve problems or figure out concepts in math or science the first time you encounter them. This is why a little study every day is much better than a lot of studying all at once. When you get frustrated with a math or science problem, take a break so that another part of your mind can take over and work in the background.
    12. +
    13. Use explanatory questioning and simple analogies. Whenever you are struggling with a concept, think to yourself, How can I explain this so that a ten-year-old could understand it? Using an analogy really helps, like saying that the flow of electricity is like the flow of water. Don’t just think your explanation—say it out loud or put it in writing. The additional effort of speaking and writing allows you to more deeply encode (that is, convert into neural memory structures) what you are learning.
    14. +
    15. Focus. Turn off all interrupting beeps and alarms on your phone and computer, and then turn on a timer for twenty-five minutes. Focus intently for those twenty-five minutes and try to work as diligently as you can. After the timer goes off, give yourself a small, fun reward. A few of these sessions in a day can really move your studies forward. Try to set up times and places where studying—not glancing at your computer or phone—is just something you naturally do.
    16. +
    17. Eat your frogs first. Do the hardest thing earliest in the day, when you are fresh.
    18. +
    19. Make a mental contrast. Imagine where you’ve come from and contrast that with the dream of where your studies will take you. Post a picture or words in your workspace to remind you of your dream. Look at that when you find your motivation lagging. This work will pay off both for you and those you love!
    20. +
    +

    10 Rules of Bad Studying

    +

    Excerpted from A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014

    +

    Avoid these techniques—they can waste your time even while they fool you into thinking you’re learning!

    +
      +
    1. Passive rereading—sitting passively and running your eyes back over a page. Unless you can prove that the material is moving into your brain by recalling the main ideas without looking at the page, rereading is a waste of time.
    2. +
    3. Letting highlights overwhelm you. Highlighting your text can fool your mind into thinking you are putting something in your brain, when all you’re really doing is moving your hand. A little highlighting here and there is okay—sometimes it can be helpful in flagging important points. But if you are using highlighting as a memory tool, make sure that what you mark is also going into your brain.
    4. +
    5. Merely glancing at a problem’s solution and thinking you know how to do it. This is one of the worst errors students make while studying. You need to be able to solve a problem step-by-step, without looking at the solution.
    6. +
    7. Waiting until the last minute to study. Would you cram at the last minute if you were practicing for a track meet? Your brain is like a muscle—it can handle only a limited amount of exercise on one subject at a time.
    8. +
    9. Repeatedly solving problems of the same type that you already know how to solve. If you just sit around solving similar problems during your practice, you’re not actually preparing for a test—it’s like preparing for a big basketball game by just practicing your dribbling.
    10. +
    11. Letting study sessions with friends turn into chat sessions. Checking your problem solving with friends, and quizzing one another on what you know, can make learning more enjoyable, expose flaws in your thinking, and deepen your learning. But if your joint study sessions turn to fun before the work is done, you’re wasting your time and should find another study group.
    12. +
    13. Neglecting to read the textbook before you start working problems. Would you dive into a pool before you knew how to swim? The textbook is your swimming instructor—it guides you toward the answers. You will flounder and waste your time if you don’t bother to read it. Before you begin to read, however, take a quick glance over the chapter or section to get a sense of what it’s about.
    14. +
    15. Not checking with your instructors or classmates to clear up points of confusion. Professors are used to lost students coming in for guidance—it’s our job to help you. The students we worry about are the ones who don’t come in. Don’t be one of those students.
    16. +
    17. Thinking you can learn deeply when you are being constantly distracted. Every tiny pull toward an instant message or conversation means you have less brain power to devote to learning. Every tug of interrupted attention pulls out tiny neural roots before they can grow.
    18. +
    19. Not getting enough sleep. Your brain pieces together problem-solving techniques when you sleep, and it also practices and repeats whatever you put in mind before you go to sleep. Prolonged fatigue allows toxins to build up in the brain that disrupt the neural connections you need to think quickly and well. If you don’t get a good sleep before a test, NOTHING ELSE YOU HAVE DONE WILL MATTER.
    20. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/learning-how-to-learn/procrastination-IMPORTANT/index.html b/docs/digests/learning-how-to-learn/procrastination-IMPORTANT/index.html new file mode 100644 index 00000000..2bacbd7b --- /dev/null +++ b/docs/digests/learning-how-to-learn/procrastination-IMPORTANT/index.html @@ -0,0 +1,3516 @@ + + + + + + + + + + + + + + + + Procrastination Important - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    + +
    + + + +
    +
    + + + + + + + + + +

    Week 3: Procrastination & Memory

    +

    This is very active time hacking. To do this, write out your plan thoughtfully.

    +
      +
    • Strategies for managing procrastination without spending willpower
    • +
    • Use mental tools and tricks to inspire and motivate yourself
    • +
    +

    Procrastination

    +
      +
    • These strategies are more important than you think
    • +
    • Understand psychology of procrastination
    • +
    • Good learning is a "brick by brick" activity
        +
      • Procrastination is the #1 blocker
      • +
      +
    • +
    +

    Why not use Willpower

    +
      +
    • Hard to come by
    • +
    • Uses lots of mental resources
    • +
    • Don't need to waste on procrastination
    • +
    +

    Why procrastination?

    +
      +
    • Unhappy feeling lights up pain centers of the brain..
    • +
    • Avoidance makes you feel better temporarily
    • +
    • Shares features with addiction
        +
      • Temporary relief from reality e.g. surfing the web
      • +
      +
    • +
    • telling yourself false stories:
        +
      • i don't have good spacial reasoning
      • +
      • if i study too far ahead i will forget the material
      • +
      • belief that procrastination is "an innate characteristic"
      • +
      +
    • +
    + +
      +
    • Habit allows us to free our mind for other things
        +
      • Zombie mode so we can focus on other things
      • +
      +
    • +
    • Habits can be brief or long
    • +
    +

    4 Parts of a habit

    +

    Neither helpful or harmful innately.

    +

    Engineer the cue and reward. Update the belief on a plan. The routine will fall away

    +
      +
    1. The Cue
        +
      • Seeing a todo list item, time to do some tasks
      • +
      • Seeing a text message from a friend, time to stop work
      • +
      +
    2. +
    3. The Routine
        +
      • picking up your phone to read the news after waking up
      • +
      • zombie responses
      • +
      +
    4. +
    5. The Reward
        +
      • Find a way to reward yourself for good habits
      • +
      • Find a way to remove the reward for bad habits
      • +
      • Procrastination: Moving your mind's focus to something more pleasant
          +
        • The reward is quick and easy
        • +
        +
      • +
      +
    6. +
    7. The Belief
        +
      • Habits have power because of your belief in them
      • +
      • To change a habit, change your underlying belief
      • +
      +
    8. +
    +

    Build a habit: focus on process

    +
      +
    • To build a habit: Focus on process, not product
        +
      • product is "outcome"
      • +
      +
    • +
    • Easiest way is to do a pomodoro
        +
      • Mind can march mindlessly along
      • +
      +
    • +
    +

    Tips

    +
      +
    • use a quiet space or noise cancelling headphones
    • +
    • Usually you will have some negative feelings about beginning a learning session
        +
      • Non procrastinators use "self talk" to get past the negative feelings and get started: "just get on with it"
      • +
      +
    • +
    • Focus on process, not product: "I'm going to spend 20 minutes working"
    • +
    • Product is an outcome: "I'm going to finish my homework."
    • +
    +

    Overwriting An Old Habit

    +

    Change your reaction to a specific "cue".

    +

    The only place to apply willpower is changing your reaction to a "cue".

    +

    The Cue (4 kinds)

    +

    Action: "Recognize" what launches you into zombie procrastination mode.

    +
      +
    1. Location
    2. +
    3. Time
    4. +
    5. How you feel
    6. +
    7. Reactions
    8. +
    +

    The Routine

    +

    Action: "Engineer the routine". This is the reaction point where you must actively focus on rewiring your old habit.

    +

    Write a plan for the routine. It may not work perfectly. Adjust as necessary and celebrate the victories when your plan works.

    +
      +
    • Put your cellphone in an unreachable place
    • +
    • Use the pomodoro technique
    • +
    +

    Reward

    +
      +
    • +

      Investigate what is happening.

      +
        +
      • Why are you procrastinating?
      • +
      • Can you substitute an emotional payoff? A feeling of pride or satisfaction?
      • +
      • Can you win a small internal bet or contest?
      • +
      • Indulge in a latte or read a favorite website
      • +
      • Watch TV or read on the web without guilt for an evening
      • +
      • Go out for a movie, buy a sweater or other frivolous purchase
      • +
      • A reward can overcome previous cravings
      • +
      • Your brain will rewire when it begins to "EXPECT THE REWARD"
      • +
      +
    • +
    • +

      Tips

      +
        +
      • Stopping at 5 PM gives a mini deadline that spurs work
          +
        • Stopping is a nice reward and ties into focus on process
        • +
        +
      • +
      • It takes a few days of drudgery before flow starts to take hold
      • +
      • The better you get, the
      • +
      +
    • +
    +

    Belief

    +
      +
    • When the going gets stressful you long to fall into old, comforatable habits
    • +
    • Belief that your system works will get you through
    • +
    • Develop a new community
        +
      • Virtually hang out with MOOC classmates
      • +
      +
    • +
    +

    Juggling Life & Learning

    +

    This lecture is a bit scattered, break it out into a nice diagram or outline.

    +
      +
    • Once a week, write a weekly list of key tasks
    • +
    • On each day write a list you can reasonably work on or accomplish
        +
      • Otherwise they take up space on the edge of your working memory
      • +
      +
    • +
    • Action: Daily task list the evening before
        +
      • This helps your diffuse mode to grapple with tasks to figure out how to accomplish them
      • +
      +
    • +
    • Most items are process oriented
    • +
    • Only a few items are product oriented because they are very well quantified
    • +
    • Sidetracked by email
        +
      • switch to pomodoro, a process orientation
      • +
      • 22 minute pomodoro I don't have to do the same thing every time
      • +
      +
    • +
    • Mixing up tasks keeps things fun and prevents unhealthy bouts of sitting
    • +
    • Since I practice, I am good at gauging what I can do in a reasonable period
    • +
    • Goal finish time for the day - 5 PM
        +
      • Planning quitting time is as important as planning working time
      • +
      • Sometimes review your major work right before you sleep, diffuse mode working
      • +
      • Maintaining healthy leisure time will improve your work
      • +
      • No matter how busy your life is, you do need a bit of break
      • +
      +
    • +
    • Eat your frogs first in the morning
        +
      • Action: Most disliked (and important) task, at least 1 pomodoro right when you start working
      • +
      +
    • +
    +

    Summary: Procrastination

    +
      +
    • Learning is brick by brick, so procrastination stops this from happening
    • +
    • Tackling procrastination is incredibly important
    • +
    • Keep a planner journal so you easily track when you reach your goals
        +
      • Observe what does and does not work
      • +
      +
    • +
    • Commit to certain routines and tasks every day
        +
      • Write your planned tasks out the night before so you can dwell on your goals
      • +
      +
    • +
    • Arrange work into a series of small challenges
    • +
    • Make sure you and "your zombies" get lots of rewards
    • +
    • Take a few minutes to savor feelings of happiness and triumph, brain temporarily changes modes
    • +
    • Delay rewards until you finish a task
    • +
    • Try surroundings with few procrastination cues
    • +
    • Relax without guilt or worry
    • +
    • Have backup plans for when you still procrastinate, no one is perfect
    • +
    • Eat your frogs first every day
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/meditations_Marcus_Aurelius/index.html b/docs/digests/meditations_Marcus_Aurelius/index.html new file mode 100644 index 00000000..a5278df5 --- /dev/null +++ b/docs/digests/meditations_Marcus_Aurelius/index.html @@ -0,0 +1,3133 @@ + + + + + + + + + + + + + + + + Meditations Marcus Aurelius - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Meditations - Marcus Aurelius

    +

    Some things that stood out to me

    +

    Book 1

    +

    He gives a lot of things he has lived by

    +
      +
    • Spend liberally on private trainings at home
    • +
    • Work with your own hands
    • +
    • Be happy with a plank bed and hide covering and whatever goes with a greek discipline
    • +
    • Write letters in a simple style
    • +
    • If someone offends you, be easily disposed to be pacified and reconciled as soon as they have shown a readiness to be reconciled
    • +
    • from appolonious
        +
      • I learnt freedom of will and undeviating steadiness of purpose, and to take no other viewpoint, even for a moment, but that of reason
      • +
      • to see clearly (trent: a.k.a. "to reason") on all occasions whether it be extreme pain, the loss of a child, or long illness
      • +
      • be most resolute and yielding
      • +
      • receive favors without letting them go unnoticed or being put in an awkward position
      • +
      +
    • +
    • correct people's language later by example without bringing specific attention to their mistake
    • +
    • never say to anyone "that you have no time" or allege "you have urgent business to attend to"
    • +
    • thankful that he did not fall into the hands of sophists when he became interested in philosophy, waste his time on observing the movements of the heavens, literature, and intellectual puzzles, "for all these things require the help of the gods and fortune"
    • +
    +

    Book 2 (chapter 5)

    +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/rules_for_radicals_1971/index.html b/docs/digests/rules_for_radicals_1971/index.html new file mode 100644 index 00000000..9063b678 --- /dev/null +++ b/docs/digests/rules_for_radicals_1971/index.html @@ -0,0 +1,3713 @@ + + + + + + + + + + + + + + + + Rules For Radicals 1971 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Rules For Radicals - 1971

    +

    Author: Saul Alinksy

    +

    Safety Note

    +

    Do not store or supply unsafe materials for Anything Illegal, especially for "People You Trust".

    +

    In 2012-2017, the FBI has repeatedly radicalized left-wing organizations to cross strict legal barriers in perceived assistance of domestic terrorism.

    +

    If an agent knocks, federal investigators and your rights

    +
    +

    Today, the FBI may begin a full investigation whenever there is a reasonable indication that "two or more persons are engaged in an enterprise for the purpose of furthering political or social goals wholly or in part through activities that involve force or violence and a violation of the criminal laws of the United States." The FBI has interpreted "force or violence" to include the destruction of property as a symbolic act, and the mere advocacy of such property destruction would trigger an investigation. Even without any reasonable indication, under a separate guideline on "Civil Disorders and Demonstrations Involving a Federal Interest," the FBI may investigate an organization that plans only legal and peaceful demonstrations.

    +

    Another set of rules governing federal intelligence gathering is Executive Order 12333, in force since 1981. It authorizes the FBI and CIA to infiltrate, manipulate and destroy U.S.political organizations, as well as to use electronic surveillance -- under the pretext of an international intelligence investigation.

    +
    +

    Here is a half baked guide about what infiltrators might do.

    +
    +

    Also in Texas, a left-wing group was infiltrated by an FBI informant who insisted that the group become violent in response to the Republican scourge. Once he convinced members to make Molotov cocktails, the FBI stormed in and made arrests.

    +

    Lastly, the FBI infiltrated middle-aged peace activists and filed trumped-up charges of them providing “assistance” to terrorists. The bogus charges were eventually dropped.

    +
    +

    The FBI has also infiltrated Oil Pipeline Protestors using legal loopholes.

    +

    Dictionary

    +

    The book is dated in some political terminology. See the below list for clarifications.

    +
      +
    • radical means activist in 2017
    • +
    • revolution means political revolution in 2017
        +
      • Although, Alinsky doesn't make this strict distinction between whether violence is actually used.
      • +
      +
    • +
    • reformation means reorganization of values or priorities for your political base
    • +
    +

    General Notes

    +

    Wikipedia offers a summary of the rules:

    +
      +
    1. “Power is not only what you have, but what the enemy thinks you have.” Power is derived from 2 main sources – money and people. “Have-Nots” must build power from flesh and blood.
    2. +
    3. “Never go outside the expertise of your people.” It results in confusion, fear and retreat. Feeling secure adds to the backbone of anyone.
    4. +
    5. “Whenever possible, go outside the expertise of the enemy.” Look for ways to increase insecurity, anxiety and uncertainty.
    6. +
    7. “Make the enemy live up to its own book of rules.” If the rule is that every letter gets a reply, send 30,000 letters. You can kill them with this because no one can possibly obey all of their own rules.
    8. +
    9. “Ridicule is man’s most potent weapon.” There is no defense. It’s irrational. It’s infuriating. It also works as a key pressure point to force the enemy into concessions.
    10. +
    11. “A good tactic is one your people enjoy.” They’ll keep doing it without urging and come back to do more. They’re doing their thing, and will even suggest better ones.
    12. +
    13. “A tactic that drags on too long becomes a drag.” Don’t become old news.
    14. +
    15. “Keep the pressure on. Never let up.” Keep trying new things to keep the opposition off balance. As the opposition masters one approach, hit them from the flank with something new.
    16. +
    17. “The threat is usually more terrifying than the thing itself.” Imagination and ego can dream up many more consequences than any activist.
    18. +
    19. "The major premise for tactics is the development of operations that will maintain a constant pressure upon the opposition." It is this unceasing pressure that results in the reactions from the opposition that are essential for the success of the campaign.
    20. +
    21. “If you push a negative hard enough, it will push through and become a positive.” Violence from the other side can win the public to your side because the public sympathizes with the underdog.
    22. +
    23. “The price of a successful attack is a constructive alternative.” Never let the enemy score points because you’re caught without a solution to the problem.
    24. +
    25. “Pick the target, freeze it, personalize it, and polarize it.” Cut off the support network and isolate the target from sympathy. Go after people and not institutions; people hurt faster than institutions.
    26. +
    +

    Rules for Radicals Notes

    +

    Taken while reading the book.

    +

    Prologue

    +

    McCarthy Era

    +
    +

    "Few [radicals] survived the Joe McCarthy Holocaust of the 1950s and of those there were even fewer whose understanding and insights had developed beyond the dialectical materialism of orthodox Marxism. My fellow radicals who were supposed to pass on the torch of experience and insights to the new generation just were not there. As the young looked around at society around them, it was all, in their words, 'materialistic, decadent, bourgeois in its values, bankrupt, and violent.' Is it any wonder that they rejected us in toto." (p. xiii)

    +
    +
      +
    • Reader note: McCarthyism is seen now as a reactionary backlash to issues as far ranging as women's suffrage, child labor laws, and gay rights, as well as a means for certain politicians to use fear to keep power. The FBI is also implicated heavily in performing illegal spying. There are loophopes for domestic spying used by the FBI today.
    • +
    +

    Young vs. Old

    +
      +
    • Young people have seen 'activist democracies' turn into 'nihilistic bombing and murder' and there is no panacea for it as there was in the past, 'revolution in Russia and China has since become the same old stuff under a different name'.
    • +
    • Young people are looking for a way of life that has some meaning or sense: religion, political philosophy, science, or ideologies.
    • +
    • The small world of the past inspired trust, and the big world of today inspires confusion and incomprehensibility.
    • +
    • Generation Gap - Older people think younger people haven't learned how the world is, younger people think the old people will never get with the changing times.
    • +
    • Approaches to the chaotic world by the young:
        +
      1. Panic and run - "copping out"
          +
        • Hippies and Yuppies
        • +
        • Taking drugs
        • +
        • Trying communes
        • +
        • Anything to escape
        • +
        +
      2. +
      3. Sure-loser confrontations: "We tried and did our part"
          +
        • Dying
        • +
        • Jail
        • +
        • Followed by panic and run, "copping out"
        • +
        +
      4. +
      5. Guilt and "not knowing where to turn to"
          +
        • Suicide
        • +
        • Contempt
        • +
        • "take off for Algeria"
        • +
        +
      6. +
      +
    • +
    • There are no rules for revolution as there are for revelation.
    • +
    +

    There are no rules for revolution but there are rules for radicals.

    +
    +

    "Remember we are talking about revolution, not revelation; you can miss the target by shooting too high as well as too low. First, there are no rules for revolution any more than there are rules for love or rules for happiness, but there are rules for radicals who want to change their world; there are central concepts of action in human politics that operate regardless of the scene or the time. To know these is basic to a pragmatic attack on the system. These rules make the difference between a realistic radical and being a rhetorical one who uses the tired old words and slogans, calls the police 'pig' or 'white fascist racist' or 'motherfucker' and has so stereotyped himself that others react by saying, 'oh, he's one of those,' and then promptly turn off." (p. xviii)

    +
    +

    Communication

    +
    +

    Throughout history, silence has been regarded as assent -- in this case, assent to the system.

    +
    +

    If you cannot communicate in a way that your audience listens to you, you are silent no matter how loudly you scream. The inference here is that if you are not accepted in the community you wish to change, you are assenting to the system by not truly seeking a path to change that brings the community with you.

    +
      +
    1. Communicate within the experience of your audience
        +
      • Pay full respect to its values
      • +
      • A fool attacks the American flag: it is the establishment which has betrayed the flag while the flag, itself, remains the glorious symbol of America's hopes and aspirations
      • +
      +
    2. +
    3. Humor and comedy are essential
        +
      • Through humor much is accepted that would be rejected if presented seriously.
      • +
      • Note: People want to laugh and find joy in whatever they do. It inspires growth more than anything.
      • +
      +
    4. +
    5. Radicalism is social
        +
      • Do it for, and with, people
      • +
      +
    6. +
    7. If the real radical finds that having long hair sets up psychological barriers to communication and organization, he cuts his hair.
        +
      • Start your battle where the world is, not where you would like it to be.
      • +
      • Work inside the system
      • +
      +
    8. +
    +
    +

    Dostoyevsky said that taking a new step is what people fear the most. Any revolutionary change must be preceded by a passive, affirmative, non-challenging attitude toward change among the mass of our people. They must feel so frustrated, so defeated, so lost, so futureless in the prevailing system that they are willing to let go of the past and chance the future. That acceptance is the reformation essential to any revolution. To bring on this reformation requires that the organizer work inside the system, among not only the middle class but the 40 percent of American families... whose income ranges from $5000 to$10000 a year [in 1971 dollars]... IF we fail to communicate with them... they will move to the right... maybe they will anyways, but lets not let it happen by default. (p. xix)

    +
    +

    Non-Violence

    +

    Violence is absurd when the other side has all the guns.

    +
    +

    Just one violent incident like has happened in the US would have resulted in a sweeping purge and mass executions in Russia, China, or Cuba. Lets keep some perspective. (paraphrased)

    +
    +

    Remember that we have the freedom to fight with our words and to build an opposition base against the administration.

    +

    Start with the system

    +

    There is no other place to start.

    +
      +
    1. Revolution is precededed by Reformation
        +
      • Also called popular reformation of your opposition political base
      • +
      +
    2. +
    3. People need a bridge to cross from their own experience to a new way
        +
      • Shake up the patterns of their lives
      • +
      • Agitate
      • +
      • Create Disenchantment
      • +
      • Discontent with current values
      • +
      +
    4. +
    5. Goal: Produce a passive, affirmative, non-challenging climate or a passion for change in the political base.
        +
      • Revolution without prior reformation will collapse or become totalitarian tyranny.
      • +
      • Reformation - People are fed up with past ways. They don't know what will work but they know that the present system is hopeless. They won't act for change but won't strongly oppose those who do. Then the time is ripe for revolution.
      • +
      +
    6. +
    +

    Participation

    +
    +

    Citizen participation is the animating spirit and force in a society predicated on voluntarism.

    +

    We are not here concerned with people who profess the democratic faith but yearn for the dark security of dependency where they can be spared the burden of decisions.

    +

    To lose your "identity" as a citizen of democracy is but a step from losing your identity as a person. People react to this frustration by not acting at all.

    +

    Hang on to one of the most precious parts of youth, laughter... (p. xxvii)

    +
    +

    Chapter 1 - The Purpose

    +

    "The Prince" by Machiavelli is for the Haves on how to hold power.

    +

    "Rules for Radicals" is for the Have Nots on how to take it away.

    +

    Defining This Book

    +

    Purpose: Create mass organizations to seize power and give it to the people.

    +

    Premise: The significant changes in history have been made by revolutions.

    +

    Content: The book proposes:

    +
      +
    • Certain general observations
    • +
    • propositions
    • +
    • concepts of the mechanics of mass movements
    • +
    • various stages of the cycle of action and reaction in a revolution
    • +
    +
    +

    This book will not contain any panacea or dogma; I detest and fear dogma. I know that all revolutions must have ideologies to spur them on. That in the heat of conflict these ideologies tend to be smelted into rigid dogmas claiming exclusive possession of the truth, and the keys to paradise, is tragic. Dogma is the enemy of human freedom. Dogma must be watched for and apprehended at every turn and twist of the revolutionary movement... To diminish the danger that ideology will deteriorate into dogma, and to protect the free, open, questing, and creative mind of man, as well as to allow for change, no ideology should be more specific than that of America's founding fathers: "For the general welfare." (p. 4)

    +
    +

    Political Sensitivity & Control Over Events

    +
      +
    • Resilient, Adaptable, and Sensitive
        +
      • "Radicals must have a degree of control over the flow of events"
          +
        • Have a plan for each branch in the path
        • +
        +
      • +
      • Adaptable: Merge the plan, old plans, similar experiences
          +
        • Adapt to shifting political circumstances
        • +
        +
      • +
      • Resilient: Don't back down!!
      • +
      • Sensitive: find, create, and take opportunities
          +
        • Avoid being trapped by your own tactics
        • +
        • Forced to travel a road not of your choosing.
        • +
        +
      • +
      • Keep the initiative. Do not pass the initiative.
          +
        • Keep things in motion!!
        • +
        +
      • +
      +
    • +
    +

    Revolutionary "how-to" Guides Are Rare

    +

    This text is dedicated to splitting two atomic ideas: revolution from communism

    +
      +
    • +

      Revolutionary literature is sparse!

      +
        +
      • Literature extolling the virtues of the Haves is prolific
      • +
      • Literature decrying revolution as reptilian, evil, and hellish is prolific
      • +
      • To the status quo, revolution "is the only force which has no image, but instead casts a dark, ominous shadow of things to come."
      • +
      +
    • +
    • +

      A significant body of communist revolutionary literature exists

      +
        +
      • It is embedded in the "language of communism, red and yellow"
      • +
      • Tactics, maneuvers, strategy, and principles of action in the making of revolutions
      • +
      +
    • +
    • +

      Today's situation is suicidal: revolution and communism have become one in peoples' minds

      +
        +
      • We only accept revolution if it is guaranteed to be on our side and we can't find a way out
      • +
      • Revolution is associated with communism
      • +
      • "The Status Quo" is associated with capitalism
      • +
      +
    • +
    +

    Section: The Ideology of Change

    +
      +
    • +

      Question: What, if any, is my ideology?

      +
        +
      • The prerequisite for ideology is possession of a basic truth
          +
        • Easy for christians, marxists
        • +
        • Hard for an organizer working for open society, who must be a political relativist
        • +
        +
      • +
      +
    • +
    • +

      A free-society organizer is free of the shackles of dogma

      +
        +
      • One belief: that people, given the power to act, will do the right thing in the long run, most of the time
      • +
      • Politics of Change: free to focus on what matters to people now, rather than serve a dogma
      • +
      • Note: This is perhaps better called the un-dogma of a free society.
      • +
      +
    • +
    +
    +

    Political realists see the world as it is: an arena of power politics moved primarily by perceived immediate self-interests, where morality is rhetorical rationale for expedient action and self-interest. (p.12)

    +
    +

    Duality of Revolution and Counter-Revolution

    +
      +
    • +

      Accept and embrace the duality of revolution and counter-revolution. If you understand the big picture of revolution and counter-revolution then you can seek to alter the historical pattern of "two steps forwards, one step back".

      +
    • +
    • +

      Examples of the duality of revolution and reaction (p. 16)

      +
        +
      1. Urban Housing Projects - A dream of replacing the tenements vs. a doubly segregated place.
      2. +
      3. CIO + AF of L - CIO reforming AF of L becomes entrenched member of establishment as AFLCIO
      4. +
      5. etc.
      6. +
      +
    • +
    +

    Section: Class Distinctions: The Trinity

    +
      +
    1. Three Parts of Mankind
        +
      1. Haves: want to keep
          +
        • power, money, food, security, luxury
        • +
        • determined to freeze the Status Quo
        • +
        • "When do we sleep?" - fear violent uprising
        • +
        +
      2. +
      3. Have-Nots: want to get
          +
        • poverty, rotten housing, disease, ignorance, political impotence, despair
        • +
        • jobs pay the least
        • +
        • deprived in all areas basic to human growth
        • +
        • caged by color physical or political, barred from representation
        • +
        • hate the establishment, opulence, police, courts, churches
        • +
        • Justice, morality, law, and order are mere words when used by the Haves: justify and secure the status quo
        • +
        • Power in Numbers.
        • +
        • "When do we eat?", "get off our backs"
        • +
        +
      4. +
      5. Have-A-Little, Want Mores: the middle class
          +
        • Torn between status quo and change things to get more
        • +
        • social, economic, political schizoids
        • +
        • Generally seek the safe way
        • +
        • Insist on three aces in their hand before playing the poker game of revolution
        • +
        • Majority in the US, and generally in Western society.
        • +
        • Argument by Alinksy that the greats come out of the middle class
        • +
        +
      6. +
      +
    2. +
    +

    The middle class spawns people who provoke action but Do Nothing, "I agree with your ends but not with your means." Act as a blanket for the sparks of disension. The book will examine both the Doers and the Do-Nothings. Edmund Burke: "The only thing necessary for the triumph of evil is for good men to do nothing." Alice in Wonderland: Tiger-Lily points out that the flowers that talk grow out of hard beds of ground. In most gardens, they make the beds too soft so that the flowers are always asleep. (p. 21)

    +
    +

    Change means movement. Movement means friction. Only in the frictionless vacuum of a nonexistent abstract world can movement or change occur without that abrasive friction of conflict. In these pages it is our open political purpose to cooperate with the great law of change; to want otherwise would be like King Canute's commanding the tides and waves to cease.

    +

    Alinsky's personal philosophy is anchored in optimism. If we imagine the struggle as a mountain, we must visualize a mountain with no top.... Knowing that the mountain has no top... Why do we continue? ... because it's there...

    +
    +

    Different than Sisyphis, doomed to have the boulder roll back down again. We see new vistas at each plateau.

    +

    The low road to morality.

    +
      +
    • If you have bread and your neighbor has none, he will kill you and eat yours.
    • +
    • We must accept that we rely on each other to continue a free society.
    • +
    • You must share some of your wealth, or lose all of it. Remember: organizations are wealth, you can't destroy everyone.
    • +
    • Note: Following this low road, welfare and basic income can be viewed, for better or for worse, as ransom on society's wealth.
    • +
    +
    +

    This is the low road to morality. There is no other. (p. 23)

    +
    +

    Chapter 2 - Of Means and Ends

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/index.html b/docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/index.html new file mode 100644 index 00000000..a101726b --- /dev/null +++ b/docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/index.html @@ -0,0 +1,3111 @@ + + + + + + + + + + + + + + + + Thoughts On Tyrrany Of Structurelessness Jo Freeman - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Thoughts on "The Tyranny of Structurelessness" by Jo Freeman

    +

    Referenced work: http://www.jofreeman.com/joreen/tyranny.htm

    +

    Thoughts - October 2017

    +

    This paper is not an attack on the informal elite, but an attack on how structurelessness overempowers the INEVITABLE informal elite

    +

    The author says: if the informal elite is both well structured and exercises fair amounts of power, then it should become formalized. let us hope no informal elite at noisebridge ever does these things.

    +

    (anyways, that assumes the author's premise is correct in blanket terms, which is a safe assumption as long as we don't fill her preconditions for formalization)

    +

    In other words, as long as any informal elite at noisebridge doesn't fill her conditions for formalization, it is not necessary to make judgments about the author's correctness and reject or implement her recommendation (which would be formalizing a power structure).

    +

    I agree that formalization is often used to hide the elites and prevent other elites from forming. In corporations, the internal elites (corporate officers) often create snaking structures for middle management, but recruit new elites from outside the organization except in exceptional cases, which usually bypass the 'snaking structures' +I agree that formalization is usually a means of consolidating power +I agree that sometimes formalization exists by the grace of elites and that elites leave or crush formal structures that stop benefiting them +I think that some organizations might outgrow their original elites, accumulating a high amount of a certain type of capital, e.g. media attention, can legitimize the formal power structure and cause the elites to be sloughed off, who then go make something else. Especially if the elites were there for a different reason than that accumulated capital. +I think formal structure is necessary, but that spending the energy developing a custom-fit is too challenging for most organizations, and the "standard structures" we adopt don't fit very well at all.

    +

    I think it's totally spooky how well this paper predicts things

    +

    It definitely says explicitly that groups like this are natural and important, and outlines how they can become awful.

    +

    I think her last section, "Principles of Democratic Structuring" is tailor-fit to some particular organizations in the women's liberation movement that already had lots of established capital at stake

    +

    They were probably good candidates for a higher quantity of structure to wield that capital as an interface to the rest of the humans

    +

    I don't think it fits the general tone of the paper.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/external/Nethack_Keyboard_Commands.pdf b/docs/external/Nethack_Keyboard_Commands.pdf new file mode 100644 index 00000000..2ee31f53 Binary files /dev/null and b/docs/external/Nethack_Keyboard_Commands.pdf differ diff --git a/docs/external/david_recommendations_keystorage/index.html b/docs/external/david_recommendations_keystorage/index.html new file mode 100644 index 00000000..25ec8412 --- /dev/null +++ b/docs/external/david_recommendations_keystorage/index.html @@ -0,0 +1,3056 @@ + + + + + + + + + + + + + + + + David Recommendations Keystorage - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    David Recommendations Keystorage

    + +
    +

    That sounds way better. I am hoping to set this up. Do you know where I can find a checklist or aggregation of modern guide about specific implementations? I know a lot of the tech involved but not the specific products.

    +
    +

    Mostly, I recommend channeling everything through GnuPG and running hardware for that. You'll have issues if you try to simultaneously use something like PKCS#11 for your SSH agent but GnuPG for other tasks. I document using GnuPG for SSH in my desktop config repo, including hardware.

    +

    There are guides to creating an offline, software-managed root key and then signing the hardware tokens with that, but I prefer to just manage a set of hardware tokens instead. The hierarchical approaches only solve direct GnuPG usage, anyway, not SSH.

    +
    +

    My secrets include gpg keys, ssh keys, possibly a keepassx key depending on how I decide to do that. I need to check that. Right now I memorize more passwords than is probably advisable.

    +
    +

    You can centralize all three needs (and more) on GnuPG with a hardware token: +GnuPG keys will obviously work as expected when backed with compatible hardware (instead of just software). My repo above explains basic setup from initializing hardware tokens to setting up new machines/installations to use existing tokens. +You'll want to move your SSH client to using the agent provided by GnuPG. This will require you to upload SSH public keys generated from your GnuPG keys. My repo above explains the rest, including auto-starting the GnuPG agent. +For passwords, I use Password Store. This supports encrypting/decrypting with GnuPG and synchronizing repositories over git, which you can do using git+ssh to leverage the previous work. +For mobile password access, NFC-compatible GnuPG tokens (and USB if you're willing to use a dongle) can decrypt entries in hardware on Android devices. For Android's git+ssh access, I just use an SSH key resident on my phone. Hardware tokens aren't yet supported for SSH on Android, but Password Store doesn't depend on repository access for password security, anyway. +For Google, GitHub, and Dropbox (and other U2F-supporting services), I use a YubiKey (which can also provide a combination of GnuPG hardware and NFC, depending on model). +So, in short, I can nearly run my whole crypto stack in hardware with one YubiKey Neo or any U2F key plus a Sigilance card (my laptop has a smart card reader). The only thing I don't have working yet is backing my browser client certificates with a GnuPG agent.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/external/kevins-defcon-notes-2017.txt b/docs/external/kevins-defcon-notes-2017.txt new file mode 100644 index 00000000..f4701aef --- /dev/null +++ b/docs/external/kevins-defcon-notes-2017.txt @@ -0,0 +1,725 @@ +Notes by Kevin, July 2017 +========================= + +1300 101: Controlling IoT Devices With Crafted Radio Signals +1400 Tr2: Death By 1000 Installers; on MacOS, It’s All Broken! +1500 Tr3: Dark Data, 101: Assembly Language is Too High Level +1600 101: Radio Exploitation 101 +1700 Tr3: MEATPISTOL, malware implantation +### + +1300 101: Controlling IoT Devices With Crafted Radio Signals + +Wirelessly controlled outlet switches +REmoved control unit, soldered in transistors, and could remote control the buttons +Music theory: spectral analysis +Wireless hacking, wireless protocol attack often can't be fixed with a patch +802.11 monitor mode, to figure out if wireless camera can be used for motion detection +We'll explore the physical layer + +"Harness the invisible energy all around us!" -Jedi quote. +IoT: all wireless attacks have 5000% damage power now +Many things operate thru radio: Cell, TV, Wifi, BT, GPS, wireless sec sys, +His device: HackRF One: Great Scott Gadgets (SDR) +LimeSDR, RTL-SDR (cheaper) +Wizard metaphor: transmitting power thru your wand (antenna) +Attacked his Jeep Patriot with the HackRF +Gnu Radio on notebook, using it to turn on Jeep +It was a replay attack. Some cars have rolling codes, which might be defeatable. +Jamming attack: jam_narrow.py 420420000 + +$ python3 ask_modulate_radio_signal.py -c raw_data/outlet_c2_on.json -o /tmp/radio_signal.pcm +$ ./transmit_signal.py -f /tmp/radio_Signal.pcm + +Config file with bit string, frewquency, baud rate, etc. + +Shows captured signal on SDR, converted to audio, in Audacity +Audio tools can be reused for radio hacking +ASK on off key +Short bursts are zeros, long burst ones. + +Open wave files in Audacity by specifying the base Hz, and it resamples to audible. +Do not need to know the math. Gnu Radio will handle much of it. + +Convoluted waves can be deconvoluted +Many things are waves: breathing, temperature of earth, quantum theory +Derivative of a sine wave is itself, another sine wave +Superposition principle: how can you hear many things at once? +How can there be multiple radio waves in the air at once? + +Euler's formula relates e^x to sin(x) and cos(x) +e^ipi = + +Radios actually use a circular sine wave, not a flat 2d sine wave + +ASK, FSK, PSK + +Jupyter notebook for generating a radio wave from scratch +It's on github.com/caleb.../radio-hacking-scripts/ + +CalebMadrigal.com + +### + +ReconVillage.org + +http://reconvillage.org/comprehensive-look-at-twitter-as-a-research-tool/ +Twitter as a Research Tool +6K tweets per second, 500MM tweets per day, 180Bn/year + +March 2006 first tweet +Larry Bird is the bird + + + +DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib +^ Apply IDAPro +Stephan Esser +github.com/nologic/idaref + +Frida, Cycrypt, LLDB +FileMon +MiTM proxy +ObjC, more meaningful than strace to watch its messages +hit/fuzz a particular method +Swift, we see rntime library interactions +IF a function appears in a cache, that means it's been executed before +MachShark: he wrote this to see messages and data structures + + +Breaking in -> automating + +Most apps are largely user reactive in nature +"A little engine for driving the UI while observing the inner workings of an ios app" +^ ChaoticMarch + +Apply your intelligence: Simulate the user, read and understand the UI +How does UI look in memory? +^ Tree of objects with methods attached + +ChaoticMarch is Lua scriptable +Standard functions for touching device etc. + +Mutator to alter web requests to get different results +th3bartend3r + +datasploit github personal access token: 4304ca06ac9ecc108b6d3e1f1e73158374a9d147 +emailhunter: jq/ab12 + +google dork: aggressive google advanced search +domain == dns identity equivalences + +Deloite has a bizintel group, private spy agency + +### Rhett Greenhagen - http://reconvillage.org/skip-tracing-for-fun-and-profit/ + +Simple Pivots to Profiling: + - Where's the perfect place to hide if FBI/CIA/NSA was after you? + - Unique names are a pivot: "Kis*" means eastern europe descent + - Reverse Google search on an avatar to find unique matches + - Unique name is able to be pivoted from searches + - Key phrases/questions can be searched / cross refed + - Phrases with location, date, names can be merged + - Time frame on posts can be used to create a timeline of movement/thinking for profiling + +Maltego: interactive data mining tool +Case File gathers data after collection, for deliverable +Caninput from multiple sources +Palantir Metropolis platform - used to gather large-scale data to use in quantitative investigations + ^ Integrates across multiple sources of data +netglub: open source data mining tool + ^ uses own scripting language, can integrate any toolset + ^ it's Rhett's bread and butter +Social Engineer Toolkit +Michael Bazzell's tools are great + +Google alerts +Footprinting google alerts to see if anything new + +Some cases Rhett liked: + - Justin KEeting #92 + - Chain of identities from Steam to friends to other games + - Via netglub + - MAsterMerge.txt + +Google Takeout - all your data are belong to them +Michelle Gomez on Wired about skip tracing + +What are your steps, what you did to trace someone with success + + +W3C - Since 2013 they've pursued a course unwise, to make a DRM standard for the web. +This allows DRM vendors to work with browser vendors to seamlessly integrate DRM into browsers. +EFF have joined and failed to convince W3C +"Go ahead if you must make DRM, but don't involve the membership." +Compromise: doesn't stop W3C members from suing anybody. +Says W3C can't use DRM to threaten developers. + + + +STM32 ST-Link Utility +System Workbench for STM32 +STM32 CubeMX + +### +Recon Village 1300 Sat - Bug Bounties +One of 5 bug bounty researchers at Synack +Uninformed threat model +Hackers interested in your subdomains, your third party apps, github repos +Recon is great, how to? +Reverse ip search when pen testing? +dnsdumpster.com - to get subdomains of a domain +subbrood? subroot? +censys.io +https://www.virustotal.com/ +https://www.yougetsignal.com/ + +Please don't list private keys on your github repos! + +Google site:domain.com with date constraints, look back to the early history of a domain to find exploitable URLs that have been "forgotten" + +linkfinder on github + +jason haddix +nahamsec +naffy +shubs_shah +bharath kumar + +bugcrowd +@abhijeth + +### 13:30 - DFIR Automation/Orchestration Tools for OSINT/RECON +Tyler Rorabaugh +maltego +hunchly +better investigations +open refine +netglub +intrigue.io + +Why use DFIR Tactics 4 OSINT? +Understand & reduce your attack surface +Gain awareness of threat actors +Enhance incident response investigations +Or for fun... +...like getting to know your CEO + +Then auto-responding to your friends who you scan. + +Let's compare phases: attacking vs response vs OSINT +Why use DFIR +- Built to gather evidence +- Case management +- Can integrate with a ton out of box +- New tools can be added +- You can push/pull data from one place to another +- Because we need to automate or die, right? + +Playbooks make it easy to automate + +These all have automation frameworks, for automation +Demisto +TheHive project +LogRhythm +Hexadite +proofpoint +cybertriage +Siemplify +Resilient IBM +Phantm +swimlane + +IACD Standard says legal mumbo-jumbo + +Montego has transformations +Playbooks are step by step process that glues stuff together + +Tyler's process- +- ican.hopto.org +- ArcSight ESM +- ArcSight Logger +- ArcSight XML + +OSINT for CTF!!! +demisto.com + + +## 14:00 Total Recoll - Dakota +http://reconvillage.org/total-recoll-conducting-investigations-without-missing-a-thing/ +"We are buried beneath the weight of information, which is being confused for knowledge..." Tom Waits +"All Your Data" - NSA Sources +882 MB of PDFs + +Desktop full-text search tool (an understatement) +Create an index: +Preferences > Index Config > Top Directories "+" > Folder of PDFs +http://www.lesbonscomptes.com/recoll/ + +"wapo-prism.pdf" + +Hunchly + +Firefox addon: Recoll visited web pags indexer +Install Plugin > saves to ~/wherever +- then Preferences > Index Config > Top Dirs "+" > that dir +- Preferences > Index Config > Web History tab > check box, put that dir in, set cache size +- It can save pages also. By domain, or for a term, or regex + +Full text search, copy saved locally, no effort! + +Hunchly isn't free, is Recoll? +They eat many document formats +Recoll WebUI has python binding, allows scripting, SDK etc. +Can share index with other users + +NSA docs archive: https://github.com/nsa-observer/documents/tree/master/files/pdf + +dakota@strikersecurity.com +@jerkota +Dakota Nelson + +### 100 Facebook accounts per day - m0m0 (Deloitte MX City) - into breaking things for fun +FB Issue #331801952 +POF, exploiting en masse, we got paid!, remediation, what's next? +- Facebook mobile app implements content thru "instant articles" -2016 +- Content from third parties can be viewed, shared, saved etc in FB +- Found a session hijacking vuln in this functionality +- Informed FB in their bug bounty program + +How it works +- Detected when sharing links from the FB mobile app +- Lack of proper validation in "one tap login" +- "Links shared with a session_key and api_key +- Allows a third party to steal the session when opening the link in a browser since the browser asks to initiate session as the user uses the link + +POF +- A legitimate user opens an instant article on FB mobile app +- User shares it by tapping Share, then Copy link +- User shares the link copied thru any social media +- Exposes the session_key +4. Malic user opens the link and notes that the browser asks to initiate session as the user that initially shared the link! +5. The malicious user accepts and gains the other user's session + +Exploiting the vuln en masse +- IT was not easy to test this issue since we identified that the vuln was not always present when sharing a link +- Searching Google for these links, to steal valid sessions from FB accounts + +Search twitter for: "m.facebook.com/auth.php" and see += ?api_key=asdfasdf&session_key=asdfasdf + +Realtime searches, using "tresor"? +Search vulnerable urls +search twitter for "facebook.com/auth.php" + + +### 14:15 Vulnex.com +- Basic source code analysis, applying OSINT tactics on source code +- Techical people but not usually security savvy +- Influencers +- Access to info & systems +- Common habits we can exploit: Sci-Fi, anime, pr0n, beer + +1. Identify source code repos: Organizations, individuals +2. Search for OSINT patterns in code +3. Go to social networks + +Classics: +-IPs +- Domain names +- URLs +- Emails +- Credit cards +- Phone numbers +- Twitter alias +- Comments +- Source headers - "Written or maintained by ... , company etc" + +e.t. AirCrack-NG +Who is KoreK? +WPA-PSK: Joshua Wright +SHA1 MMX assembly code Simon Marechal + +Github-rank.com: who has the highest ranking? +Gitrob: github.com/michenriksen/gitrob - finds credentials and private keys +^ runs in background, scans for findings, generate "Assessments" report +^ "New assessment" produces new report +.bash_aliases, .bashrc, .gitconfig, etc. <- files the git user shouldn't have published + + + +github.com/Microsoft/ghcrawler +github.com/dfm/github-repo-crawler/tree/master/crawler +npmjs.com/package/repo-crawler + +Get the feeling of developer angriness +- Source code vs. Twitter +Indexing repos by nice words love, good, nice, sweet, kiss +linuxcounter.net/statistics/kernel + +Commens contain plenty of dirty data +- Code +- Bad chars (punctuation etc) +- Useless text (licenses) +- Useless talks by this presenter. I could do much better. + ++ maltego ++ recon-ng ++ datasploit ++ custom scripting + +### 30 July - I can tell what you are by the smell of your wifi + +Multiple signatures +Clients behave differently depending on the AP +APs advertise capabilities, clients react accordingly +e.g. 2.4 ghz, 5 ghz, power management capabilities + +He caches signatures in the database. Uses three different signatures +Sometimes devices have ambigious signatures +To distinguish, they include the upper 24 bits of MAC address + +Only the AP can see the DHCP address/signature unencrypted + +Some client devs have same signature, i.e. iPad Air 2nd gen & iphone 6s + +They developed a WiFi taxonomy +If we could just know what the chipset of a device is, we'd find clever workarounds based on HW or bugs +List of connected clients display in a UI +Correlated with other data - a useful hostname in the DHCP client req +Packet reordering (for lower latency) is a signature element +WIDS (wireless intrusion detec sys) a factor +Published papers: arxiv.org/abs/1608.01725 + +Current status of Impl +- hostapd 2.6 added CONFIG_TAXONOMY +- database of known signatures released to github +- 907 signatures of 172 devs +- ~60% of connected devices are known signatures + +What's next +- Integration +- Better tools to gather signatures, it's a manually intensive process + - Handle dependency on AP +- AP taxonomy? + + + +Power Laws +- Natural processes, they're statistical +- Things descriptive of natural processes follow power laws +- When they don't, something's wrong +- Not all nat processes are natural +- Financial transactions e.g. +- You can use power laws to detect fraud + +Natural distribution vs power law distrivution + +Why matters? += Somehow network traffic is "natural" +- Good lord the machines are alive! +- So power laws must ally +- Some power laws can be hard coded +- Extremely low cost and fast anomaly detection + +(I wonder vs NN) + +Benford's Law +- Simple and awesome power law +- If it's a number... +- Generated by a process... +- The more articicial the packet, the worse the anomaly +- Flood DDoS (Amplification, tcp, etc attack) are very loud +- Can be clearly seen in gestalt connection data +- Practically instantaneous +- Realtime in 100Mb/Gigabit scenarious +- No training at all + +How it's done +- Get a tcpdump +- Extract features +- Power law analysis tells us goodness +- Prnt out to csv with timestamp +- Or throw an alarm +- Iptables maybe, as a trigger endpoint/handler + +What to do with it? +- Watch for DDoS attacks +- Probably won't save your network +- Can determine if someone is using your PC for something nefarious +- DDoS zombie instead of WTF is this? +- Determine between attack types, too + +What else can you do: IDS +- DoS isn't the only kind of disturbance +- Obviously we don't know what all of them are +- Strap learning agent to output +- Tell it to make decisions +- Should at least detect active recon, even at slow speeds +- (portscan demo shows high central spike) + +What else: diagnostics +- Changes in traffic across a network change "power law profile" +- Are all the changes where you expect? +- Is someone doing something to your systems when they're not around? Not physically present? + +What else: User IDing +- Natural systems aren't just networks +- User interaction with a computer is too +- You can profile a user's keystrokes +- Profile your own keystrokes +- Have your own laptop/pc as a honeypot + +What else: much more +- Very early days for power law based analysis +- Possible that all kinds of computer metrics are power law compliant +- Experiment +- It's cheap, fast, simple, so why not? + +What's the demo URL +bitbucket.com/redezem/peimaultralite + + +### iGaming 11:00 + +Security incidents +- Las Vegas Sands hack +- NJ iGaming DDOS attacks +- Affinity Gaming breach +- Hard Rock Hotel/Casino data breach +- Casino Rama Resort in Ontario +- Peppermill + +LV Sands website hack +- They had a tiny IT security staff + +History +- Banknote validators +- Fake coins +- Tony Carmichael / Monkey Paw to release the coin hopper +- Light wand which manipulated the sensors +- 4/24/1980 - lottery reached its liability limits on Daily Number s(3 digits), winning number was 666 +- Later rumour surfaced that illegal bookmakers were not paying +- When watched in slow mo only the 4s and 6s appeared +- Ronald Dale Harris, computer prog, worked for Nevadada gaming control board 1990s, responsible for finding flaws, gaffes in software that runs computerized casino games. +- He audited EEPROMS to look for vulnerabilities, but then reprogrammed them so when a certain sequence was input it'd pay off +- They don't know how much money he made from this +- He wasn't caught for that, caught for Keno, by predicting the pseudorandom number generator beforehand. +- Went to Bally's (Reid Errol McNeal), attempted to redeem a high value winning keno ticket +- Execs became suspicious and notified NJ gaming investigators +- Winrate in BB/100, poker ultimate bets, scatterplot, had a backdoor programmed to see players hole cards, illegally clawed $20MM from players + +Latest news (Evan) +- Hot Lotto RNG Rigging at Muscle: Eddie Tipton, Tommy Tipton, Robert Rhodes, Rob Sand (Iowa Assistant AG, lead prosec) +- Eddie picked the winning lottery tocket , went almost a year before claiming the prize +- Crawford Shaw began investigating +- Lottery refused to release the prize because the trust declined to give their identities, which is req under Iowa law +- Claim to prize was withdrawn in Jan 2012 +- Oct 13 authorities received a tip that Tipton was the man in the video +- Investigators analyzed Tipton's cell recs, showed he was in Des Moines +- Eddie was convicted in 2015 2 cts fraud, following week trial + + + +### Tinder chatbot - Inbar Raz, former Principal Researcher, PerimeterX (company) @inbarraz / @perimeterx +Chatbots have link in profile, or in messages +Better than Tinder! +Unsubscribe - but you're not subscribed +Send any message and they still go on as before +live:juicyyy768 - for example +Created fake Skype profile, and connected +Juicyy Aphrodite + +I'm taking screenshots of thos convo. Kaspersky SAS admins/screens +"Hmm I'm gettin wet" + +Service announcements: "LookHoles.com" +"hey babe:) hope u catching u at a good time and not being too agressive. for ya but i wanna play, wann chat? comne here LookHoles.com" + +"Do you like chat with me? Come here its free to join and find me same username lookholes.com" +"Do you want to sex with me?" +"I am boring, do you want to chat with me? Come here it's free to join and find me same username lookholes.com" + +Esther, 25 "Hi, I'm Kate!" + +Jessie, 27 twitter: emmyyy "I am very interesting dogs, especially pungs" +Evelyn, 27, To be honest I have no idea why I downloaded this: url + +VirusTotal to review the domains of these bots +7 of 61 domains registered to one IP were not protected by proxy reg +One domain reg had fake address +One domain reg had an email, Edouard SZERKOV, same fake address but real email + +Connecting the dots ... greg752@gmail.com, Mathieu Durand, different address still fake + +whereIfoundluv.com +reverse lookup of IP finds even more, virustotal +passionfoundhere.com +IPAddress.com to look up +Montrell Nuble of Silver Spring MD, computertechnicals@yahoo +Shifting from bad/opaque opsec to transparent +Devon Green aka Montrell Devon Nuble +Took photo of himself with scads of cash + +How hard is it to operate such a scam? +Bots- +- Gen 1 Bots - scripts, no JS, no cookies +- Gen 2 - Scripts + State: no JS, uses cookies +- Gen 3 - JS, cookies, Selenium, PhantomJS +- Gen 4 - Malware running on top of real browsers, hijacked machines, fake extensions + + +"I created a bot to find love online - reader, it worked" guardian.co.uk + +Q: How much of your own automation drove your bot discovery process? + +They created their own bots: 70% conversion rate. +70% of people who sent a message to a bot girl clicked through +Most of the discussion int he security indus is around how you got breached +There's so much you can do to avoid exploits. + +Someone is using an automator script over a mobile device or emulator to make this happen. + +Percent of bots vs real people: 57 fake profiles out of 1,000, he says + + +SweepAtic.com - big researcher for multinationals +Mimic recon techniques from adversaries for customers +High frequency, but enterprise-grade, to avoid being blocked +Obfuscation, load balancing algos, to cycle thru different DNS servers +To spread the load across multiple source IPs +To not pollute the ecosystem, so they're not blocked +DataSploit +JPMorgan Chase has over 400 seed domains in the world +They did contracting jobs +To reduce attack service - the value prop + +Client maintained domains in Excel spreadsheet + +Starting to explore competitive analysis +Analysing domains of suppliers of client company +Seed == base domain + +They produce a report of exposure + +Monitor DNS records of subdomains +See how cloud provider relationship changes + + +CTF winners: RumpleForeskin - Jesse & David + +"Hunting licenses" + + +### Zombie Chrome Extensions - Tomer Cohen R&D Security Team Leader, Wix.com +Chrome bots which increase apparent signups, versus legit traffic + +Investigating attack patterns +- Most increase comes from Latin America +- Signup requests come from an iframe in a WiX signup page in FB +- Suspicous users signup then publish a new WiX page within 10 seconds +- The published websites were "How does it work? If you want to see your profile on FB, click Start and download Chrome Extension to do it. Viad30 Unlocker" - gets more views or some similar promise. + +Viad30 +- It injects code into FB tabs +- Opens a WiX iframe transparently inside FB via chrome ext markup injection +- Sends signup request to WiX +- Why? Chrome ext don't have same-origin restriction +- All published sites lead back to the same attack page +- It distributes the link to itself to all the victim's friends +- Reviews the extension in Google Web Store + +Why do it like this? Why WiX.com? +- Wix was used as a supplier of disposable URLs +- Each newly created website provided a new URL basis +- FB didn't recognize that pattern, and allowed those URLs + +This was only the infection phase. These bots were used for more. +- Send Spam, DDoS, Scrape Websites, Click Frauds +- Put the bots up for rent + +Timeline +April 2016: "Facebook 'Comment Tagging Malware' spreading via google chrohme" + +"Tag me if you can" attack according to Kaspersky + +- Victim gets a notification on FB, saying you were mentioned in a comment +- Clicking that, you get a .jse file, which runs a malware to crash Chrome +- The malware copies the Chrome process file, starts a new Chrome with the extension installed +- New copy of .jse is uploaded to user's Google Drive +- Then uses FB's API to tag all friends with that .jse Google Drive URL +- Repeat from "Victim gets a notification" above +- Exponential growth + +Bacground script +chrome.tags.onUpdated.addListener(function() ... + var xhr_obj = asdfasdf(); + xhr_obj['onreadystatechange'] = function() { + ifxhr_obj['readyState'] == 4) { + chrome['tabs']['executeScript'] ... + +How can we make it easier? +- Smuggling an extension to Google Web Store, keeping it up to date, is a lot of effort +- By using XSS to form a botnet +- Adobe Acrobat extension XSS (Jan 2016). Embed an exploit into a PDF file. +- window.open("chrome-extension://.asdfasdfasdf/frame.js + open = request.panel_op + switch(op) { ... + case "request" : .... +- CSP on extensions by default since 2014 +- Prevents common JS injections + - Inline scripts, eval + - whitelist script sources only + + +AVG Web Tuneup XSS +- Attack page adds a listener to a webpage +- window.postMessage(payload) to the AVG Web Tuneup extension embedded in the page +- The AVG extension is vulnerable + +### Weaponizing AI - Bishop Fox + +Hacking into the database +- AI is trying variants on a SQL string, looking for a tablename that exists in the sqlite_master table +- The AI learned how to look for an attack vector ? +- 200 lines of py +- Takes existing ML methodology and applying it to hacking +- "It has to discover the data on its own." +- "This might seem magical, or special and scary to you" +- Please, be more patronizing + +The Model +Regular program: Code -> Binary -> Action +AI program: (Code, Data) -> Model -> Action + +Difficult to enumerate all possible states + + +### 25 Years of Program Analysis +Blind trust of a program by the monitor|kernel was common back to the 60s and earlier. + +You have a potentially vulnerable program, and want to analyse it. +It's composed of "basic blocks" which are executed all together + x = input() # single basic block, a statement + if x== 42: + print "Correct" + else: + print "No" + +Each of these blocks has a constraint attached to it. Depending on the input() value, it'll execute differently. + +"SELECT-a formal system for testing and debugging programs by symbolic execution" + - ACM SigPlan Notices, 1975. + + +" Cyber Grand_Challenge" 2016 where seven fully automated machines fought each other for primacy. +Software analysis- += 249 programs +- Source code avail (now, not during challenge) +- Range of vuln classes +- Documented vulns +- Simple OS model +- Explicit security specifications + +Program coverage is a thing, here. + +Fuzzing. Varying inputs until diff --git a/docs/external/sat-for-noobs/index.html b/docs/external/sat-for-noobs/index.html new file mode 100644 index 00000000..7556f990 --- /dev/null +++ b/docs/external/sat-for-noobs/index.html @@ -0,0 +1,3803 @@ + + + + + + + + + + + + + + + + Sat For Noobs - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    The SAT problem for noobs

    +

    Originally posted at: https://raw.githubusercontent.com/crillab/gophersat/master/examples/sat-for-noobs.md

    +

    This document gives an overview of the SAT problem, and how to use a SAT solver to solve a given problem. +It is intended for users of such solvers. It does not describe strategies, algorithms or implementation +of such solvers. +The intended audience for this document are developpers, so it assumes the reader understands boolean logic.

    +

    This document is work in progress. Expect it to be improved over time.

    +

    What is the SAT problem?

    +

    SAT is a shortcut for "boolean satisfiability". +Imagine you have a boolean formula, i.e a formula containing boolean variables. For instance:

    +
    (a and (b or not(c))) or (not(b) and c)
    +
    + +

    In this formula, a, b and c can either be true or false. +The SAT problem is the problem of finding an assignment for these variables so that the +whole formula becomes true, if such an assignment exists. This assignment is called a model, and a formula +can have zero, one or several models.

    +

    In the above problem, a=false, b=true, c=false is not a model of the formula, because

    +
    (false and (true or not(false))) or (not(true) and false)
    +
    + +

    reduces to false.

    +

    However, the assignment a=true, b=true, c=false is a model, because

    +
    (true and (true or not(false))) or (not(true) and false)
    +
    + +

    reduces to true.

    +

    Now, the trivial problem

    +
    a and not(a)
    +
    + +

    has no model, because there is no way to make this formula true, no matter the value associated with a. +This formula is said to be unsatisfiable (UNSAT for short).

    +

    What is a SAT solver?

    +

    A SAT solver is a piece of software that, when given a formula (more on the input syntax below), +returns either one model, if at least one model exists, or the indication that the problem is +unsatisfiable.

    +

    Implementing such a piece of software is rather easy, but there's one little problem: the SAT problem is NP-complete, +meaning all known algorithms to solve it take an exponential time (worse-case complexity is O(k^n), with k > 1), and we're not even sure there is a way to make +a non-exponential algorithm (this is the famous "P = NP" problem). +So, the most trivial algorithm to solve the SAT problem (test all possible assignments for all variables, stop when one makes the formula true, +return UNSAT once all assignments were unsuccessful), has a worse-case complexity of O(2^n). That means there are, for instance, more than 1 billion assignments to test +for a formula with 30 variables, and about 1.27 * 10^30 for a formula with 100 variables: the time to solve a very simple problem is unacceptable.

    +

    But all hope is not lost.

    +

    The first good news is that exponential does not necessarily mean 2^n. It means k^n, with k > 1. Solving the SAT problem is a whole research field, and algorithms are more and more efficient, +trying to bring k as close to 1 as possible. Because, for instance, although an algorithm with a worst-case complexity of O(1.01^n) is still exponential, there are only about 400 million operations to +solve a problem with 2000 variables.

    +

    The second good news is that practical, real-world, industrial problems are generally structured in such a way that worst-case complexity is just a theoretical limit. Those problems are usually easier to +solve than theoretical ones.

    +

    The third good news is that, according to the Cook-Levin theorem, any NP-complete problem can be translated in a SAT problem, meaning all the research effort in emproving the efficiency of SAT solvers +also profits all other NP-complete problems. In other words, when you are facing an NP-complete problem, you can either try to develop a specific algorithm to solve it, +use a dedicated piece of software (if such a software exists) or try to translate it to SAT and use a SAT solver.

    +

    What is the input format of a SAT solver? How do I represent my problem?

    +

    Conjunctive Normal Form

    +

    To be solved by a SAT solver, a problem must be described in CNF, or Conjunctive Normal Form. The CNF is a conjunction of disjunctions.

    +

    In other words, a CNF formula is a set of clauses, all of which must be true:

    +
    F = C1 and C2 and C3 and ... and Cn
    +
    + +

    A clause is a set of literals, of which one (at least) must be true:

    +
    Ci = L1 or L2 or ... or Lm
    +
    + +

    A literal is a variable, potentially negated.

    +

    Any boolean formula can be translated to an equivalent CNF formula in polynomial time, although the process can sometimes be tricky. +For instance, the formula

    +
    (a and (b or not(c))) or (not(b) and c)
    +
    + +

    is equivalent to the following CNF formula

    +
    (x1 or x2) and (not(x1) or a) and (not(x1) or b or not(c)) and (not(x2) or not(b)) and (not(x2) or c)
    +
    + +

    Note that a few more variables had to be introduced.

    +

    DIMACS format

    +

    the standard way of describing a CNF formula is through the DIMACS syntax. A DIMACS file consists in a one-line prolog, and the description of each clause on each following lines. +The prolog starts with p cnf and is followed by the number of variables and the number of clauses:

    +
    p cnf 5 5
    +
    + +

    Then, on each line, a clause is described. A clause is described as a list of integer values separated by spaces, and ending with th value 0. That means each variable must be translated as an integer value. +Negation is represented by the minus sign. For instance, let's say a is 1, b is 2, c is 3, x1 is 4, x2 is 5. The clause not(x2) or c will be translated as -5 3 0. The above formula will then +be written as:

    +
    p cnf 5 5
    +4 5 0
    +-4 1 0
    +-4 2 -3 0
    +-5 -2 0
    +-5 3 0
    +
    + +

    The SAT solver, when given an input, will then return either the string UNSATISFIABLE or the string SATISFIABLE with an assignment that makes the formula true. +For instance, when fed the formula above, Gophersat will answer:

    +
    SATISFIABLE
    +-1 -2 3 -4 5
    +
    + +

    It means that, when both c and x2 are true, and all other variables are false, the whole formula becomes true. Since x1 and x2 were dummy variables we introduced to make our original formula a CNF, +we can say that our original formula is true when a=false, b=false, c=true. Remember this is not necessarily the only model for this formula, but finding all models +(or getting the total number of models) would take a longer time and is not always useful.

    +

    Translating a general boolean formula to a CNF formula

    +

    Formulas need to be in CNF to be used by a SAT solver. However, problems are usually not formulated this way. Translating general boolean formulas to CNF is thus required. This process can be automated, +but for the moment Gophersat doesn't include such a translator. Here are a few guidelines to translate general formulas to CNF.

    +

    Negation

    +

    In a CNF formula, negation only applies to literals, not to subformulas. Using DeMorgan's laws, such a transformation is trivial: not(F1 or F2) (where F1 and F2 are subformulas) +becomes not(F1) and not(F2) and not(F1 and F2) becomes not(F1) or not(F2). Such transformations are then applied recursively, until only literals are negated.

    +

    Implication (if... then)

    +

    Implication is easily translated in CNF: a -> b is equivalent to not(a) or b.

    +

    Equivalence (equality)

    +

    The formula a <-> b is equivalent to (a -> b) and (b -> a), and can thus be translated as the set of clauses (not(a) or b) and (not(b) or a).

    +

    Exclusive or

    +

    The formula a xor b is equivalent to a <-> not(b), so it can be written (a or b) and (not(a) or not(b)).

    +

    From disjunction of conjunctions to conjunctions of disjunctions

    +

    In a CNF formula, literals are linked by or operators to form clauses, and clauses are linked by and operators. +How do you deal with the opposite, i.e a subformula like (F1 and F2) or (F3 and F4) where F1, F2, F3 and F4 are subformulas? +There are several ways, but the most efficient one requires the introduction of new variables: let's rewrite this formula as

    +
    (x1 <-> (F1 and F2)) and (x2 <-> (F3 and F4)) and (x1 or x2)
    +
    + +

    According to the rules above, x1 <-> (F1 and F2) can be rewritten as

    +
    (not(x1) or F1) and (not(x1) or F2) and (not(F1) or not(F2) or x1)
    +
    + +

    So, the original formula can be written as the following set of clauses:

    +
    not(x1) or F1
    +not(x1) or F2
    +x1 or not(F1) or not(F2)
    +not(x2) or F3
    +not(x2) or F4
    +x2 or not(F3) or not(F4)
    +x1 or x2
    +
    + +

    By applying this rule (and all rules above) recursively, you can translate any boolean formula in a CNF equivalent.

    +

    Uniqueness

    +

    Very often, one wants to specify that exactly one boolean variable among several must be true, the others being false. +For instance, you may want to state that a device is in one of four states : s1, s2, s3 or s4. +It can be written as this set of clauses :

    +
    s1 or s2 or s3 or s4
    +not(s1) or not(s2)
    +not(s1) or not(s3)
    +not(s1) or not(s4)
    +not(s2) or not(s3)
    +not(s2) or not(s4)
    +not(s3) or not(s4)
    +
    + +

    The first clause states "at least one state is true". Then, for each pair of states, one clause states that at least one of these two states is false. +Note that it can lead to the generation of a lot of clauses: there are n*(n-1)/2 pairs of variables. So, when n is big, a huge amount of clauses can be generated. +There are other, more efficient encodings, but they are a little more complicated and won't be explained in this document.

    +

    Examples

    +

    In this section, you will find the translation of a few problems translated as a boolean formula, then as a CNF boolean formula, then as a DIMACS file format.

    +

    Sudoku

    +

    Let's say we want to solve a sudoku problem. Such a problem has a set of constraints:

    +
      +
    • each spot has exactly one number from 1 to 9,
    • +
    • on each line, each number appears exctaly once,
    • +
    • on each column, each number appears exactly once,
    • +
    • in each 3x3 box, each number appears exactly once,
    • +
    • a few spots are already assigned numbers.
    • +
    +

    We must translate this problem in a formalism using only boolean variables, i.e assertions that are either true or false. In this problem, the variables we will use will be:

    +
    line-1-col-1-is-a-1
    +line-1-col-1-is-a-2
    +...
    +line-1-col-1-is-a-9
    +line-1-col-2-is-a-1
    +...
    +
    + +

    and so on. So, we will have 9*9*9=729 variables to represent this problem, each one indicating line-x-col-y-is-a-z, or, as a shortcut, x;y=z, so we will have 1;1=1, 1;1=2 and so on.

    +

    Now, we must represent all our contraints.

    +

    Each spot has exactly one number

    +

    For each spot, we must indicate that the associated value is unique:

    +
    unique(1;1=1, 1;1=2, 1;1=3, 1;1=4, 1;1=5, 1;1=6, 1;1=7, 1;1=8, 1;1=9) and
    +unique(1;2=1, 1;2=2, 1;2=3, 1;2=4, 1;2=5, 1;2=6, 1;2=7, 1;2=8, 1;2=9) and
    +... and
    +unique(9;9=1, 9;9=2, 9;9=3, 9;9=4, 9;9=5, 9;9=6, 9;9=7, 9;9=8, 9;9=9)
    +
    + +

    This can be translated as a CNF set of clauses (see transformation rules above):

    +
    1;1=1 or 1;1=2 or 1;1=3 or 1;1=4 or 1;1=5 or 1;1=6 or 1;1=7 or 1;1=8 or 1;1=9
    +not(1;1=1) or not(1;1=2)
    +not(1;1=1) or not(1;1=3)
    +not(1;1=1) or not(1;1=4)
    +...
    +not(1;1=8) or not(1;1=9)
    +
    + +

    This will lead to the generation of 1 + (9*8)/2 = 37 clauses for each spot, i.e 9*9*37 = 2997 clauses for all spots.

    +

    Each line, column, box contains each number

    +

    Since there are 9 spots in a line and each number from 1 to 9 must appear once, stating that each number must appear at least once is enough. So, we will write:

    +
    (1;1=1 or 1;2=1 or 1;3=1 or 1;4=1 or 1;5=1 or 1;6=1 or 1;7=1 or 1;8=1 or 1;9=1) and
    +(2;1=1 or 2;2=1 or 2;3=1 or 2;4=1 or 2;5=1 or 2;6=1 or 2;7=1 or 2;8=1 or 2;9=1) and
    +... and
    +(9;1=1 or 9;2=1 or 9;3=1 or 9;4=1 or 9;5=1 or 9;6=1 or 9;7=1 or 9;8=1 or 9;9=1) and
    +(1;1=2 or 1;2=2 or 1;3=2 or 1;4=2 or 1;5=2 or 1;6=2 or 1;7=2 or 1;8=2 or 1;9=2) and
    +...
    +
    + +

    This will lead to the generation of 9*9=81 clauses.

    +

    The same reasoning can be applied for columns and boxes, leading to the generation of 81 clauses each time.

    +

    Already assigned numbers

    +

    Now this is easy, we just have to state that a few variables are known to be true. So, for the following problem:

    +

    Sudoky problem example

    +

    the following clauses will be added:

    +
    1;1=5
    +1;2=3
    +1;5=7
    +2;1=6
    +2;4=1
    +2;5=9
    +2;6=5
    +....
    +
    + +

    This will lead to the generation of one clause per already assigned number, i.e 30 clauses for the example problem above.

    +

    Putting it all together in a DIMACS file

    +

    To generate the corresponding DIMACS file, we must indicate the total number of variables and clauses in the prolog line. +There are 729 variables and 2997+81+81+81+30=3270 clauses, so the prolog will be

    +
    p cnf 729 3270
    +
    + +

    Now, each variable must be associated with a numeric value, from 1 to 729. Let's say that x;y=z is translated as (x-1) * 81 + (y-1) * 9 + z. So, 1;1=1 will be 1 and 9;9=9 will be 729. +The complete DIMACS file is available.

    +

    When fed that problem, gophersat will answer

    +
    SATISFIABLE
    +-1 -2 -3 -4 5 -6 -7 -8 -9 -10 -11 12 -13 -14 -15 -16 -17 -18 -19 -20 -21 22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 33 -34 -35 -36 -37 -38 -39 -40 -41 -42 43 -44 -45 -46 -47 -48 -49 -50 -51 -52 53 -54 -55 -56 -57 -58 -59 -60 -61 -62 63 64 -65 -66 -67 -68 -69 -70 -71 -72 -73 74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 87 -88 -89 -90 -91 -92 -93 -94 -95 -96 97 -98 -99 -100 101 -102 -103 -104 -105 -106 -107 -108 109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 126 -127 -128 -129 -130 131 -132 -133 -134 -135 -136 -137 138 -139 -140 -141 -142 -143 -144 -145 -146 -147 148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 161 -162 163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 180 -181 -182 -183 -184 -185 -186 -187 188 -189 -190 -191 192 -193 -194 -195 -196 -197 -198 -199 -200 -201 202 -203 -204 -205 -206 -207 -208 209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 221 -222 -223 -224 -225 -226 -227 -228 -229 -230 231 -232 -233 -234 -235 -236 -237 -238 -239 -240 241 -242 -243 -244 -245 -246 -247 -248 -249 -250 251 -252 -253 -254 -255 -256 257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 270 -271 -272 -273 -274 -275 -276 277 -278 -279 -280 -281 -282 -283 -284 285 -286 -287 -288 289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 301 -302 -303 -304 -305 -306 -307 308 -309 -310 -311 -312 -313 -314 -315 -316 -317 318 -319 -320 -321 -322 -323 -324 -325 -326 -327 328 -329 -330 -331 -332 -333 -334 335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 359 -360 -361 -362 -363 -364 365 -366 -367 -368 -369 -370 -371 372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 396 397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 412 -413 -414 415 -416 -417 -418 -419 -420 -421 -422 -423 -424 -425 426 -427 -428 -429 -430 -431 -432 -433 -434 -435 -436 -437 -438 -439 -440 441 -442 443 -444 -445 -446 -447 -448 -449 -450 -451 -452 -453 454 -455 -456 -457 -458 -459 -460 -461 -462 -463 -464 -465 -466 467 -468 -469 -470 -471 -472 473 -474 -475 -476 -477 -478 -479 -480 -481 -482 483 -484 -485 -486 -487 -488 -489 -490 -491 -492 -493 -494 495 -496 -497 -498 -499 -500 501 -502 -503 -504 505 -506 -507 -508 -509 -510 -511 -512 -513 -514 -515 -516 -517 518 -519 -520 -521 -522 -523 -524 525 -526 -527 -528 -529 -530 -531 -532 -533 -534 -535 -536 -537 538 -539 -540 -541 542 -543 -544 -545 -546 -547 -548 -549 -550 -551 -552 -553 -554 -555 -556 557 -558 -559 -560 -561 562 -563 -564 -565 -566 -567 -568 569 -570 -571 -572 -573 -574 -575 -576 -577 -578 -579 -580 -581 -582 -583 584 -585 -586 -587 -588 -589 -590 -591 592 -593 -594 -595 -596 -597 598 -599 -600 -601 -602 -603 604 -605 -606 -607 -608 -609 -610 -611 -612 -613 -614 -615 -616 -617 -618 -619 -620 621 -622 -623 -624 -625 -626 627 -628 -629 -630 -631 -632 633 -634 -635 -636 -637 -638 -639 -640 -641 -642 -643 644 -645 -646 -647 -648 -649 -650 651 -652 -653 -654 -655 -656 -657 -658 -659 -660 661 -662 -663 -664 -665 -666 -667 -668 -669 -670 671 -672 -673 -674 -675 -676 677 -678 -679 -680 -681 -682 -683 -684 -685 -686 -687 -688 -689 -690 -691 692 -693 -694 -695 -696 -697 -698 699 -700 -701 -702 703 -704 -705 -706 -707 -708 -709 -710 -711 -712 -713 -714 -715 -716 -717 718 -719 -720 -721 -722 -723 -724 -725 -726 -727 -728 729
    +
    + +

    This answer must now be parsed: each positive value indicates the corresponding spot contains the corresponding value. For example, the value 661 is positive. And the variable 661 means +9;2=4; so, the value at line 9, column 2 is 4.

    +

    Representing a sudoku puzzle can seem tedious, but once it is done, the process can be easily automated and used for any other puzzle.

    +

    Automated planning

    +

    Let's say we have a small factory that should be running 24/7. Now, we have a few constraints:

    +
      +
    • an employee should only work 8 hours at most in a given day,
    • +
    • an employee should at most work 5 days per week,
    • +
    • there must be at least one employee at any given moment,
    • +
    • we only want to hire 4 employees.
    • +
    +

    Now, to simplify things, we consider there are 3 working time slots per day: night(12AM - 7AM), morning(7AM - 2PM) and afternoon(2PM - 12AM). How could we generate a timetable for our employees?

    +

    Variables

    +

    Let's deal with variables first. There are 7*3=21 time slots and 4 employees, so we will have at least 21*4=84 variables, each variable meaning employee-x-works-on-day-y-timeslot-z, +or, as a shortcut x=y;z. Now, that could be enough, but to simplify the writing of our formula, let's add a few variables, to indicate employee-x-works-on-day-y, with no time slot indicated, +or, as a shortcut x=dy. There will be 4*7=28 such variables, i.e 112 total variables.

    +

    Employees work only 8 hours a day

    +

    This is akin to a unique constraint: given a set of variable, exactly one must be true. But, here, this is not an "exactly one" constraint, this is an "at most one" constraint: an employee does not +necessarily work on a given day, but if he does, he only works during one time slot. So, for employee 1 on day 1, we will have the following set of clauses:

    +
    not(1=1;1) or not(1=1;2)
    +not(1=1;1) or not(1=1;3)
    +not(1=1;2) or not(1=1;3)
    +
    + +

    And we will do the same for the 7 days, for all 4 employees, leading to the generation of 3*7*4=84 clauses.

    +

    At least one employee in each timeslot

    +

    That's an easy one: for each time slot, we indicate that one of the 4 variables representing each employee for that time slot is true. So, for monday night (day 1, time slot 1), this will be:

    +
    1=1;1 or 2=1;1 or 3=1;1 or 4=1;1
    +
    + +

    Whether we have one, two, three or all four employees working, this clause will be true. We do the same for all 21 time slots, leading to the generation of 21 clauses.

    +

    Employees work at most 5 days per week

    +

    This one is a little trickier. No, we want our workers to have at most five working days, meaning that, for each set of 6 days, at least one must be a day off. For employee 1, this will lead to the generation +of these clauses:

    +
    not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6)
    +not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d7)
    +not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d6) or not(1=d7)
    +not(1=d1) or not(1=d2) or not(1=d3) or not(1=d5) or not(1=d6) or not(1=d7)
    +not(1=d1) or not(1=d2) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7)
    +not(1=d1) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7)
    +not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7)
    +
    + +

    So, for all 4 employees, we will have 4*7=28 more clauses.

    +

    Linking x=y;z variables with x=dy ones

    +

    We must link both types of variables: if an employee works on day 1, that means he either works on day1-slot1, on day1-slot2 or on day1-slot3. For employee 1, that means:

    +
    1=d1 <-> (1=1;1 or 1=1;2 or 1=1;3)
    +
    + +

    In CNF:

    +
    not(1=1;1) or 1=d1
    +not(1=1;2) or 1=d1
    +not(1=1;3) or 1=d1
    +not(1=d1) or 1=1;1 or 1=1;2 or 1=1;3
    +
    + +

    For each day and each employee, we have to generate 4*7*4=112 clauses.

    +

    Translation to DIMACS

    +

    We need to associate each variable with an integer identifiant. Let's say x=y;z be associated with (x-1)*21 + (y-1)*3 + z. That leads to the generation of 84 variables. We also need a different identifier +for each variable of the kind x=dy. We will associate them with the value 84 + (x-1)*7 + y.

    +

    The DIMACS file is available for download. When we feed it to gophersat, it answers

    +
    UNSATISFIABLE
    +
    + +

    Oops! Looks like there is no way to solve our problem. Actually, we could have found that without a solver: there are 4 employees, and each employee works at most during 5 timeslots, meaning only 5*4=20 +time slots with an employee at most. But there are 7*3=21 time slots to fill. We need to relax our constraints. Let's say we decide to hire a fifth employee. We rewrite our problem, as described in DIMACS file timetable5.cnf and ask gophersat his advice. The solver answers:

    +
    SATISFIABLE
    +-1 2 -3 -4 -5 -6 -7 -8 -9 -10 -11 12 13 -14 -15 16 -17 -18 -19 -20 21 -22 -23 -24 25 -26 -27 28 -29 -30 -31 32 -33 -34 -35 -36 -37 38 -39 40 -41 -42 43 -44 -45 -46 -47 48 -49 50 -51 -52 -53 -54 -55 56 -57 -58 -59 -60 -61 62 -63 -64 -65 66 -67 68 -69 -70 -71 72 73 -74 -75 -76 -77 78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 102 -103 -104 -105 106 -107 -108 109 110 111 112 -113 114 115 116 -117 118 119 120 121 122 -123 124 -125 126 127 128 129 130 131 -132 -133 -134 -135 -136 -137 -138 139 -140
    +
    + +

    Great! Now, we have to translate this answer, by checking what each positive value means. Here, the solver gave us the following timetable:

    +
    1=1;2
    +1=4;3
    +1=5;1
    +1=6;1
    +1=7;3
    +2=2;1
    +2=3;1
    +2=4;2
    +2=6;2
    +2=7;1
    +3=1;1
    +3=2;3
    +3=3;2
    +3=5;2
    +3=7;2
    +4=1;3
    +4=2;2
    +4=3;3
    +4=4;1
    +4=5;3
    +5=6;3
    +
    + +

    Everything is okay now. All employees from 1 to 4 work only five days a week, and part-time employee 5 fills the last, unassigned slot.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/external/sfpd_radio_codes_050116.txt b/docs/external/sfpd_radio_codes_050116.txt new file mode 100644 index 00000000..eb717282 --- /dev/null +++ b/docs/external/sfpd_radio_codes_050116.txt @@ -0,0 +1,308 @@ +00 Burglar alarm +32 Accessory to a felony +53m Harassment by phone (obscene call) +67 Offer a bribe to executive officer +69 Deter/resist executive officer (other than peace officer) +71 Threaten injury to school officer or employee +93d Theft of CATV +100S Silent burglar alarm +102 Take or destroy property in custody of officer +118 Perjury +136.1(a) Intimidation of witness or victim +137(a) Offer bribe to influence testimony +146a Impersonating a peace officer +148 Resisting arrest +148.1 False report of a bomb +148.5 False report of a crime +150 Refuse to aid an officer +151(a1) Advocate killing/injuring officer +152 Drunk driver +187 Homicide +192.1 Voluntary manslaughter +192.2 Involuntary manslaughter +192.3 Vehicular manslaughter +203 Mayhem +207 Kidnapping +209a Kidnaping for ransom/extortion +211 Robbery (holdup) +212 Strongarm +213 Purse snatch +216 Shots fired +217 Shooting +219 Stabbing/cutting +220 Assault with intent to mayhem/rape/sodomy/oral copulation +221 Person with gun +222 Person with knife +236 False imprisonment +240 Assault/battery +241 Assault on peace officer/EMT/firefighter +242 Battery +243a Battery against a citizen +244 Throwing acid with intent to disfigure or burn +245 Aggravated assault/deadly weapon (ADW) +246 Shooting at an inhabited dwelling or vehicle +261 Sexual assault/rape +261.5 Rape - under 18 years of age +262 Rape of spouse +266h Pimping +266i Pandering +270 Child neglect/failing to pay the support payments +271 Child abandonment - under 14 +272 Contributing to the delinquency of a minor +273d Corporal injury upon child +273.5a Corporal injury to spouse/cohabitant +278 Child abduction from parent or guardian +285 Incest +286 Sodomy +288 Sexual assault, victim under 15 y/o +290 Sex registration +311 Indecent exposure +311.2a Possession of obscene matter 314 Indecent exposure +330 Gambling +373 Public nuisance misdemeanors (spitting in public places, etc.) +374b Garbage dumping +400 Demonstration/pickets +402b Abandoned refrigerator +404 Riot +405 Citizens holding prisoner +406 Officer needs emergency help +407 Prisoner transport +408 Send ambulance +409 Send tow-truck +410 Requested assistance responding +415 Noise complaint +416 Citizen standby +417 Person ringing doorbells/begging +418 Fight or dispute, no weapons +419 Fight or dispute with weapons, specify +420 Juvenile disturbance +451 Arson +459 Burglary +470 Fraud +476a Insufficient funds (checks) +484e Theft of a credit card +487 Grand theft +488 Petty theft +496 Stolen property receiving +499b Joy riding +503 Embezzlement +518 Vehicle accident, no injury +519 Vehicle accident with injury +520 Accident (non-vehicle) +527 Bonfire +528 Fire +529 Explosion +530 Bomb threat +531 Suspected explosive device found +537 Nonpayment of a bill (Restaurants, etc.) +555 Posted trespass 5 +585 Traffic stop +586 Traffic Congestion +587 Parking violation +588 Driveway violation - tow +594 Malicious mischief (vandalism) +595 Malicious mischief (graffiti) +596 Abandoned vehicle +597 Killing or abusing animals +600 Roadblock +601 Trespassers +602 Breaking & Entering +603 Prowler +647B Prostitute +650 Threats +799 Senile person +800 Mentally-disturbed person +801 Person attempting suicide +802 Coroner's case +805 Juvenile complaint (minor) +806 Juvenile beyond parental control +807 Missing juvenile +809 Missing person +811 Intoxicated person +819 Rolling of intoxicated person +851 Stolen vehicle +852 Auto boost/strip +853 Recovered stolen vehicle +901 Call ____________ +902 Return to station +903 Close Signal Box +904 Meet with officer, non-emergency +905 Meet with city or public service employee +909 Citizen requests interview +910 Check on well-being +911 Broken window +912 Person dumping rubbish +913 Complaint unknown +914 Person down +916 Suspicious person in vehicle +917 Suspicious person +918 Person Screaming For Help +1000 Plane Crash +2000 Prison break +3000 Blockade +4000 Evacuation, mobilization +5150 Mental-health detention +7000 Use of chemical agents imminent + +10-00 Exercise great caution. +10-01 Reception is poor. +10-02 Reception is good. +10-03 Stop transmitting. +10-04 OK/message received +10-05 Relay message. +10-06 Change channel. +10-07 Out of service/unavailable for assignment. +10-07A Out of service at home. +10-07B Out of service - personal. +10-07C Out of Service (court) +10-07E Out of Service (end of watch) +10-07F Out of Service (follow-up) +10-07G Out of Service (gas/garage) +10-07I Out of Service (investigation) +10-07M Out of Service (meal) +10-07R Out of Service (radio shop/range) +10-07S Out of Service (station) +10-07T Out of Service (traffic control/training) +10-008 In service/available for assignment. +10-08F In service, on foot +10-09 Repeat last transmission. +10-10 Off duty. +10-10A Off duty at home. +10-11 Identify this frequency. +10-12 Visitors are present (be discrete). +10-13 Advise conditions at scene +10-14 Citizen holding suspect. +10-15 Prisoner in custody. +10-16 Pick up prisoner. +10-17 Request for gasoline. +10-18 Equipment exchange. +10-19 Return/returning to the station. +10-20 Location +10-21 Telephone: +10-21A Advise home that I will return at: +10-22 Cancel last assignment +10-22C Leave area if all secure +10-22 Disregard the last assignment. +10-23 Standby. +10-24 Request car-to-car transmission. +10-25 Respond & act as backup +10-26 Clear. +10-27 Driver's license check. +10-28 Vehicle registration +10-29 Check for being wanted/warrants. +10-29F The subject is wanted for a felony. +10-29H Caution - severe hazard potential. +10-29M The subject is wanted for a misdemeanor. +10-29V The vehicle is wanted in connection with a possible crime. +10-30 Person/vehicle wanted/stolen +10-31 Person has arrest record +10-32 Person/vehicle clear +10-33 Alarm sounding. +10-34 Confidential info follows +10-35 Consent to search +10-35 Time check. +10-36 Confidential information. +10-36 Emergency notification +10-37 Identify the operator. +10-38 Probation +10-39 Can ______ come to the radio? +10-40 Is ______ available for a telephone call? +10-42 Check on the welfare of/at ______. +10-43 Call a doctor. +10-43 Intelligence Div. interested +10-45 What is the condition of the patient? +10-45A Condition of patient is good. +10-45B Condition of patient is serious. +10-45C Condition of patient is critical. +10-45D Patient is deceased. +10-49 Proceed to ______. +10-50 Subject is under the influence of narcotics. +10-51 Subject is drunk. +10-52 Resuscitator is needed. +10-53 Man down. +10-54 Possible dead body. +10-55 This is a coroner's case. +10-56 A Suicide attempt. +10-56 Suicide. +10-57 Missing person. +10-59 Security check. +10-60 Lock out. +10-61 Miscellaneous public service. +10-62 Meet a citizen. +10-62B Civil standby. +10-62A Take a report from a citizen. +10-63 Prepare to copy. +10-64 Found property. +10-66 Suspicious person. +10-67 Person calling for help. +10-68 Call for police made via telephone. +10-70 Prowler. +10-71 Shooting. +10-72 Gun involved. +10-73 How do you receive? +10-79 Bomb threat. +10-80 Explosion. +10-86 Any traffic? +10-88 Assume your post. +10-91 A Stray. +10-91 Animal. +10-91B Noisy animal. +10-91C Injured animal. +10-91D Dead animal. +10-91E Animal bite. +10-91G Animal pickup. +10-91J Pickup/collect ______. +10-91L Leash law violation. +10-91V Vicious animal. +10-95 Requesting an I.D./Tech unit. +10-96 Undercover surveillance, marked units keep out +10-97 Arrived at scene +10-98 Available for assignment. +10-100 Civil disturbance - Mutual aid standby. +10-101 Civil disturbance - Mutual aid request. +11-10 Take a report. +11-24 Abandoned automobile. +11-25 Traffic hazard. +11-26 Abandoned bicycle. +11-27 with the driver being held. +11-28 with the driver being held. +11-40 Advise if an ambulance is needed. +11-41 An ambulance is needed. +11-42 No ambulance is needed. +11-48 Furnish transportation. +11-51 Escort. +11-52 Funeral detail. +11-54 Suspicious vehicle. +11-55 Officer is being followed by automobile. +11-56 Officer is being followed by auto containing dangerous persons. +11-57 An unidentified auto appeared at the scene of the assignment. +11-58 Radio traffic is being monitored. Phone all non-routine messages. +11-59 Give intensive attention to high hazard/business areas. +11-60 Attack in a high hazard area. +11-65 Signal light is out. +11-66 Defective traffic light. +11-78 Aircraft accident. +11-79 Accident - ambulance has been sent. +11-80 Accident - major injuries. +11-81 Accident - minor injuries. +11-82 Accident - no injuries. +11-83 Accident - no details. +11-84 Direct traffic. +11-85 Tow truck required. +11-94 Pedestrian stop. +11-95 Routine traffic stop. +11-96 Checking a suspicious vehicle +11-97 Time/security check on patrol vehicles. +11-98 Meet: _______ +11-99 Officer needs help. + +Code 1 Do so at your convenience. +Code 2 Urgent. +Code 3 Emergency/lights and siren. +Code 4 No further assistance is needed. +Code 5 Stakeout. +Code 6 Responding from a long distance. +Code 7 Mealtime. +Code 8 Request cover/backup. +Code 9 Set up a roadblock. +Code 33 Mobile emergency - clear this radio channel. diff --git a/docs/external/ukraine_daily_news/index.html b/docs/external/ukraine_daily_news/index.html new file mode 100644 index 00000000..0ebd9bde --- /dev/null +++ b/docs/external/ukraine_daily_news/index.html @@ -0,0 +1,3069 @@ + + + + + + + + + + + + + + + + Ukraine Daily News - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Ukraine Daily News

    + +

    Daily Status Updates (pro-ukranian but mostly objective) +- https://twitter.com/DefMon3 +- https://twitter.com/HeliosRunner

    +

    Accurate Account of Vehicle Losses (only confirmed visual loses, both sides) +- https://twitter.com/oryxspioenkop +- Website: https://www.oryxspioenkop.com/

    +

    Analysis (pro-ukranian or neutral, mostly objective) +- https://twitter.com/RALee85 +- https://twitter.com/ChrisO_wiki (good military historian) +- https://twitter.com/Tatarigami_UA (has some very awesome threads) +- https://twitter.com/RealCynicalFox +- https://twitter.com/Osinttechnical +- https://twitter.com/KofmanMichael

    +

    Translation of Russian Videos +- https://twitter.com/wartranslated (pretty much any relevant videos) +- https://twitter.com/JuliaDavisNews (mostly Russian Media)

    +

    Analysis & Updates (very pro ukranian) +- https://twitter.com/small10space +- https://twitter.com/NOELreports +- https://twitter.com/Deepstate_UA (Videos Mostly) +- https://twitter.com/WarMonitor3

    +

    Official Sources: +- https://twitter.com/StratCom_AFU (posts daily status reports)

    +

    Russian Sources (all telegram) +- https://t.me/notes_veterans +- https://t.me/grey_zone +- https://t.me/milinfolive +- https://t.me/rybar

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/gpt4/cholesterol_plan/index.html b/docs/gpt4/cholesterol_plan/index.html new file mode 100644 index 00000000..247c0345 --- /dev/null +++ b/docs/gpt4/cholesterol_plan/index.html @@ -0,0 +1,3184 @@ + + + + + + + + + + + + + + + + Cholesterol Plan - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Cholesterol Plan

    + +

    Here's the revised plan:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #StrategyConfidenceSpecific ActionsMain Evidence
    1Modify DietHighReduce saturated and trans fats. Increase intake of omega-3 fats and dietary fiber.Sacks et al., 2015
    2Regular ExerciseHigh150 minutes/week of moderate-intensity aerobic exercise and strength training twice a week.Sarzynski et al., 2015
    3Weight LossHighAim for a 5-10% reduction in body weight if overweight.Wing et al., 2011
    4Plant Sterols and StanolsHighConsume foods fortified with plant sterols/stanols like certain margarines or dietary supplements.AbuMweis et al., 2008
    5Avoid Refined Carbohydrates and SugarsHighMinimize intake of foods high in refined carbohydrates and sugars.Te Morenga et al., 2014
    6Monounsaturated FatsHighIncrease intake of foods rich in monounsaturated fats like avocados, nuts, and olives.Kris-Etherton et al., 2018
    7Soluble Fiber SupplementsModerate-HighIncorporate soluble fiber supplements into your diet.Brown et al., 1999
    8Polyphenol-rich FoodsModerateInclude foods like berries, green tea, and dark chocolate in your diet.Tresserra-Rimbau et al., 2014
    9Adequate SleepModerateEnsure 7-9 hours of quality sleep per night.Cappuccio et al., 2010
    10ProbioticsModerateIncorporate fermented foods or probiotic supplements into your diet.Khalesi et al., 2018
    11Time-Restricted Eating/Intermittent FastingModerateLimit the window during which you consume food each day or consider periodic fasting.Patterson et al., 2018
    12Stress ManagementLow-ModerateIncorporate mindfulness activities such as meditation or yoga into your daily routine.Steffen et al., 2017
    13Adequate HydrationLowMaintain regular water intake; guidelines suggest around 2 liters per day.Theoretical, lacks empirical support
    +

    Confidence levels based on strength of scientific evidence: systematic reviews and meta-analyses of randomized controlled trials (highest), single randomized trials (high), cohort studies (moderate), case-control studies (low), and expert opinion (lowest).

    +

    ===

    +

    Sure, here's a table summarizing the three supplemental components with recommended daily doses:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #SupplementDaily DosePrimary BenefitMain Evidence
    1Psyllium Husk5 grams (usually in 1 teaspoon)Soluble fiber for lowering LDL cholesterolBrown et al., 1999
    2Berries and Nuts (Whole Foods)Varied. For instance, a handful of nuts (1 oz.) and 1 cup of berries.Rich in polyphenols, fiber, and healthy fatsSeeram et al., 2008; Bolling et al., 2010
    3NOW Foods Plant Sterols1.5 to 2.4 gramsPlant sterols/stanols for lowering LDL cholesterolAbuMweis et al., 2008
    +

    Ensure to follow the usage instructions on the supplement labels and consult with a healthcare professional before starting any new supplement regimen. Confidence: High, based on randomized trials indicating these substances can help in lowering LDL cholesterol.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/gpt4/cpp_retro_gaming/index.html b/docs/gpt4/cpp_retro_gaming/index.html new file mode 100644 index 00000000..d4f26164 --- /dev/null +++ b/docs/gpt4/cpp_retro_gaming/index.html @@ -0,0 +1,3523 @@ + + + + + + + + + + + + + + + + Cpp Retro Gaming - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Cpp Retro Gaming

    + +

    I would like to contribute code to c++ open source retro gaming projects, + what should I look into?

    +
      +
    1. MAME: Arcade machine emulator.
    2. +
    3. RetroArch: Emulation frontend.
    4. +
    5. Dolphin: GameCube/Wii emulator.
    6. +
    7. PCSX2: PlayStation 2 emulator.
    8. +
    9. ScummVM: Adventure games.
    10. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: Project topic, goals. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 85% (well-known projects, active development, retro gaming focus).

    +

    (0.7/8192/218) +robbintt@gpt-4 27> What else?

    +
      +
    1. higan: Multi-system emulator.
    2. +
    3. OpenEmu: Emulation frontend for macOS.
    4. +
    5. DeSmuME: Nintendo DS emulator.
    6. +
    7. PPSSPP: PlayStation Portable emulator.
    8. +
    9. RPCS3: PlayStation 3 emulator.
    10. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: Project topic, goals. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 80% (popular projects, platform variety, active development).

    +

    (0.7/8192/332) +robbintt@gpt-4 28> what else?

    +
      +
    1. Citra: Nintendo 3DS emulator.
    2. +
    3. Cxbx-Reloaded: Xbox emulator.
    4. +
    5. Nestopia: NES emulator.
    6. +
    7. Snes9x: Super Nintendo emulator.
    8. +
    9. VisualBoyAdvance-M: Game Boy Advance emulator.
    10. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: Project topic, goals. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 75% (variety of consoles, known projects, activity may vary).

    +

    robbintt@gpt-4 30> is this all c++

    +

    Apologies, not all projects are in C++. Here's a revised list of C++ projects:

    +
      +
    1. OpenRA: Red Alert, Tiberian Dawn, Dune 2000.
    2. +
    3. OpenTTD: Transport Tycoon Deluxe.
    4. +
    5. OpenMW: Morrowind.
    6. +
    7. 0 A.D.: Real-time strategy game, 90s style.
    8. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: 90s game, C++ language. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 75% (C++ language, 90s game style, activity may vary).

    +

    robbintt@gpt-4 31> What else from the 2000s?

    +

    C++ open-source projects from the 2000s or with 2000s-style gameplay:

    +
      +
    1. Rigs of Rods: Vehicle simulation.
    2. +
    3. OpenXcom: X-COM: UFO Defense, X-COM: Terror from the Deep.
    4. +
    5. VCMI: Heroes of Might and Magic III.
    6. +
    7. Pioneer: Space trading and combat, inspired by Frontier: Elite II.
    8. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: 2000s game or style, C++ language. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 70% (C++ language, 2000s game style, varying activity).

    +

    (0.7/8192/908) +robbintt@gpt-4 32> what else?

    +

    Additional C++ open-source projects from the 2000s or with 2000s-style gameplay:

    +
      +
    1. Stendhal: Multiplayer online adventure game.
    2. +
    3. The Battle for Wesnoth: Turn-based strategy game.
    4. +
    5. Warzone 2100: Real-time strategy game.
    6. +
    7. Spring Engine: Engine for real-time strategy games.
    8. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: 2000s game or style, C++ language. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 65% (C++ language, 2000s game style, maintenance and activity may vary).

    +

    (0.7/8192/1056)

    +

    robbintt@gpt-4 33> what about modern open source c++ games

    +

    Modern open-source C++ game projects:

    +
      +
    1. Godot Engine: Game engine for various genres.
    2. +
    3. OGRE: 3D rendering engine.
    4. +
    5. Urho3D: Cross-platform game engine.
    6. +
    7. OpenRW: Open-source recreation of Grand Theft Auto III.
    8. +
    9. Cataclysm: Dark Days Ahead: Post-apocalyptic roguelike.
    10. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: Modern game, C++ language. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 70% (C++ language, modern game focus, varying activity).

    +

    (0.7/8192/1200) +robbintt@gpt-4 34> how about 20 more

    +

    Additional modern open-source C++ game projects:

    +
      +
    1. Tesseract: First-person shooter engine.
    2. +
    3. The Powder Toy: Physics sandbox game.
    4. +
    5. Mindustry: Resource management, tower defense.
    6. +
    7. Red Eclipse: First-person shooter.
    8. +
    9. +

      Veloren: Open-world RPG.

      +
    10. +
    11. +

      OpenDungeons: Dungeon management game.

      +
    12. +
    13. ValyriaTear: 2D JRPG.
    14. +
    15. Thrive: Evolution simulation game.
    16. +
    17. Widelands: Real-time strategy game.
    18. +
    19. +

      Naev: Space trading and combat game.

      +
    20. +
    21. +

      OpenClonk: Action, strategy, and skill game.

      +
    22. +
    23. 0k: Real-time strategy game.
    24. +
    25. Voxelands: Sandbox game, Minecraft-like.
    26. +
    27. UFO: Alien Invasion: Strategy game.
    28. +
    29. Megaglest: Real-time strategy game.
    30. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: Modern game, C++ language. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 60% (C++ language, modern game focus, activity and maintenance may vary).

    +

    robbintt@gpt-4 35> which are most suitable to an experienced professional developer starting + out in cpp who already read a tour of cpp

    +

    Considering experience and familiarity with A Tour of C++, the following projects are suitable:

    +
      +
    1. Godot Engine: Versatile game engine, large community.
    2. +
    3. OGRE: 3D rendering engine, established project.
    4. +
    5. Urho3D: Cross-platform game engine, active development.
    6. +
    7. Tesseract: First-person shooter engine, technical knowledge application.
    8. +
    9. Spring Engine: Real-time strategy game engine, potential for algorithm implementation.
    10. +
    +

    Confidence Rubric: +- Popularity: GitHub stars, active community. +- Relevance: C++ language, project complexity, code quality. +- Maintenance: Recent updates, responsiveness.

    +

    Confidence: 75% (C++ focus, varying complexity, active communities).

    +

    robbintt@gpt-4 40> list all 40 in a table with their maintenance and responsiveness and any +other intersting columns for my use case

    +

    Here is a table of the 40 open-source C++ roguelike or Diablo-like game projects with columns for maintenance, responsiveness, and project focus.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    #ProjectMaintenanceResponsivenessProject Focus
    1DevilutionXActiveHighDiablo 1 reverse-engineered
    2FlareActiveHighDiablo-like action RPG
    3Cataclysm: Dark Days AheadActiveHighPost-apocalyptic roguelike
    4AngbandActiveHighTraditional dungeon-crawl roguelike
    5TomeNETActiveModerateOnline multiplayer roguelike
    6KeeperRLActiveHighDungeon management, roguelike
    7UnNetHackActiveModerateNetHack variant
    8Infra ArcanaActiveModerateLovecraftian horror roguelike
    9ADOMActiveModerateClassic roguelike
    10DCSSActiveHighDungeon-crawl roguelike
    11LambdaHackActiveModerateRoguelike game engine
    12GearHeadActiveModerateMecha roguelike RPG
    13FreeabloActiveModerateDiablo 1 engine reimplementation
    14Rogue Survivor RevivedActiveModerateZombie apocalypse roguelike
    15RogueBox AdventuresActiveModerateRoguelike sandbox
    16X@COMActiveModerateTurn-based strategy, roguelike
    17EmpyreanActiveModerateDiablo-like action RPG
    18T-Engine4ActiveModerateRoguelike game engine
    19POWDERInactiveLowClassic roguelike
    20BrogueCEActiveModerateDungeon-crawl roguelike
    21IvANActiveModerateViolent roguelike
    22PosChengbandActiveModerateAngband variant
    23Tales of Maj'EyalActiveHighFantasy RPG, roguelike elements
    24Slash'EM ExtendedActiveModerateNetHack variant
    25Dungeon MercenaryInactiveLowDungeon-crawl roguelike
    26NPPAngbandActiveModerateAngband variant
    27Sil-QActiveModerateAngband variant, Tolkien lore
    28DeliantraInactiveLowOnline RPG, roguelike elements
    29Armoured Commander IIActiveModerateWWII tank roguelike
    30ZorbusActiveModerateDungeon-crawl roguelike
    31IncursionInactiveLowD&D-inspired roguelike
    32The Veins of the EarthInactiveLowD&D-based roguelike
    33SteambandInactiveLowAngband variant, steampunk
    34SilInactiveLowAngband variant, Tolkien's First Age
    35Crawl LightInactiveLowDCSS variant, simplified
    36Halls of MistInactiveLowAngband variant, unique dungeons
    37S.C.O.U.R.G.E.InactiveLowDiablo-like action RPG
    38FAangbandInactiveLowAngband variant, Tolkien's First Age
    39DaJAngbandInactiveLowAngband variant, diverse gameplay
    40DemonActiveModerateMonster-catching roguelike
    +

    Please note that maintenance and responsiveness are subject to change over time, and the table provides an overview at the time of writing. It is recommended to visit each project's repository to evaluate its current status.

    +

    robbintt@gpt-4 45> let's take a step back, what categories of open source linux games should i look at to contribute c++ code to

    +

    Here is a list of categories of open-source Linux games to consider contributing C++ code:

    +
      +
    1. +

      Game Engines: Develop or improve game engines that support various game genres, e.g., Godot Engine, OGRE, Urho3D, Spring Engine.

      +
    2. +
    3. +

      Emulators: Contribute to projects that emulate gaming consoles or arcade machines, e.g., MAME, Dolphin, PCSX2, RetroArch, Citra.

      +
    4. +
    5. +

      Remakes/Recreations: Work on projects that recreate or enhance classic games from different eras, e.g., OpenRA, OpenTTD, OpenMW, CorsixTH, FreeCiv, DevilutionX.

      +
    6. +
    7. +

      Roguelike/Diablo-like: Contribute to projects focused on roguelike or Diablo-like gameplay, e.g., Flare, Cataclysm: Dark Days Ahead, Angband, KeeperRL, TomeNET.

      +
    8. +
    9. +

      Real-time Strategy: Work on projects in the real-time strategy genre, e.g., 0 A.D., Widelands, Warzone 2100, Megaglest.

      +
    10. +
    11. +

      First-person Shooters: Contribute to projects focused on first-person shooter gameplay, e.g., Tesseract, Red Eclipse, DarkPlaces (Quake-related).

      +
    12. +
    13. +

      Role-playing Games: Work on projects in the role-playing game genre, e.g., ValyriaTear, Cataclysm: Dark Days Ahead, OpenMW.

      +
    14. +
    15. +

      Puzzle/Physics: Contribute to projects with puzzle or physics-based gameplay, e.g., The Powder Toy, Mindustry.

      +
    16. +
    17. +

      Sandbox/Crafting: Work on projects focusing on sandbox or crafting elements, e.g., Voxelands, Minetest.

      +
    18. +
    +

    Before contributing to a project, ensure it aligns with your interests and expertise. Visit the project repository, read the documentation, and familiarize yourself with the project's goals, guidelines, and community.

    +

    robbintt@gpt-4 46> how is minetest doing

    +

    Minetest is an open-source voxel game engine and game with Minecraft-inspired gameplay. The project is active and well-maintained. As of February 2022, the latest stable version is 5.4.1, released in June 2021. The project has an active community, with contributors continuing to work on new features, bug fixes, and improvements.

    +

    Minetest has an official forum where users and contributors can discuss the game, development, mods, and other related topics. The project's GitHub repository has over 3,000 stars, and the development team is responsive to issues and pull requests.

    +

    Overall, Minetest is in a healthy state, with ongoing development and an engaged community. If you are interested in contributing to a sandbox/voxel game, Minetest is a good choice.

    +

    (0.7/8192/5159) +robbintt@gpt-4 47> is it all c++

    +

    Minetest's core game engine is primarily written in C++. This includes the rendering engine, networking, and various game systems. However, it also uses the Lua programming language for modding and scripting, allowing users to create custom game modes, items, and functionality using Lua scripts.

    +

    If you are looking to contribute to the core engine or game systems, your C++ skills will be applicable. If you are interested in creating mods or extending the game's functionality, you will need to work with Lua scripts.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/gpt4/increasing-happiness-praxis/index.html b/docs/gpt4/increasing-happiness-praxis/index.html new file mode 100644 index 00000000..6c9533db --- /dev/null +++ b/docs/gpt4/increasing-happiness-praxis/index.html @@ -0,0 +1,3640 @@ + + + + + + + + + + + + + + + + Increasing Happiness Praxis - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Praxis: Increasing Happiness

    +

    Put simply, your reactions and emotions don't change your baseline happiness. The techniques in this document do.

    +

    Explanation of "Happiness Set Point" AKA "Hedonic Treadmill"

    +

    This section is not by GPT-4. Most of the document is. It's not really a more or less reliable narrator than me.

    +

    From wikipedia: Hedonic Treadmill

    +

    Note that "happiness set point" and "hedonic treadmill" are the same concept.

    +

    Importantly, the "happiness set point" can easily be changed.

    +

    Things that bring you immediate feelings, e.g. joy or sadness, do not change your overall happiness. Note that circumstances, e.g. "life events" can change your happiness, and need managed differently, although generally as humans our most important skills for these events are are coping with things we cannot control and controlling things we should.

    +

    The hedonic treadmill, also known as hedonic adaptation, is the observed tendency of humans to quickly return to a relatively stable level of happiness despite major positive or negative events or life changes.

    +
    +

    Headey (2008) concluded that an internal locus of control (https://en.m.wikipedia.org/wiki/Locus_of_control) and having "positive" personality traits (notably low neuroticism (https://en.m.wikipedia.org/wiki/Neuroticism)) are the two most significant factors affecting one's subjective well-being.

    +

    Headey also found that adopting "non-zero sum" goals, those which enrich one's relationships with others and with society as a whole (i.e. family-oriented and altruistic goals), increase the level of subjective well-being.

    +

    Conversely, attaching importance to zero-sum life goals (career success, wealth, and social status) will have a small but nevertheless statistically significant negative impact on people's overall subjective well-being (even though the size of a household's disposable income (https://en.m.wikipedia.org/wiki/Disposable_income) does have a small, positive impact on subjective well-being). Duration of one's education seems to have no direct bearing on life satisfaction.

    +
    +

    Daily Happiness Checklist

    +

    This checklist came from combining the suggestions from: + - "reducing neuroticism" + - "increasing locus of control" + - "improving your happiness set point"

    +

    Daily Happiness Checklist (Revised Order by Effectiveness)

    +
      +
    1. +

      Sleep Hygiene (7-9 hours)

      +
        +
      • Prioritize getting sufficient, quality sleep each night, as sleep is crucial for overall well-being and happiness. Maintain a consistent sleep schedule and establish a relaxing bedtime routine.
      • +
      +
    2. +
    3. +

      Physical Activity (30 minutes)

      +
        +
      • Engage in your preferred form of exercise (e.g., walking, jogging, yoga, or swimming) to boost mood and reduce stress.
      • +
      +
    4. +
    5. +

      Cognitive Behavioral Therapy (CBT) (variable time)

      +
        +
      • Use CBT techniques, such as challenging negative thoughts and restructuring cognitive distortions, to improve mood and overall well-being. Consider working with a therapist or using self-help resources.
      • +
      +
    6. +
    7. +

      Morning Mindfulness Meditation (10-15 minutes)

      +
        +
      • Find a quiet space and spend time focusing on your breath or a mantra to start your day with a calm mind.
      • +
      +
    8. +
    9. +

      Social Connection (variable time)

      +
        +
      • Reach out to friends or family members through a phone call, text, or in-person visit to maintain and strengthen relationships.
      • +
      +
    10. +
    11. +

      Acts of Kindness (variable time)

      +
        +
      • Perform small acts of kindness for others, such as helping a neighbor, complimenting someone, or volunteering. This can boost happiness by promoting positive emotions and fostering social connections.
      • +
      +
    12. +
    13. +

      Time in Nature (15-30 minutes)

      +
        +
      • Spend time outdoors in natural settings, such as a park, forest, or beach. Exposure to nature has been shown to reduce stress, improve mood, and increase well-being.
      • +
      +
    14. +
    15. +

      Problem-Solving Practice (10-15 minutes)

      +
        +
      • Identify a challenge you are currently facing, brainstorm possible solutions, and take a small step toward resolving the issue.
      • +
      +
    16. +
    17. +

      Goal Review and Progress (5-10 minutes)

      +
        +
      • Reflect on your long-term goals, review the short-term actionable steps you've outlined, and track your progress.
      • +
      +
    18. +
    19. +

      Positive Affirmations (5 minutes)

      +
        +
      • Recite affirmations that emphasize control over personal choices and behaviors, promoting self-confidence and an internal locus of control.
      • +
      +
    20. +
    21. +

      Gratitude Journaling (10 minutes)

      +
        +
      • Write down three things you are grateful for each day to cultivate a positive mindset and increase happiness.
      • +
      +
    22. +
    23. +

      Laughter and Humor (variable time)

      +
        +
      • Make time to watch a funny movie, read a humorous book, or share jokes with friends. Laughter can reduce stress, improve mood, and promote feelings of happiness.
      • +
      +
    24. +
    25. +

      Deep Breathing Exercises (5-10 minutes)

      +
        +
      • Practice deep breathing exercises throughout the day to help manage stress and maintain a sense of calm.
      • +
      +
    26. +
    27. +

      Nurturing Hobbies (variable time)

      +
        +
      • Engage in hobbies or activities that bring you joy and fulfillment, such as painting, playing a musical instrument, gardening, or cooking.
      • +
      +
    28. +
    29. +

      Evening Mindfulness Meditation (10-15 minutes)

      +
        +
      • Wind down with another session of mindfulness meditation, focusing on releasing any stress or tension from the day.
      • +
      +
    30. +
    +

    Please note that the effectiveness of each activity may vary depending on individual preferences and experiences. The revised order provided above takes into consideration the importance of certain items, but you should still adjust the checklist according to your personal needs and priorities.

    +

    Reducing your "Neuroticism"

    +

    To reduce neuroticism:

    +
      +
    1. +

      Cognitive-Behavioral Therapy (CBT): Alters thought patterns, reducing negative thinking associated with neuroticism.

      +
    2. +
    3. +

      Mindfulness: Reduces anxiety, promotes self-acceptance.

      +
    4. +
    5. +

      Physical Activity: Reduces stress, promotes mood stability.

      +
    6. +
    7. +

      Develop Coping Skills: Strategies to manage stress help mitigate neurotic reactions.

      +
    8. +
    +

    Increase Your "Locus of Control"

    +
      +
    1. +

      Problem-Solving: Identify challenges, generate solutions, take action, reflect on the outcome.

      +
    2. +
    3. +

      Affirmations: Positive self-statements that emphasize control over personal choices and behaviors.

      +
    4. +
    5. +

      Goal Setting: Long-term vision with short-term actionable steps promotes a sense of control.

      +
    6. +
    7. +

      Mindfulness: Practice staying present-focused rather than worrying about uncontrollable future events.

      +
    8. +
    +

    Improving happiness set point involves psychological interventions

    +
      +
    1. +

      Cognitive Behavioral Therapy (CBT): It focuses on changing thought patterns. Negative thoughts can drag down your happiness set point.

      +
    2. +
    3. +

      Mindfulness Meditation: Regular practice can increase baseline happiness, as it helps reduce stress and promote relaxation.

      +
    4. +
    5. +

      Regular Exercise: It can release chemicals called endorphins which can make you feel happier.

      +
    6. +
    7. +

      Maintain Social Connections: Strong, positive relationships are essential for happiness.

      +
    8. +
    9. +

      Practice Gratitude: Reflecting on positive experiences can boost happiness levels.

      +
    10. +
    +

    Rubric: Evidence based (1-3 points), applicability (1-3 points), detail level (1-3 points).

    +

    Confidence:

    +
      +
    • CBT: Evidence (3/3), Applicability (2/3), Detail (2/3)
    • +
    • Mindfulness: Evidence (3/3), Applicability (3/3), Detail (2/3)
    • +
    • Exercise: Evidence (3/3), Applicability (3/3), Detail (2/3)
    • +
    • Social Connections: Evidence (3/3), Applicability (3/3), Detail (2/3)
    • +
    • Gratitude: Evidence (3/3), Applicability (2/3), Detail (2/3)
    • +
    +

    Overall, I am fairly confident in these recommendations based on scientific literature. However, individual experiences can vary.

    +

    Detailed Activities

    +

    Solo CBT

    +

    robbintt@gpt-4 12> Is CBT a solo activity

    +

    CBT, or Cognitive Behavioral Therapy, is traditionally a form of psychotherapy conducted with a licensed therapist. In this setting, it is not a solo activity, as you work together with the therapist to identify and address negative thought patterns and cognitive distortions.

    +

    However, there are also self-help resources and books available that teach CBT techniques that can be practiced individually. In this case, CBT can be considered a solo activity. Keep in mind that practicing CBT on your own may not be as effective as working with a trained professional, especially when addressing more severe mental health concerns.

    +

    In summary, CBT can be both a solo activity (using self-help resources) and a collaborative activity (working with a therapist). The choice depends on individual needs, preferences, and the severity of the issues being addressed.

    +

    (0.7/8192/5345) +robbintt@gpt-4 13> What is the research around solo cbt

    +

    Research on self-guided or solo Cognitive Behavioral Therapy (CBT) has shown promising results. Several studies have found that self-help CBT interventions can be effective for treating various mental health conditions, particularly mild to moderate anxiety and depression.

    +

    A meta-analysis of 40 studies on self-help CBT interventions (Andersson & Cuijpers, 2009) showed that these interventions had a moderate effect size in reducing symptoms of anxiety and depression. Another meta-analysis of 15 studies (Cuijpers et al., 2009) examining self-help interventions for depression found a moderate effect size as well.

    +

    It is important to note, however, that self-guided CBT may not be as effective as therapist-guided CBT for more severe mental health issues or complex cases. Additionally, self-help interventions may not provide the same level of support, personalization, and feedback as working with a trained professional.

    +

    Despite these limitations, self-guided CBT can be a useful option for individuals who may not have access to a therapist, cannot afford therapy, or prefer to work independently. It can be an accessible starting point for those seeking to improve their mental well-being.

    +

    References:

    +
      +
    • Andersson, G., & Cuijpers, P. (2009). Internet-based and other computerized psychological treatments for adult depression: a meta-analysis. Cognitive Behaviour Therapy, 38(4), 196-205.
    • +
    • https://pubmed.ncbi.nlm.nih.gov/20183695/
    • +
    • Cuijpers, P., Donker, T., van Straten, A., Li, J., & Andersson, G. (2009). Is guided self-help as effective as face-to-face psychotherapy for depression and anxiety disorders? A systematic review and meta-analysis of comparative outcome studies. Psychological Medicine, 40(12), 1943-1957.
    • +
    • https://pubmed.ncbi.nlm.nih.gov/20406528/
    • +
    +

    Solo CBT: Overview from GPT-4

    +

    robbintt@gpt-4 15> ok, how do I do solo cbt

    +

    To practice solo Cognitive Behavioral Therapy (CBT), follow these steps:

    +
      +
    1. +

      Understand the basics of CBT: Familiarize yourself with the principles of CBT, which aims to identify and change negative thought patterns and cognitive distortions that contribute to emotional distress.

      +
    2. +
    3. +

      Learn CBT techniques: Study various CBT techniques, such as thought records, cognitive restructuring, and behavioral activation. You can find these techniques in self-help books, online resources, or mobile apps designed for CBT practice.

      +
    4. +
    5. +

      Identify your negative thoughts and cognitive distortions: Start by observing your thoughts, especially when you experience strong emotions. Recognize common cognitive distortions, such as all-or-nothing thinking, magnification, and personalization.

      +
    6. +
    7. +

      Keep a thought journal: Record your thoughts, emotions, and situations that trigger negative thinking patterns. Note any cognitive distortions and their intensity.

      +
    8. +
    9. +

      Challenge negative thoughts: Question the accuracy and validity of your negative thoughts. Analyze the evidence supporting and contradicting these thoughts and consider alternative explanations.

      +
    10. +
    11. +

      Cognitive restructuring: Replace negative thoughts with more balanced and rational alternatives. Practice this by reframing your thoughts to be more objective and less emotionally charged.

      +
    12. +
    13. +

      Set behavioral goals: Identify and set small, achievable goals that promote positive behaviors and experiences. These goals could include engaging in enjoyable activities, overcoming procrastination, or improving social connections.

      +
    14. +
    15. +

      Monitor your progress: Regularly review your thought journal and progress towards your behavioral goals. Make adjustments as needed and celebrate your successes.

      +
    16. +
    17. +

      Practice mindfulness: Incorporate mindfulness meditation or other mindfulness techniques into your daily routine to enhance self-awareness and emotional regulation.

      +
    18. +
    19. +

      Seek support if needed: If you find solo CBT challenging or feel that your mental health concerns are too complex to address on your own, consider seeking professional guidance from a therapist or counselor.

      +
    20. +
    +

    Remember that self-guided CBT may not be as effective as working with a trained professional, especially for more severe mental health concerns. However, it can be a helpful starting point for those seeking to improve their well-being and manage mild to moderate symptoms of anxiety or depression.

    +

    Creating & Reciting Affirmations

    +

    robbintt@gpt-4 16> How do I do the affirmations one?

    +

    To practice positive affirmations, follow these steps:

    +
      +
    1. +

      Identify areas for improvement: Reflect on aspects of your life where you'd like to boost self-confidence, build motivation, or change negative thought patterns. Examples could include self-worth, relationships, career, or personal growth.

      +
    2. +
    3. +

      Create your affirmations: Write positive, present-tense statements that directly address the areas you want to improve. Make sure they are specific, concise, and self-affirming. For example, "I am capable of achieving my goals," "I deserve love and respect," or "I handle challenges with resilience and confidence."

      +
    4. +
    5. +

      Personalize your affirmations: Ensure that your affirmations resonate with you and feel genuine. Use language that reflects your values and beliefs.

      +
    6. +
    7. +

      Make a list: Compile a list of your chosen affirmations. You can start with a few and gradually expand your list as you become more comfortable with the practice.

      +
    8. +
    9. +

      Practice regularly: Set aside time each day to recite your affirmations. You can do this in the morning as part of your daily routine or throughout the day whenever you need a boost of confidence or positivity.

      +
    10. +
    11. +

      Speak with conviction: Recite your affirmations out loud, with confidence and conviction. You can also say them silently or write them down if you prefer.

      +
    12. +
    13. +

      Visualization: As you recite your affirmations, visualize yourself embodying the positive qualities and emotions they represent. This mental imagery can help reinforce the affirmations and create a stronger emotional connection.

      +
    14. +
    15. +

      Repetition: Repeat your affirmations multiple times during each session to help solidify them in your mind.

      +
    16. +
    17. +

      Be consistent and patient: Practice affirmations consistently over time to experience their full benefits. Change takes time, so be patient and trust the process.

      +
    18. +
    19. +

      Monitor your progress: Periodically review your affirmations to ensure they still align with your goals and values. Update or modify them as needed to reflect your personal growth and development.

      +
    20. +
    +

    Remember, the effectiveness of affirmations may vary for individuals, and it's essential to find an approach that works best for you. Consistency and repetition are key to reaping the benefits of positive affirmations.

    +

    Example Affirmations

    +

    Here's a list of example affirmations covering various aspects of life. Feel free to use these as inspiration or modify them to better suit your personal needs and preferences:

    +
      +
    1. Self-worth: "I am worthy of love, success, and happiness."
    2. +
    3. Confidence: "I believe in my abilities and trust myself to handle any situation."
    4. +
    5. Resilience: "I am strong and adaptable, and I can overcome any challenges that come my way."
    6. +
    7. Positive mindset: "I choose to focus on the positive aspects of my life and embrace gratitude."
    8. +
    9. Health and well-being: "I am committed to taking care of my body and mind, and I prioritize my health every day."
    10. +
    11. Relationships: "I attract positive, supportive, and loving relationships into my life."
    12. +
    13. Career success: "I am capable of achieving my career goals and continue to grow professionally."
    14. +
    15. Personal growth: "I embrace new experiences and opportunities for growth and self-improvement."
    16. +
    17. Financial abundance: "I am financially secure and attract wealth and prosperity."
    18. +
    19. Inner peace: "I cultivate inner peace and balance through mindfulness and self-awareness."
    20. +
    +

    Remember, when using affirmations, it's important to tailor them to your unique needs, values, and beliefs. Personalize these examples or create your own affirmations that resonate with you and reflect your personal goals.

    +

    Practicing Gratitude

    +

    robbintt@gpt-4 19> how do i practice gratitude?

    +

    Practicing gratitude involves cultivating a mindset of appreciation and thankfulness for the positive aspects of your life. Here are some ways to practice gratitude:

    +
      +
    1. +

      Gratitude journal: Dedicate a notebook or journal specifically for gratitude. Each day, write down three things you're grateful for. They can be small, like a delicious meal, or more significant, like a supportive friend. Over time, this practice will help you focus more on the positive aspects of your life.

      +
    2. +
    3. +

      Express gratitude to others: When someone helps or supports you, make a conscious effort to express your appreciation. This can be as simple as saying "thank you" or writing a heartfelt note or message.

      +
    4. +
    5. +

      Gratitude meditation: Spend a few minutes each day in quiet reflection, focusing on the things you're grateful for. Visualize the people, experiences, and circumstances that bring you joy and contentment.

      +
    6. +
    7. +

      Gratitude jar: Set up a jar in a visible location in your home and keep small slips of paper nearby. Whenever you feel grateful for something, write it down and place it in the jar. Over time, you'll accumulate a collection of positive memories and experiences.

      +
    8. +
    9. +

      Share gratitude with others: During casual conversations or at the dinner table, take turns sharing something you're grateful for. This practice can help create a positive atmosphere and strengthen relationships.

      +
    10. +
    11. +

      Mindful moments: Throughout the day, pause and take a moment to appreciate the present moment and your surroundings. This can help you cultivate gratitude for the small, everyday pleasures in life.

      +
    12. +
    13. +

      Reflect on challenges: Consider how past challenges have helped you grow and learn. By finding the silver lining in difficult situations, you can develop a deeper sense of gratitude for your life experiences.

      +
    14. +
    15. +

      Volunteer or help others: Giving back to your community or helping someone in need can foster a sense of gratitude for your own circumstances and the opportunity to make a difference in others' lives.

      +
    16. +
    17. +

      Create gratitude reminders: Set up reminders in your phone, on sticky notes, or through a visual cue to prompt you to pause and reflect on something you're grateful for.

      +
    18. +
    19. +

      Practice gratitude before bedtime: As you wind down for the night, spend a few moments reflecting on the positive aspects of your day. This can help shift your mindset and promote better sleep.

      +
    20. +
    +

    Remember, practicing gratitude is a habit that takes time to develop. Be patient with yourself and try different methods to find what works best for you. Consistency is key to experiencing the benefits of gratitude practice.

    +

    Mindfulness Meditation

    +

    Q: how do I do mindfulness meditation?

    +

    Mindfulness meditation is a practice that focuses on building awareness of the present moment and accepting it without judgment. Here's a step-by-step guide to help you get started with mindfulness meditation:

    +
      +
    1. +

      Find a quiet space: Choose a location where you can sit or lie down comfortably without distractions or interruptions.

      +
    2. +
    3. +

      Set a timer: Decide on the duration of your meditation session, especially if you're a beginner. You can start with 5-10 minutes and gradually increase the duration as you become more comfortable with the practice.

      +
    4. +
    5. +

      Choose a comfortable position: Sit or lie down in a comfortable position, maintaining a relaxed but upright posture. You can sit cross-legged on the floor, on a cushion, or in a chair with your feet flat on the ground.

      +
    6. +
    7. +

      Close your eyes: Gently close your eyes or, if you prefer, maintain a soft gaze a few feet in front of you.

      +
    8. +
    9. +

      Focus on your breath: Pay attention to your natural breathing pattern. Observe the sensation of the air entering and leaving your nostrils or the rise and fall of your chest or abdomen. You don't need to change your breath, just be aware of it.

      +
    10. +
    11. +

      Accept wandering thoughts: It's normal for your mind to wander during meditation. When you notice your thoughts drifting, gently acknowledge them and bring your focus back to your breath without judgment. This process of noticing and refocusing is a key part of mindfulness meditation.

      +
    12. +
    13. +

      Use an anchor: If you find it difficult to focus on your breath, you can use an alternative anchor for your attention, such as a word, phrase, or mantra that you silently repeat to yourself.

      +
    14. +
    15. +

      Expand your awareness: As you become more comfortable with the practice, you can expand your focus to include other sensations or experiences in the present moment, such as sounds, bodily sensations, or emotions.

      +
    16. +
    17. +

      End your meditation: When your timer goes off or you feel ready to end your session, take a few moments to notice your surroundings and gradually bring your awareness back to the room. Gently open your eyes and take a few deep breaths before returning to your daily activities.

      +
    18. +
    +

    Remember, mindfulness meditation is a skill that takes time and practice to develop. Be patient with yourself and try to maintain a non-judgmental attitude towards your thoughts and experiences.

    +

    Q: Isn't there research about focusing on your breath?

    +

    Yes, there is research on the benefits of focusing on your breath during mindfulness meditation and other relaxation practices. Focusing on your breath is a fundamental technique in mindfulness meditation that helps anchor your attention in the present moment and develop greater self-awareness.

    +

    Research has shown that focusing on your breath during mindfulness meditation can lead to various positive outcomes, such as:

    +
      +
    1. +

      Reduced stress: Mindfulness meditation, including breath-focused practices, has been shown to reduce stress by activating the body's relaxation response and decreasing the production of stress hormones.

      +
    2. +
    3. +

      Improved emotional regulation: Focusing on your breath can help you develop greater awareness of your emotions and improve your ability to regulate them, leading to better emotional well-being.

      +
    4. +
    5. +

      Enhanced attention and focus: Breath-focused meditation has been found to improve attention and focus by promoting mental clarity and reducing distractions.

      +
    6. +
    7. +

      Reduced symptoms of anxiety and depression: Studies have shown that mindfulness meditation, including breath-focused techniques, can help alleviate symptoms of anxiety and depression by promoting a more balanced and positive mindset.

      +
    8. +
    9. +

      Improved overall well-being: Regular practice of mindfulness meditation that includes breath focus can lead to an increased sense of well-being and life satisfaction.

      +
    10. +
    +

    In summary, focusing on your breath during mindfulness meditation is a well-researched technique that has been shown to provide numerous psychological benefits, including stress reduction, improved emotional regulation, enhanced attention, and overall well-being.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/gpt4/learning-how-to-learn-summary/index.html b/docs/gpt4/learning-how-to-learn-summary/index.html new file mode 100644 index 00000000..68552a4d --- /dev/null +++ b/docs/gpt4/learning-how-to-learn-summary/index.html @@ -0,0 +1,3185 @@ + + + + + + + + + + + + + + + + Learning How To Learn Summary - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Learning How to Learn

    +

    I would like to condense this to a format for chatgpt to provide information.

    +

    Then I can directly ask for anki cards, outlines, and quizzes for specific chunks and other techniques.

    +

    Key Takeaways

    +
    +

    Can you provide the key points of the book "learning how to learn"

    +
    +

    I'm sorry for any confusion, but as of my last training cut-off in September 2021, there is no book titled "Learning How to Learn". However, there is a popular online course with the same title offered by Coursera, taught by Dr. Barbara Oakley and Dr. Terrence Sejnowski. This course provides key insights into the learning process, based on scientific research.

    +

    Here are some key takeaways from the course, which could also be presented as principles in a hypothetical "Learning How to Learn" book:

    +
      +
    1. +

      Focused and Diffuse Modes of Thinking: Our brain operates in two modes. The focused mode involves a direct approach to solving problems using logical, sequential, analytical thought. The diffuse mode is more relaxed and is associated with "big-picture" thinking. Both modes are necessary for learning.

      +
    2. +
    3. +

      Active Recall and Spaced Repetition: Repeatedly testing oneself and recalling information over spaced intervals are effective techniques for strengthening memory. This is often more effective than simply rereading or highlighting text.

      +
    4. +
    5. +

      Chunking: This involves breaking down complex information into smaller, manageable chunks. Over time, these chunks can be linked together to understand and recall large amounts of information.

      +
    6. +
    7. +

      Procrastination and Memory: The course discusses the science of procrastination and suggests methods to overcome it, such as the Pomodoro Technique (working for 25 minutes, then taking a five-minute break). It also delves into how sleep affects memory and why it's crucial for learning.

      +
    8. +
    9. +

      Interleaving: This technique involves mixing different types of problems or learning materials in one study session. This contrasts with blocked practice (doing a lot of the same type of problem at once), and it's generally more effective for long-term learning.

      +
    10. +
    11. +

      Metaphors and Analogies: These can help in understanding and remembering difficult concepts by linking new information to something you already know.

      +
    12. +
    13. +

      Mindset: The course emphasizes the importance of a "growth mindset", the belief that intelligence and talent can be developed over time through effort, as opposed to a "fixed mindset", the belief that these qualities are inborn and unchangeable.

      +
    14. +
    +

    This is just a summary, and the course goes into much more detail about the science behind these principles and how to apply them effectively. For a comprehensive understanding, I'd recommend either taking the course or reading a book that elaborates on these principles. Dr. Barbara Oakley also has a book called "A Mind for Numbers: How to Excel at Math and Science (Even If You Flunked Algebra)" which talks about similar concepts in the context of learning math and science.

    +

    Chunking

    +
    +

    Can you provide a practical outline tot ry chunking and also an outline for interleaving? I am a programmer if that context helps.

    +
    +

    Absolutely, chunking and interleaving can be extremely beneficial techniques for learning programming. Here's how you can apply them:

    +

    Chunking

    +

    Chunking refers to the process of breaking down larger pieces of information into smaller, manageable "chunks". In the context of programming, these chunks could be individual skills, concepts, or sections of code.

    +
      +
    1. +

      Identify a Topic or Task: Start by identifying what you need to learn. For example, if you are learning a new programming language or framework, the whole topic might seem overwhelming at first.

      +
    2. +
    3. +

      Break It Down: Next, break this topic down into smaller, manageable parts or "chunks". These could be individual functions, classes, or methods in the language or framework you're trying to learn.

      +
    4. +
    5. +

      Focus on One Chunk: Concentrate on learning one chunk at a time. For instance, if you're learning Python, you might start with basic syntax, then move on to data types, and then to control flow structures like loops and conditionals.

      +
    6. +
    7. +

      Practice and Repeat: After you've understood one chunk, practice it. Write code using the function or feature you've just learned. Repeat this process until you feel comfortable with it.

      +
    8. +
    9. +

      Link Chunks: Once you're comfortable with individual chunks, start linking them together. Write code that uses multiple functions or features that you've learned. This will help you understand how these chunks fit together to create a larger program.

      +
    10. +
    +

    Interleaving

    +

    Interleaving involves switching between different types of problems or learning materials in one study session. In programming, this could mean working on different types of coding tasks or switching between different coding languages or concepts.

    +
      +
    1. +

      Identify Different Topics or Tasks: Just like with chunking, start by identifying what you need to learn. Then, find several different types of tasks or topics within this larger topic.

      +
    2. +
    3. +

      Mix Your Practice: Instead of practicing one type of task or topic until you've mastered it (which is called "blocked practice"), mix up your practice. Work on one type of task for a while, then switch to a different type.

      +
    4. +
    5. +

      Apply to Different Contexts: For instance, if you are learning web development, you could practice JavaScript for a while, then switch to CSS, and then to HTML. This will help you understand how these different languages work together to create a website.

      +
    6. +
    7. +

      Use Different Resources: Use a mix of tutorials, documentation, and practical projects. This way, you are not only switching between different topics but also between different learning modalities.

      +
    8. +
    9. +

      Revisit Previous Topics: Regularly revisit previously learned concepts and try to apply them to new problems. This helps strengthen your understanding and enhance recall.

      +
    10. +
    +

    Remember that both chunking and interleaving should be combined with active recall (practicing retrieving information or performing a task) and spaced repetition (revisiting information after increasing intervals of time) for effective learning.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/gpt4/skin_health_drives_all_health/index.html b/docs/gpt4/skin_health_drives_all_health/index.html new file mode 100644 index 00000000..57b57d9a --- /dev/null +++ b/docs/gpt4/skin_health_drives_all_health/index.html @@ -0,0 +1,3220 @@ + + + + + + + + + + + + + + + + Skin Health Drives All Health - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Skin Health Drives All Health

    +

    Prolonged exposure to UV radiation, including UVA and UVB rays, can cause systemic inflammation, leading to age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's.

    +

    UV damage drives 80% of skin health reduction, not aging. This is not referring to skin visual condition (wrinkling), which apparently had no difference, at least in UV vs control group.

    +

    The appearance of the skin can also serve as a predictive marker for various health conditions, emphasizing the importance of proper skin care and sun protection as integral parts of overall physical well-being.

    +

    Source Article

    +
      +
    • https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health
    • +
    • archive: https://archive.is/2023.08.24-114321/https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health
    • +
    • hacker news discussion: https://news.ycombinator.com/item?id=37248882
        +
      • Especially see humectants and occlusives (moisturizers vs moisture trappers on the skin), you need BOTH
      • +
      +
    • +
    +

    GPT-4 executive summary

    +

    The risks associated with neglecting skin health extend beyond mere cosmetic concerns and are linked to serious systemic health issues. Prolonged exposure to UV radiation, particularly UVA and UVB rays, can cause damage to the skin, leading to systemic inflammation. This inflammation is not confined to the skin but affects other organs, including the heart and brain. The concept of "inflammaging" highlights how chronic inflammation, often stemming from skin damage, can be a significant risk factor for age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's.

    +

    Furthermore, the appearance of the skin can be an early indicator of underlying health conditions. Research, such as the Baltimore Longitudinal Study, has found correlations between skin appearance and inner health, making skin a potential predictive marker for various diseases. The failure to protect and maintain skin health through proper care and sun protection can exacerbate these risks, making the skin not just a reflection of our lifestyle but an active participant in our overall well-being. The connection between skin health and systemic health underscores the importance of a comprehensive approach to skincare, recognizing its vital role in overall physical wellness.

    +

    GPT-4 Checklists

    +

    Daily Runbook Checklist:

    +
      +
    1. Morning: Cleanse, moisturize, apply suncream (SPF15 or higher), wear SPF clothing.
    2. +
    3. Afternoon: Reapply suncream if exposed to sun, stay hydrated.
    4. +
    5. Evening: Cleanse, apply nourishing moisturizer.
    6. +
    7. Special Considerations: Use sunglasses, wide-brimmed hat, seek shade, use sun umbrella if outdoors.
    8. +
    +

    Best Practices Checklist:

    +
      +
    1. Understand Skin: Know your skin type and needs.
    2. +
    3. UV Protection: Use suncream with UVA/UVB protection.
    4. +
    5. Wear Protection: Utilize protective clothing and accessories.
    6. +
    7. Moisturize: Apply moisturizer regularly.
    8. +
    9. Avoid Sun Overexposure: Limit sun exposure during peak hours.
    10. +
    11. Monitor Skin: Regularly check for changes and consult professionals if needed.
    12. +
    13. Holistic Approach: Recognize skin's role in overall well-being.
    14. +
    15. Stay Informed: Keep updated on skin health research and consult healthcare professionals.
    16. +
    +

    These checklists encapsulate the essential daily routines and best practices for maintaining skin health, reflecting the information provided in the article.

    +

    Experimental Ideas

    +
      +
    • DIY 20% ascorbic acid for the face (vitamin c): https://news.ycombinator.com/item?id=37254602
    • +
    • humectants AND emollients AND occlusives required: https://news.ycombinator.com/item?id=37253270
        +
      • I think aquaphor is just an occlusive and emollient? Although I thought at one point it had water as well...
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/logs/creativity_2023123/index.html b/docs/logs/creativity_2023123/index.html new file mode 100644 index 00000000..178fa90e --- /dev/null +++ b/docs/logs/creativity_2023123/index.html @@ -0,0 +1,3258 @@ + + + + + + + + + + + + + + + + Creativity 2023123 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Creativity

    +

    ref: https://www.henrikkarlsson.xyz/p/good-ideas

    +

    Notes on "Cultivating a state of mind where new ideas are born"

    +
    +

    This is an insight that has been repeated by artists, too. Pablo Picasso: “Without great solitude, no serious work is possible.” James Baldwin: “Perhaps the primary distinction of the artist is that he must actively cultivate that state which most men, necessarily, must avoid: the state of being alone.” Bob Dylan: “To be creative you’ve got to be unsociable and tight-assed.”

    +
    +

    Solitude is not being alone, it is a state of mind where "the opinions of others do not bother them and where they reach a heightened sensitivity for the larval ideas and great questions in them".

    +

    Insights from the notes of 2 creatives "Alexander Grothendieck" and "Ingmar Bergman".

    +

    Alexander Grothendieck

    +
      +
    • be uncommonly willing to linger in confusion, and be curious about "what confuses"
    • +
    • wait for a more powerful and subtle question to arise from loose and open attention
    • +
    • capacity to surface questions set Grothendieck apart
    • +
    • Paul Graham: People who'd never dream of being fashionable in any other way get sucked into working on fashionable problems
    • +
    +

    Working with others without losing yourself

    +
      +
    • didn't find this section too useful
    • +
    +

    Ingmar Bergman

    +
      +
    • admonishes self to create a personality resistant to outside world and protect creativity
    • +
    • i often correct myself with such a phrase, and i thought of it as propping myself up or giving myself confidence of sorts, but i guess it is also an admonition of a past experience or behavior that i am committing not to allow to replicate
    • +
    • bergman used the journal as a safe place for ideas
    • +
    • we have such safe places, even at work as team collaborative private channels
    • +
    • bergman develops strict routine of writing in workbook from 9-noon for 3 hours, stopping mid sentence at the strike of the clock!
    • +
    • journal is main technique to induce the creative state where his works are born
    • +
    • non judgmental zone
    • +
    • +
      +

      This is a fairly common practice, crafting a ritual where you sit down at the same time every day, in the same chair, writing in the same kind of notebook, creating a repetitiveness that borders on self-hypnosis. This is what Hemingway did, it is what Mario Vargas Llosa does.

      +
      +
    • +
    • I tried to replace this with digital, but I think I will bring back paper, tried and true.
    • +
    +

    Similarities between the two

    +
      +
    • both kept creative/work journals
    • +
    • journals veered off without warning, to whatever comes to the author's focus, not trying for a structure, but just freely journaling.
    • +
    +

    More Techniques

    +

    This is pretty useful, putting the excerpt here:

    +
    More techniques 
    +
    +Here are some other techniques people use to access and maintain the zone:
    +
    +    Introducing a long delay between when you do the work and when it is shown to the world. Annie Ernaux writes about this in A Simple Passion, a memoir about how she becomes obsessed in a banal way with a man who is having an affair with herthe thought that others will read these notes about the tacky sex life of a middle-aged woman feels, to her, almost fictional. She will be far away when it happens. Therefore, she doesnt feel a need to protect herself. 
    +
    +    Thinking of the work in religious terms, as a service to, or a search for, God. Bergman, Grothendieck, and Pascal all do this. It might be easier to summon the awe and daring necessary to push out into the unknown and against social pressure if the alternative is failing God. Or a fiendish muse.
    +
    +    Working with talented and open-minded collaborators, if you have the chance, can be a way to enter the zone. Nick Cave, when asked how hes been able to reinvent himself so many times as a musician, says that his bandmates, especially Warren Ellis, simply will not play anything that sounds like what hes done before. He has surrounded himself with people whose influence is the inverse of the social pressure of normal society and his audience. 
    +
    +    Another idea if you want to push against the mental pressure that kills good ideas, from Paul Grahams recent essay on how to do good work: One way to do that is to ask what would be good ideas for someone else to explore. Then your subconscious won't shoot them down to protect you.” I don’t know of anyone using this technique, but it might work.
    +
    +    Actively subvert expectations. Kristian Mattsson, who performs under the moniker Tallest Man on Earth, says he pays close attention to his emotions as hes writing new songs. If he gets excited, purely, he immediately puts the guitar downexcitement means what he is playing something he knows others will like, something that retreads paths he has already explored and been socially validated for. The songs hes looking for are the ones that hes ashamed of liking.
    +
    +        Noticing these subtle differences in creative excitement requires subtle introspection. But you can be even more subtle. If we think of creative introspection as having three levels, Mattsson is on level two. (Level one is just noticing that you find an idea interesting or exciting.) Level two is noticing that your longing to be accepted can fool you to get excited about an idea that you are not actually excited about. Level three is Andrei Tarkovsky. In his diary, during preproduction of his masterpiece Solaris, the Soviet filmmaker writes that he has met a sound engineer that he considers brilliant. The sound engineer told Tarkovsky that they shouldnt use Bach in the film because everyone is using Bach in their films at the moment. In the diary, Tarkovsky makes no further note, but in the film, the music isBach. Tarkovsky realized it didnt matter that Bach was a popular choice that people would praise him for. It was just the right thing. This is very hard to do, so most creatives stay on level 2 and learn that what is popular is a trap. This does lead to good ideas being needlessly killed. But likely more would die if they had let what is popular kill unpopular ideas. 
    +
    +    Work so fast that you dont have time to self-censor. While writing the intensely confessional My Struggle, Knausgaard forced himself to write five pages a day to overcome his tendency to freeze up in shame. Every time he acclimated to the pace of his writing, he increased the quota so he would always be overwhelmedat one point he forced himself to write 25,000 words in 24 hours, about a third of a normal-sized novel. It is not the best writing he has done; it kind of melts at the edges. But it is true literature and, like Récoltes et Semailles and Bergmans workbooks, it is a rare opportunity to observe an uncommon and fertile mind in real-time.
    +
    +The mental states where new ideas can be born are hard to open up. And they are continually collapsing. The things you have to do to keep them from caving in will make people frown upon youyour tendency for isolation, working deep in the night, breaking norms. The zone is a place at the margin of society. But strangely enough, this fragile margin is where the ideas that make our society possible come from. Almost everything that makes up our world first appeared in a solitary headthe innovations, the tools, the images, the stories, the prophecies, and religionsit did not come from the center, it came from those who ran from it.
    +
    + +

    Refs

    +
      +
    • https://news.ycombinator.com/item?id=36883436
    • +
    • https://www.henrikkarlsson.xyz/p/good-ideas
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/3dprint_notes_nb.txt b/docs/monographs/3dprint_notes_nb.txt new file mode 100644 index 00000000..35302ef0 --- /dev/null +++ b/docs/monographs/3dprint_notes_nb.txt @@ -0,0 +1,71 @@ +General notes: + +When printing a circle, the back and front (oriented in printer) of each item seemed to have deformation. This is likely a resolution issue or a problem with the model. I saw a much smaller circular print at the same time without that deformity visible, although it may have been available to be seen on the bottom of the item. it was a lot taller (a 1 inch tall, half inch diameter cylinder with a hole in the middle) + + +PLA + +https://www.makerbot.com/blog/2011/01/26/how-to-get-better-results-from-your-3d-printer-%E2%80%93-part-iii +Platform temperature: 70 C recommended + +First PLA Print (8 PM) +- Came out great! +- 80 mm/s feedrate +- 100 mm/s travel feedrate +- 190 C nozzle temperature +- 70 C platform temperature +- Painter's tape on platform (fresh) +- Used a raft +- No real deformation + + + +ABS +=== + +Today's Notes (11.17.15, 4 attempts) +I started printing at +Finished printing at around 730 PM. +During this time it got dark and colder as well. Probably started at 72 C ambient room temperature and went to 67 C ambient room temperature. +Alex reported that he could see his breath at NB last night and his print was very deformed. There may have been a relationship. + + +First Attempt (worked well!) +============================ +Extruder @ 220 C +Feedrate 40 mm/s +Travel Feedrate 55 mm/s +Blue painter's tape on platform. Platforma at 110 C. + + +Second Attempt (Worked very well! I deformed it when prying up.) +======================= +Extruder @ 220 C +This was the nicest sample. +No raft - the coin bent because the platform was not allowed to cool. +Previously, rafts must have allowed the structure of the item to cool faster than the platform, preventing deformation. IMPORTANT IF NOT USING A RAFT!! +Kapton tape on platform. Platform at 130 C. + + +Third attempt (not good, many deformities) +========================================== +Extruder @ 220 C +Feedrate 80 mm/s was TERRIBLE quality print. +Travel feedrate probably doesn't matter, since it doesn't affect the print? +Travel Feedrate was 80. +Kapton tape on platform. Platform at 130 C. + + +Fourth attempt (ok, but some deformities): +========================================== +Extruder @ 220 C +Feedrate 40 mm/s was much nicer than the recommended 80 mm/s +Travel feedrate probably doesn't matter, since it doesn't affect the print? +Travel Feedrate was 40. +Kapton tape on platform. Platform at 135 C. + +https://www.makerbot.com/blog/2011/01/26/how-to-get-better-results-from-your-3d-printer-%E2%80%93-part-iii +print temperature 220-230 C for small to large (higher for larger) + +https://www.makerbot.com/blog/2011/01/26/how-to-get-better-results-from-your-3d-printer-%E2%80%93-part-iii +Platform temperature: 130 C (135-140 recommended by source) \ No newline at end of file diff --git a/docs/monographs/Hearthstone_Going_Infinite.txt b/docs/monographs/Hearthstone_Going_Infinite.txt new file mode 100644 index 00000000..832ac979 --- /dev/null +++ b/docs/monographs/Hearthstone_Going_Infinite.txt @@ -0,0 +1,120 @@ +Trent's untested arena ideas: +============================= +1. Time Matters - Play online at 1-4 PM pacific time to fight weaker opponents. Simply put, children are less capable. +2. Do not play after 11 PM pacific time. Tests in ranked shows that the level of difficulty goes way up due to hardcore players. +3. Be prepared to pick from your top 7 classes. Only 2 may be wholesale ignored. Have your prioritization written down. +4. Removal/Tempo is critical, including board wipe. +5. Weapons = Tempo. They are always picked first. + +Always take (incomplete): +===== +all -> chillwind yeti +mage -> enrage cards +priest -> high health +druid -> taunt +midrange -> card draw, 2-for-1, other card advantage. +minions are efficient if they cost half of their combined attack + health. Chillwind Yeti (5/4) = 9, 9/2 = 4.5, 4.5 > 4. Very efficient. +Booty bay bodyguard is bad, it is 5/4 for 5, (4.5 < 5), specifically, a 4 health minion will trade down with a 3-4 cost card. + + +Going Infinite and Games Per Day +================================ +A NOTE: In a sense, with a daily quest and one arena round per day, going infinite actually happens at 6 wins. This nets 106 gold per day average. Coupled with 10 gold for winning 3 rounds you can play arena daily. + +Going infinite takes at least 7 wins (on average). +This is a game 7 win ratio higher than 2.25. + +You get your gold back after 7 games plus prizes. +The prizes must be worth seven games worth of playing. + +GAME 6 WIN RATIO: 3.0 -- (6 wins / 2 losses, then a win after). +The plus is to indicate that the third loss must occur last, so the win rate is actually much higher at different points. +To accomplish this win rate, you will need an extremely high win rate (lets assume 100%) in the first three rounds, which can taper in the 2nd 3 rounds to 1.33 + +Notes: +The true breakeven on buying packs is 3-4 games. Over 4 wins is coming out ahead. +It takes up to 4 quests (4 days) to get one arena play, so save your gold! +What is the average gold you get for 3-4 wins? + +From the internet (http://us.battle.net/hearthstone/en/forum/topic/11224842495) +0 win = 0-30 gold, average 14 gold +1 win = 0-40 gold, average 17 gold +2 win = 0-50 gold?, average 23 gold +3 win = 30- at least 50 gold, average 41 +4 win = 45-85 gold, average 65 +5 win = 55-120 gold, average 81 +6 win = 75-145 gold, average 106 +================================ +7 wins = 150-180, average 165 +8 wins = 150-220, average 185 +9 wins = 150-255, average 211 +10 wins = 150-370, average 261 +11 wins= 225-510, average 306 +12 wins= 225-535, average 332 + +What about your bankroll? +========================= +You can't win every time. How much do you need to have socked away to keep things smoothly running? +Simple concept: 3 bad beats (0-2 wins) requires 600 gold, including the 4th buy in. + + +Nick's Arena Tips: +================== +Use Tier Lists (online) - HearthArena, Trump Arena Tier List +Get a good batch of two drops. +Pay attention to your curve. +Many people right now (before the expansion) are really good, so the arena is harder. +It is harder at the end of a season (month of ranked play) +It is harder on the final days of an expansion (less hot, less casual). +Some classes are better than others - see the tier lists. Mages have common removal. Paladins are also very good. + + +Nick's Tier Lists: +================== +http://www.heartharena.com/ +http://www.liquidhearth.com/guides/arena-tier-list + + +Warming Up: +=========== + +Presumably there is some limit to how many games per day are fun. +Quest rewards 40 gold and typically take 2-3 games per quest. +One quest is given per day. +This means there are 2-3 games 'guaranteed gold' per day. +Quests can be used as daily warm ups to keep sharp. + +It makes sense to do a quest to warm up, then try to go infinite in the arena. You can always pause your arena so if you get bored it won't be an obligation. + +Another option is to warm up in the Tavern Brawl. + + +Training for the Arena: +======================= +1. Get all basic spells for all classes. +2. Play 6-8 tavern brawls for each class to get exposed to new cards you may not have used. +3. USE INFORMATION ONLINE. This should be organized by class so I can quick reference the specific class I end up with. +4. WARM UP BEFORE GOING IN!! +5. You must be prepared to pick 7 of the 9 classes, you may get your worst three picks and have to choose from those. +6. MAYBE: BUILD ALL ARCHETYPES FOR ALL CLASSES??? This takes a lot of common cards, and it can probably be replaced by using information online. However, there are a lot of cards. + + +Getting android Galaxy S6 an android phone packs: +================================================= +https://www.reddit.com/r/hearthstone/comments/32q830/stepbystep_guide_for_getting_free_android_pack +https://www.reddit.com/r/hearthstone/comments/3dkwew/how_to_get_the_samsung_s6_3_packs_and_card_back/ + + +Trent's Play Notes: +============== + +My worst classes so far: +Druid + +My best classes so far: +Mage, Priest + +Tavern Brawl Tally: +=================== +Mage - 2 +Hunter - 1 \ No newline at end of file diff --git a/docs/monographs/account_traversal/index.html b/docs/monographs/account_traversal/index.html new file mode 100644 index 00000000..2fdae0e8 --- /dev/null +++ b/docs/monographs/account_traversal/index.html @@ -0,0 +1,3402 @@ + + + + + + + + + + + + + + + + Account Traversal - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Account Traversal

    +

    Disclaimer: This document does not include a strict howto.

    +

    Can someone who has gained control of your phone number take over all your online accounts?

    +

    What if someone controls one of these: +1. Primary Email +2. Recovery Email for the Primary Email +3. Domain Name Registrar - for the Domain Name of your Primary Email

    +

    Can I Trust my phone company?

    +

    No, that's how the CIA Director got hacked.

    +

    If you need more fear, watch this exploit demo video.

    +

    Not convinced? This reporter lost it all (and got some back).

    +

    Should I turn off phone number recovery?

    +

    I don't know, should you?

    +

    This whole document is dedicated to convincing you that you should, unless you don't have the bandwidth to do so.

    +

    Removing Phone Number Recovery from primary accounts will help a lot, but it's also the default way that you recover your account if you lose your password. It is not the only way though, and we will explore better alternatives.

    +

    Most accounts are dependent on one of the following accounts: +- Google Account (parent account of gmail service) +- iCloud Account (Apple) +- Facebook Profile +- Phone Number (Provider Managed Account)

    +

    But I'm in a hurry!

    +

    First of all, if you aren't really thinking about these problems and how they affect your online presence, you should just leave phone recovery on. Turning it off requires attention, consideration, and light maintenance.

    +

    If you are in a position that could compromise your salary, business, community, or family, think carefully about whether you govern your information in a way that impacts those relationships fairly.

    +

    Determine if you have what it takes!

    +

    If you are disorganized, lose your keys often, or have things stolen often, the recovery phone number may be safer for you.

    +

    Clarifying 2FA and FIDO-U2F

    +

    FIDO-U2F provides key marginal benefits over using Google Authenticator.

    +

    TL;DR - The benefits are marginal, tangible, and convenient.

    +

    Which product do I use?

    +

    I used the Yubico FIDO-U2F. You will need to register two of them on each account and put one in a safe place in case you lose the other.

    +

    Benefits

    +
      +
    1. Fast compared to OTP 2FA (one-time password e.g. Google Authenticator)
    2. +
    3. Immune to Shoulder Surfing (no visual acquisition vector)
    4. +
    5. Phone theft happens daily, this is not in a phone
    6. +
    7. A backup FIDO-U2F is cheaper & easier to maintain than a backup phone containing additional Google Authenticator OTP for each account.
        +
      • Many OTP setups only support one linked app, too (needs fact checked)
      • +
      +
    8. +
    9. The account server may be able to detect a man in the middle attack or a phishing website
        +
      • However, many companies may not bother doing this -- shame on them
      • +
      • Cannot verify they are doing this or doing it right
      • +
      +
    10. +
    +

    Costs

    +
      +
    1. Surprise: You have to use Google Authenticator on each account if you want to login to things on an iPhone
        +
      • Apparently you can connect the FIDO-U2F dongle to an android phone?
      • +
      • Browsers: FIDO-U2F only works with Chrome and Opera (for now)
          +
        • Reportedly Firefox and Microsoft are coming
        • +
        +
      • +
      • No hope for Safari, iPhone FIDO-U2F (Apple hates sharing)
      • +
      • You have to use Google Authenticator for everything else
      • +
      +
    2. +
    3. Make a backup U2F token in case you lose your keys
    4. +
    5. Keep your backup up-to-date
        +
      • Maintain an index of what services use U2F so you can audit your backup
      • +
      +
    6. +
    +

    Improving Security without FIDO-U2F?

    +

    The same order of account protection can be achieved without FIDO-U2F: +1. Use Google Authenticator +2. Have a second BACKUP 2FA method (NOT a phone number) + - WHEN your phone is stolen, you WILL lose all those Google Authenticator 2FA tokens. + - iPhone Encrypted backups currently store them. This isn't guaranteed. + - Unencrypted backups do not store them. I do not know if icloud backups store them. +3. Disable Phone Number Account Recovery

    +

    Know your recovery emails and recovery phone numbers

    +

    Google has a recovery email feature. Is it your Yahoo account from 2003?

    +

    If your recovery email for tons of services is Google, and your recovery email for Google is hacked, then you are a sitting duck. Change your recovery email!

    +

    Did you know that yahoo is totally compromised?

    +

    A customer service agent at a phone company often has the power to reallocate your phone number to a new device. If a person steals your identity, they can compromise any accounts with a recovery phone number.

    +

    Building an account recovery graph

    +

    It is helpful to build a graph of how your account dependencies resolve. This requires you to list out your commonly accessed accounts.

    +

    Draw this graph with bubbles and arrows.

    +

    For each account ask yourself, "if I lose the password for this account, how do I recover it?" The answer is usually traced back to one recovery phone number and a few recovery email accounts.

    +

    Once you find your most common recovery emails and recovery phone numbers, ask yourself - how do you recover those accounts? You should find that everything depeonds on one or two things, often your phone number and primary email.

    +

    Now imagine if a thief got access to one of these recovery accounts. What happens next? How many accounts can they steal from you?

    +

    Does your primary email have a recovery email?

    +

    Why would you have a recovery email on your primary email? If that recovery email is compromised, it is at the top of your account recovery graph, and a prime target for an attacker.

    +

    Know your Circular Dependencies

    +

    If your Google and iCloud accounts both recover each other, they form a closed loop and can compromise any account linked to either one.

    +

    Account Traversal

    +

    This just means the ability to walk down your whole graph from one piece of information. This is how you lose all your data.

    +

    Account traversal generally begins at your email or phone number.

    +

    For a given online account, a person can probably access your recovery email if they control your recovery phone number.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/candidate-languages-for-genetic-algorithms/index.html b/docs/monographs/candidate-languages-for-genetic-algorithms/index.html new file mode 100644 index 00000000..b0c336cb --- /dev/null +++ b/docs/monographs/candidate-languages-for-genetic-algorithms/index.html @@ -0,0 +1,3145 @@ + + + + + + + + + + + + + + + + Candidate Languages For Genetic Algorithms - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Self Description and Self replication and Genetic Algorithms

    +

    Candidate Languages for Genetic Algorithms:

    +
      +
    1. Binary Lambda Calculus (BLC)
    2. +
    3. Game of Life / Wiring / other derivatives
    4. +
    5. brainfuck
    6. +
    7. m4
    8. +
    +

    Generating Brainfuck using a genetic algorithm

    +

    Project here.

    +

    Binary Lambda Calculus

    +

    A lot of interesting blc information is stored here: https://tromp.github.io/cl/Binary_lambda_calculus.html

    +

    A ton of info from the creator of tromp: https://tromp.github.io/cl/cl.html

    +

    This ties in closely to computer science theory and brainfuck in general.

    +

    The author claims that tromp is the most concise possible universal machine

    +

    details about tromp: http://www.ioccc.org/2012/tromp/hint.html

    +

    m4 macro language

    +

    Written by: Brian Kernighan, Dennis Ritchie

    +
    +

    m4 is a general-purpose macro processor included in all UNIX-like operating systems, and is a component of the POSIX standard.

    +
    +

    Someone who made obfuscated casino software (about 20 years before 2018) in brainfuck on hacker news said that they "leaned heavily on make and m4" in order to write most of the brainfuck.

    +

    https://en.wikipedia.org/wiki/M4_(computer_language)

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/case-study-agar.io/index.html b/docs/monographs/case-study-agar.io/index.html new file mode 100644 index 00000000..b311b4f1 --- /dev/null +++ b/docs/monographs/case-study-agar.io/index.html @@ -0,0 +1,3120 @@ + + + + + + + + + + + + + + + + Case Study Agar.Io - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Case Study: agar.io

    +

    This game has been around for awhile now and represents migrating a viral game to an ad-based and app based revenue platform.

    +

    References

    + +
    +

    Research

    +

    Growth

    +
      +
    • Originally released on the creator's IP address via 4chan
    • +
    • Game released 1 week later on Steam Greenlight which is now called Steam Direct.
    • +
    +

    Monetization Methods

    +
      +
    1. Ads
    2. +
    3. in-game purchases
    4. +
    +

    Mobile Platform vs HTML5 - which came first, do they play together?

    +

    HTML5 - Browser Experience

    +

    Is this really the original platform or just initially the most viral?

    +

    Mobile Experience

    +

    Install the mobile game and experience how it is compared to the online game

    +

    Is this an HTML5 game? What packager does it use?

    +

    How is the performance, usership?

    +

    Does it share users with the browser game?

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/cheap_raid_server/index.html b/docs/monographs/cheap_raid_server/index.html new file mode 100644 index 00000000..8c5def04 --- /dev/null +++ b/docs/monographs/cheap_raid_server/index.html @@ -0,0 +1,3347 @@ + + + + + + + + + + + + + + + + Cheap Raid Server - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Cheap Raid Server

    +

    Working Free Space

    +

    When your storage is 80% full, consider it full due to difficulty shuffling data. So add a 80% multiplier on any storage requirements and get a 30% overhead for required stuff.

    +
      +
    • ref: https://jrs-s.net/2016/11/08/depressing-storage-calculator/
    • +
    +

    What is the base cost of a software RAID server

    +

    Hardware or software raid?

    +

    According to this reddit post, hardware raid is incredibly out of date.

    +

    Raid Configurations Available today

    +

    According to the below, only btrfs RAID10 is stable. This has great redundancy except 2 adjacent disk stripes during failure, so there is stripe single redundancy...

    +

    Used Hard Drives

    +
      +
    • LTT on why these drives are out there today (2022): https://www.youtube.com/watch?v=xQMQW4sbXf8
    • +
    • crypto mining aka "chia mining", these drives are "barely used", just written once...
    • +
    • they had 2300-2600 hours of poweron time... that's only 100 days?
        +
      • expected lifetime 50k-60k, manufacturer says 45k hours is the reliability standard
      • +
      • linus recommends 20k to 25k hours as the safe ceiling
      • +
      +
    • +
    • This video shows a lot of drive metrics (SMART attrs) that can predict drive failure up to 70% of the time
    • +
    • Video also shows how to determine the drive was used for mining (1 write, low reads, lots of poweron hours)
    • +
    • WD drives didn't record reads and writes...
    • +
    • DIY NAS best deal was 80gb per dollar, seagate was the cheapest brand on ebay and had reads/writes.
    • +
    • However, the 18TB shucked drives are only $170 (provided they are not SMR), which are the same price...
        +
      • Linux recommends used, i guess to save on electronic waste?
      • +
      +
    • +
    +

    Shingled Drives / SMR

    +

    Do not use random consumer drives for RAID arrays... ;(

    +
      +
    • Check out the SMR section here for understanding what drives don't use it lately: https://www.reddit.com/r/DataHoarder/wiki/hardware
    • +
    +

    The exact easystore shucked drive, post 2019 WD Red drives, are shingled/SMR.

    +

    According to this thread, that is not true for larger drives, they converge on helium filled: https://www.reddit.com/r/DataHoarder/comments/wlingk/should_i_buy_cmr_or_smr/

    +

    However, shucking can require power pin reroute, which I don't want to mess with.

    +
    +

    For occasional backups and cold storage, SMR is perfectly fine. In my experience, WD SMR is implemented much better than Seagate. But for WD 8-20TB are all CMR. Seagate 10-20TB are CMR.

    +
    +
      +
    • ref: https://raid.wiki.kernel.org/index.php/Linux_Raid
    • +
    • ref 2: https://raid.wiki.kernel.org/index.php/Timeout_Mismatch
    • +
    +
    +

    In 2019, a new technology called shingled magnetic recording (SMR) started becoming mainstream. Whereas drive usage limits on conventional drives are advisory, burst limits especially on SMR drives are mandatory, and interfere with raid operation. While all manufacturers have been quietly introducing SMR on their desktop lines, WD unfortunately also introduced it on their "suitable for NAS/RAID" WD Red drives. Unfortunately, combining SMR and RAID is not a good idea, with many reports of new WD Reds simply refusing to be added to an existing array.

    +

    While conventional desktop drives (which use conventional magnetic recording or CMR) may take up to two minutes to give up reading, SMR drives are even worse - there are reports of them stalling for over 10 minutes as the drive shuffles everything around to make space.

    +

    For SMR drives, the drive should report that the trim command is supported. Unfortunately, some (many?) cheaper SMR drives do not, and due to the nature of SMR drives that don't support trim will have problems, leading to exactly the grief many have reported - the drive stalling for ever almost as it has to rewrite masses of data. Note, however, that SMR drives come in at least three types - DM (device managed) which may or may not support trimming, and HM (host managed) which shouldn't be a problem as they leave it to the computer to sort out.

    +
    +

    Types of RAID

    +
      +
    • apparently RAID5 has some risks after drive fail, mainly a second drive will possibly fail when data is being redistributed.
    • +
    • https://www.reddit.com/r/sysadmin/comments/uu8115/raid5_ideal_configuration_is_35_or_9_drives_plus/
    • +
    • RAID10 aka RAID (1+0) is recommended for 2-drive redundancy
    • +
    • Apparently SSDs are safer for RAID5 but it seems their max size is 2 TB, at 9 drives == 16TB
    • +
    • So, SSD could be technically viable with multiple RAID servers
    • +
    • However, cost is probably not viable, since 2 * 9 * $160*1.1 == $3168 for 16 TB, cost is like 6x
    • +
    +

    RAID6

    +

    Ideally use RAID6 since it has double redundancy, 2 arbitrary drives can fail, and good efficiency.

    +

    It looks like LVM directly supports RAID6, so this must be the go-to software RAID: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_logical_volumes/assembly_configure-mange-raid-configuring-and-managing-logical-volumes

    +

    The main problem with RAID6 seems to be software RAID support, BTRFS discourages it for production: https://www.phoronix.com/news/Btrfs-Warning-RAID5-RAID6

    +
      +
    • RAID6 considered unstable for btrfs: https://btrfs.wiki.kernel.org/index.php/Status#RAID56
    • +
    +

    RAID6 has 2 redundant drives, this seems good if I build a system from unreliable parts.

    +

    This seems suitable for having tons of drives. How would it work with mismatched drives, e.g. does it batch the smaller drives to bring them up to "effectively 2 redundant drives"? There must be some algorithm... e.g. if I had 1 8tb disk and 10 2 tb disks, and I have an 8tb disk, does that mean that I can still have an arbitrary disk fail and keep all my data? Or does that mean that the initial max storage calculated will be much lower for mismatch drive scenarios?

    +

    Post explaining redundancy and bad reads in a drive failure scenario, explaining why RAID5 is dangerous and RAID6 provides additional bad read redundancy in this case: https://www.reddit.com/r/DataHoarder/comments/b57u7r/at_what_point_is_raid_6_worth_it/ejbsj55/

    +

    RAID10

    +

    RAID10 is RAID1+0. It is 50% redundant and would be good for critical data storage, but I don't need that.

    +

    Expensive RAID5 server

    +

    Hard drive cost: $1534.50 +Total effective storage: 65.48 terabytes

    +
      +
    • $306.90 after tax per 18tb easystore: https://shucks.top/
    • +
    • 16.37 terabytes true storage after converting 18,000 GB by /1024/1024/1024/1024
    • +
    • (terabytes on computer are actually tib)
    • +
    • https://www.bestbuy.com/site/questions/wd-easystore-18tb-external-usb-3-0-hard-drive-black/6427995/question/833048c7-e97b-38e8-b8fe-f6e48d6aea8e
    • +
    • 5 drives and 18tb/drive = 81.85 tb
    • +
    • and 4/5 storage to redundancy = 65.48 terabytes effective
    • +
    • Cost of $306.90 * 5 + base cost of RAID server
    • +
    +

    Cheaper RAID server

    +
      +
    • Still pretty expensive, how much space do we get? Probably 8/18 * 65.48 == 29.1 TB
    • +
    • So we get 44% of the space for 60% of the cost of drives, so drives are 50% more expensive, plus the base cost
    • +
    • 8 tb easystores are typically $187 after tax
    • +
    • 5 * 187 = $935
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/crm_data_model/index.html b/docs/monographs/crm_data_model/index.html new file mode 100644 index 00000000..e62f0c54 --- /dev/null +++ b/docs/monographs/crm_data_model/index.html @@ -0,0 +1,3201 @@ + + + + + + + + + + + + + + + + Crm Data Model - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Crm Data Model

    + +

    Simple Data Model for CRM

    +

    Types of data

    +
      +
    1. Customer Organization
        +
      • Data Fields
          +
        • Date first entered into this table
        • +
        • Organization Name
        • +
        • Active?
        • +
        • Definite end date?
        • +
        • Over 10k future value?
        • +
        • Missed payment?
        • +
        • History of late payment?
        • +
        • Did we ever do a project with them?
        • +
        • Do we want to work with them again?
        • +
        +
      • +
      +
    2. +
    3. Contact @ Customer Organization
        +
      • Data Fields
          +
        • Customer Organization
        • +
        • Date first entered into this table
        • +
        • Name
        • +
        • Job Role
        • +
        • Office Phone Number
        • +
        • Cell Phone Number
        • +
        • Supervisor Name
        • +
        • Supervisor Job Role
        • +
        • Email
        • +
        • Notes
        • +
        +
      • +
      +
    4. +
    5. Interaction with Contact at Customer Organization
        +
      • Data Fields
          +
        • Customer Organization
        • +
        • Contact
        • +
        • Date of Interaction
        • +
        • Time of Interaction
        • +
        • Type of Interaction (phone, email, etc.)
        • +
        • Purpose
        • +
        • Notes
        • +
        +
      • +
      +
    6. +
    7. New Lead with Contact at Customer Organization
        +
      • Data Fields
          +
        • Contact
        • +
        • Customer Organization
        • +
        • Date
        • +
        • Source of Client (advertising, referral, website, etc.)
        • +
        • Referred By (optional)
        • +
        • Estimated Project Value
        • +
        • Estimated Client Long-Term Value
        • +
        • Contact (implies link to Customer Organization)
        • +
        • Lead Status follows a branching control flow
            +
          1. Open or Outstanding Lead
          2. +
          3. Won Lead or Dead Lead
          4. +
          +
        • +
        +
      • +
      +
    8. +
    +

    Using a spreadsheet

    +

    A sheet for each type, a row for each entry.

    +

    This can easily be exported as CSV and imported to an ORM data model.

    +

    Filters can easily be written on the fly for simple analysis in the meantime.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/debt_and_blame/index.html b/docs/monographs/debt_and_blame/index.html new file mode 100644 index 00000000..ca5c9186 --- /dev/null +++ b/docs/monographs/debt_and_blame/index.html @@ -0,0 +1,3042 @@ + + + + + + + + + + + + + + + + Debt And Blame - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Debt And Blame

    + +

    Blame is like debt. If joe owes bob $2 and bob owes sam $2, that's $4 of debt but only $2 in total transaction. We parked in a spot for breakfast this morning and the car to the left was outside the parking line. So we parked to the right. A second person parked us in to our right, so we had to pull out to enter the vehicle, which is annoying. We blamed them and they blamed us, and we blamed the person to the left. That's about 2 units of blame for one unit of bad behavior, which is analogous to the debt scenario above. Debt and blame can be expanded to fill any connected graph size, such as a whole community, both for blame and debt.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/licensing_rules/index.html b/docs/monographs/licensing_rules/index.html new file mode 100644 index 00000000..1a7b85e7 --- /dev/null +++ b/docs/monographs/licensing_rules/index.html @@ -0,0 +1,3114 @@ + + + + + + + + + + + + + + + + Licensing Rules - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Licensing Rules

    + +

    Basic Licensing Rules

    +

    This is a living document. Please add an issue if you disagree.

    +
      +
    1. +

      Does it compile? Rationale: if it is interpreted, the source is required to run the application.

      +
        +
      • This criterion should be revisited with a focusing question that focuses more on source distribution rather than the more pedantic 'compiled v interpreted' concept. Specific test cases include uglified or beautified javascript, or pyc/pyo bytecode where the work is altered but there is not a sufficient legal test framework.
      • +
      • GPL 3 - If it compiles
          +
        • Require descendant projects to use
        • +
        +
      • +
      • MIT - If it is interpreted
          +
        • Give more permissiveness
        • +
        +
      • +
      +
    2. +
    3. +

      What about business works?

      +
        +
      • Apache License - Is there a case for retaining a separate agreement for business use?
      • +
      +
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/modes-of-thought/index.html b/docs/monographs/modes-of-thought/index.html new file mode 100644 index 00000000..fbebc4c8 --- /dev/null +++ b/docs/monographs/modes-of-thought/index.html @@ -0,0 +1,3267 @@ + + + + + + + + + + + + + + + + Modes Of Thought - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Modes of Thought

    +
      +
    1. What modes are useful?
    2. +
    3. How can you enter modes?
    4. +
    +

    What modes are useful?

    +

    This is the short list I came up with based on my usual way of working.

    +
      +
    1. Task or Result Focus
    2. +
    3. Creative Focus
    4. +
    5. Flow
    6. +
    7. Diffuse Mode
    8. +
    +

    How can you enter modes?

    +
      +
    • Flow*
    • +
    • I am not sure this is a distinct mode, it may be a "Composite Mode"
    • +
    • It seems like "Task or Result Focus" with some "Creative Focus" alternating loops.
    • +
    • Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress.
    • +
    • One weakness of the mode is that you might have trouble reentering the work later.
    • +
    • Task or Result Focus:
    • +
    • gather the task requirements and get to work
    • +
    • Creative Focus
    • +
    • go to a space with no stimuli such as an empty office room
    • +
    • have tools such as notebook, whiteboard, writing tools
    • +
    • avoid going into focused mode: pin any research requirements, plan those between creative focus sessions
    • +
    • Diffuse mode:
    • +
    • anything that completely unbinds the executive mind
    • +
    • mindful meditation
    • +
    • long mindful walk
    • +
    • meandering conversation over dinner
    • +
    • read a book
    • +
    • take a nap
    • +
    • exercise if mindful
    • +
    +

    What are the modes?

    +

    Task or Result Focus

    +

    Often strongly supplemented by excel.

    +

    Examples:

    +
      +
    • Collecting a bunch of documents for taxes.
    • +
    • Correlating a data set by hand, e.g. machines with a certain image.
    • +
    • Comparing two financial alternatives to determine the risks and returns.
    • +
    +

    Creative Focus

    +

    Examples: + - doing work for a design doc

    +
      +
    1. Iteratively whiteboard and refine while the idea gains concreteness.
    2. +
    3. Capture the concrete result
    4. +
    5. Spend some time in diffuse mode
    6. +
    7. Revise
    8. +
    9. repeat diffuse & revise until requirements satisfied
    10. +
    +

    Flow

    +
      +
    • Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress.
    • +
    • I am not sure this is a distinct mode, it may be a "Composite Mode"
    • +
    • I usually run out of energy before finishing.
    • +
    +

    Examples: + - creative focus alternating with "task focus" aka coding/prototyping loop

    +
      +
    1. Jump right to prototyping and get an end to end result.
    2. +
    3. Identify the components of the result and rewrite or optimize the incomplete ones.
    4. +
    5. Continue to iterate and decompose the system components until requirements satisfied.
    6. +
    +

    Diffuse Mode

    +

    Learning how to learn: exercise, conversation, resting, what else? See notes

    +
      +
    • Mindful Meditation
    • +
    • Walking
    • +
    • Resting
    • +
    • Conversation
    • +
    • Exercise*
    • +
    • I sometimes feel that exercise does not bring me to diffuse mode, instead I am in some focused mode.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/squarespace_patterns/index.html b/docs/monographs/squarespace_patterns/index.html new file mode 100644 index 00000000..39ff2b78 --- /dev/null +++ b/docs/monographs/squarespace_patterns/index.html @@ -0,0 +1,3315 @@ + + + + + + + + + + + + + + + + Squarespace Patterns - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Squarespace Patterns

    + +

    Squarespace Patterns

    +

    A collection of concepts for developing bespoke web applications in the squarespace managed hosting framework.

    +

    View a page's available JSON by appending ?format=json-pretty to the url.

    +

    Avoid putting in credentials every git push

    +

    Manage local git config in the project directory. From this squarespace answer.

    +
      +
    • `git config credential.helper 'cache --timeout=3600'
    • +
    +

    Text blocks merge! How to prevent text blocks from merging.

    +
      +
    • Alternate text blocks with empty markdown blocks
    • +
    +

    Managing LESS and CSS

    +
      +
    • styles/reset.css - override squarespace default styles
    • +
    • styles/base.css - seems to go on each site either before or after site
    • +
    +

    Managing Editable Page Sections (inside a parent page)

    +

    Squarespace requires some acrobatics in order to display editable pages inside the main page.

    +
      +
    1. Scenario: Bespoke Theme from Designer
        +
      1. The client needs to edit the contents
          +
        • Plan: Use a squarespace index.conf. This page contains other pages. The index page will display its own template, collections/index.list which will wrap the "main content" from the Squarespace CMS. The json data available to the index.conf, primarily just title and navigation title and slug (all have similar names in the json) can also be called in the template.
        • +
        +
      2. +
      3. The client doesn't need to edit the contents
          +
        • Plan: Embed the content into the page templates
        • +
        +
      4. +
      +
    2. +
    +

    Template Management

    +
      +
    1. +

      jsont.squarespace.com

      + +
    2. +
    3. +

      developers.squarespace.com

      + +
    4. +
    5. +

      answers.squarespace.com

      + +
    6. +
    +

    User-editable sections

    +

    In order to allow to clients to edit their pages in a coherent way, it is necessary to use index pages to combine each editable page into one 'main page'.

    +

    In order to aggregate pages and collections, use an index at the top level, and use folders at subordinate levels.

    + +

    One pattern is to have headers and paragraphs of text interleaved with sections of content, for example project pages with a grid of images or a grid of logos, or a grid of contributors.

    +

    An effective pattern for working with this may be to have one collection of paragraphs and titles which are specifically indexed in teh template. These are interleaved with actual collection sections which loop over each item in the collection to populate the segment.

    + +

    Managing Templates

    + +

    Basic Template, Navigation, and Blocks

    +
      +
    • Beginner Tutorial - good intro to nav and code blocks. A little unclear at times.
        +
      • blocks/navigation.block was not being detected. I renamed it to blocks/nav.block and changed the reference to it to 'nav'.
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/ssd_vs_hdd_2023/index.html b/docs/monographs/ssd_vs_hdd_2023/index.html new file mode 100644 index 00000000..17349ee8 --- /dev/null +++ b/docs/monographs/ssd_vs_hdd_2023/index.html @@ -0,0 +1,3110 @@ + + + + + + + + + + + + + + + + Ssd Vs Hdd 2023 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    SSD vs HDD

    +

    Optimal thing is to use what I already have and optimize my current data usage.

    +

    Cost per TB-Year

    +
      +
    • Assume drive is pretty much always spun up (ZFS or mirroring).
    • +
    • Assume SSD idle cost is $0, aka $3/decade ~= .1/100024365.3410`
    • +
    • +

      Assume cost of watts is constant with inflation for the next decade, and we are working in 2023-dollars.

      +
    • +
    • +

      6 idle Watts-hours per hard drive == 6/1000 KWH / HDD

      +
    • +
    • 1 HDD * 8 Years == 6/1000 KWH/HDD * 24 hours/day * 365 days/year * 8 years == 420 KWH
    • +
    • +

      420 KWH * 0.34/KWH = $142.80 lifetime cost

      +
    • +
    • +

      $322.80 / 18TB HDD @ 8 year lifetime == $322.80 / 144 TB-YEAR == $2.24/TB-YEAR

      +
    • +
    • $150 / 4TB SSD @ 10 year lifetime == $150 / 40 TB-YEAR == $3.75/TB-YEAR
    • +
    +

    GPT-4 Analyzes the requirements

    +

    Here's the final setup:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Data TypeStorage TypeCapacityLocationSpecial Functionality
    Gaming DataM.2 NVMe SSD2TBGaming ComputerN/A
    Business DataM.2 NVMe SSD and 2.5" SSD in ZFS (mirroring)4TBLenovo ThinkCentre M910qZFS for data redundancy, Always-on
    Media DataHDD in USB-C Enclosure8TBConnected to Lenovo ThinkCentre M910qN/A
    +
      +
    • GPT-3 Recommendation: Use a external USB HDD enclosure with a smart plug, orchestrate unpowering the smart plug with unmounting the device via bash script
    • +
    • Problem: Enclosures mainly do not power on when repowered, because they don't have mechanical switches.
    • +
    • Googled solution: However, external drive bays often do. I already have 1, but it doesn't seem great for constant use... I will prototype with it.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/taking_notes_on_books/index.html b/docs/monographs/taking_notes_on_books/index.html new file mode 100644 index 00000000..0b77e59f --- /dev/null +++ b/docs/monographs/taking_notes_on_books/index.html @@ -0,0 +1,3172 @@ + + + + + + + + + + + + + + + + Taking Notes On Books - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Taking Notes On Books

    + +

    How to take notes on books

    +

    Reading and taking notes on books is time consuming and many concepts exist for making the first time you read something the last time.

    +

    Review these resources

    +
      +
    1. 1
    2. +
    3. 2
    4. +
    5. 3
    6. +
    +

    Goals

    +

    Read comprehensively the first time and ensure that key information is ingested.

    +

    My Method

    +
      +
    1. As you read, take notes in an outline. Allow the outline to take its own form. Use supporting information.
        +
      • Short Summaries
      • +
      • Key Quotes
      • +
      • Page Numbers
      • +
      • References
      • +
      +
    2. +
    3. Transcribe the outline into a markdown file. Enhance the supporting information and create a references section.
    4. +
    +

    Additional Resources

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/monographs/threat_model_test_cases/index.html b/docs/monographs/threat_model_test_cases/index.html new file mode 100644 index 00000000..38e7b415 --- /dev/null +++ b/docs/monographs/threat_model_test_cases/index.html @@ -0,0 +1,3185 @@ + + + + + + + + + + + + + + + + Threat Model Test Cases - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Threat Model Test Cases

    + +

    Possible Information Attacks for Threat-Model Building

    +

    This is an aggregation of potential information-based attacks.

    +

    This list should always be growing.

    +

    These attacks should be considered when building a threat model for information defense.

    +

    General Information Attacks

    +
      +
    1. Spying by communications and content delivery engines for sale to advertisers.
        +
      1. Types of agencies (expand and reorganize)
          +
        • Verizon, AT&T, Sprint, PCS,
        • +
        • Comcast, Sonic,
        • +
        • CDN Services
        • +
        • Internet level traffic (upstream of digital ocean)
        • +
        • Digital Ocean, AWS, storage and compute providers
        • +
        +
      2. +
      +
    2. +
    3. Business Espionage
        +
      1. Small business espionage
          +
        • cryptolocker
        • +
        +
      2. +
      3. Big Business on Small Business
          +
        • high level coordination between content storage services (gmail) and related companies (Alphabet) to use competitor data for markets of interest
            +
          • Amazon, Google, Microsoft
          • +
          +
        • +
        +
      4. +
      +
    4. +
    +

    Targeted Information Attacks

    +
      +
    1. Device tampering
        +
      1. Loss of control over physical device
      2. +
      3. Organizations tampering with physical device before transfer of ownership
          +
        • Lenovo + Superfish
        • +
        • Any government tampering
            +
          • Intel ME
          • +
          +
        • +
        +
      4. +
      +
    2. +
    3. Coercive power
        +
      1. Organizations are always in a legal jurisdiction
      2. +
      3. Organizations have parent companies
          +
        • Reddit + Conde Nast
        • +
        +
      4. +
      +
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/archiveorg_archival_zip_specs.txt b/docs/praxes/archiveorg_archival_zip_specs.txt new file mode 100644 index 00000000..d2c017b7 --- /dev/null +++ b/docs/praxes/archiveorg_archival_zip_specs.txt @@ -0,0 +1,47 @@ + +To upload a zip to archive.org +============================== +crop images to be consistent (as they should look in the book) +image filenames must be in order (from beginning to end) +rename into a zip file, eg: foo_images.zip (must end in `_images.zip`) Foo MAY need to be an indentifier, not sure. Maybe it could be anything. +To test: +======== +Go to archive.org, choose upload a file, update. +(worked) + + +Spreads: +======== +Try spreads for cropping, white balance, etc. +spreads - modular workflow assistant - https://github.com/DIYBookScanner/spreads + + +after uploading: +================ +you can check at the unique identifier of your item uploaded +after 2 hours, maybe ask gio to check what's going on +anyone who creates an archive.org account can upload a book + + +If I start uploading a lot of books: +==================================== +archive.org can give me a collection which is a folder with all my contents +This would be for multiple people to share in an org, so we could have a noisebridge-digital-archivists collection +Gio can do this for me in about 5 minutes when I am ready. They don't give the feature out to the public quite yet. +Only users with at least 150, but for Noisebridge they can just do it. +We could definitely use this for the Noisebridge datastore. + +We could also share a user - noisebridge-books-bot for example. + + +timeline: +========= +200 book page takes hours - there are often 1200 books in the pipeline +if something never comes out, gio can give me feedback +if something is broken, gio can give feedback + + + +white balance: +=============== +archive uses a color card in the photo and a robot balances this to white in software diff --git a/docs/praxes/audio_to_wav_via_ffmpeg/index.html b/docs/praxes/audio_to_wav_via_ffmpeg/index.html new file mode 100644 index 00000000..d2c91162 --- /dev/null +++ b/docs/praxes/audio_to_wav_via_ffmpeg/index.html @@ -0,0 +1,3141 @@ + + + + + + + + + + + + + + + + Audio To Wav Via Ffmpeg - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Audio To Wav Via Ffmpeg

    + +

    Convert audio to 1 channel wav for DeepSpeech

    +

    It is remarkable that recording sound is the hard part of DeepSpeech.

    +

    With deepspeech installed in a virtualenv, do the following.

    +

    Recording audio

    +

    macos: get a m4a format audio with quicktime

    +

    Use ffmpeg

    +
      +
    1. Get ffmpeg: brew install ffmpeg or apt install ffmpeg
    2. +
    3. Convert to single channel 192kbps: $ ffmpeg -i ~/Desktop/test_audio.m4a -ac 1 -ab 192k ~/Desktop/test.wav
    4. +
    5. Run the demo: deepspeech models/output_graph.pb ~/Desktop/test.wav models/alphabet.txt
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/backup_mgmt_with_s3_glacier/index.html b/docs/praxes/backup_mgmt_with_s3_glacier/index.html new file mode 100644 index 00000000..1a7c6766 --- /dev/null +++ b/docs/praxes/backup_mgmt_with_s3_glacier/index.html @@ -0,0 +1,3245 @@ + + + + + + + + + + + + + + + + Backup Mgmt With S3 Glacier - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Backup Management with S3 Glacier

    +

    The most economical bulk offsite storage for a few terabytes of data in 2022 is AWS S3 Glacier Flexible Retrieval with bulk data retrieval. The bulk retrieval parameter must be specified during data restore and will take up to 12 hours for retrieval.

    +

    Note: Glacier deep archive could be 10x more economical but carries risks. Bulk restore costs are 0.025 per 1000 objects and 0.0025 per GB.

    +

    Future: Model glacier deep archive costs. 10x cheaper is huge. If objects can be reduced by using zip, then this would only cost about $2.50 per terabyte.

    +

    How to set up a bucket with glacier

    +

    TODO, did this manually in the past, write a terraform module.

    +

    How to restore all objects in a bucket

    +

    There is no recursive restore option. Restore must be implemented.

    +

    The following implementation was tested separately but not as a single script as below. Parallelism can probably be increased, consider logging object name each attempt to stdout as well

    +

    The flag --restore-priority=bulk was also not tested but will save cost so has been added.

    +
    #!/bin/bash
    +
    +set +ex
    +
    +# Execute this script and capture errors to a file, then grep the file for error types
    +# ./restore-glacier-object-list.sh > restore-results-my-bucket.txt 2>&1
    +
    +BUCKETNAME="my-bucket"
    +
    +# grep this file for NoSuchKey or other errors
    +FILENAME="glacier-restore-$BUCKETNAME.txt"
    +
    +# read all the glacier object paths and store them in a file, one line per object
    +aws s3api list-objects-v2 --bucket $BUCKETNAME --query "Contents[?StorageClass=='GLACIER']" --output text | awk 'BEGIN {FS="\t"}; {print $2}' > $FILENAME
    +
    +# consume the file, this parallelism cap is defensive to avoid too many concurrent requests to aws, consider much more, perhaps 10x as many if your machine will support it.
    +parallel -j 30 -q -a $FILENAME aws s3api restore-object --restore-request Days=7 --restore-priority=bulk --bucket "$BUCKETNAME" --key "{}"
    +
    + +

    How to download a restored object

    +

    After 12 hours, all objects are guaranteed (by AWS) restored. This is for "bulk" retrieval, as depicted above.

    +

    The flag --force-glacier-transfer must be used to download objects with aws cli.

    +

    Verify files or add new files to the bucket: s3 sync with the existing bucket

    +

    These 2 operations will verify the size and timestamp parameters match.

    +

    WARNING: Sync is destructive for the destination if the timestamp is older or the size is incorrect.

    +

    Format below is .

    +

    Below, we first sync to the bucket, then we sync from the bucket. This considers any local change should overwrite or update new objects to the bucket, then the second command downloads objects that are in the bucket that don't exist locally.

    +
      +
    • cd my-bucket; aws s3 sync --force-glacier-transfer . s3://my-bucket
    • +
    • cd my-bucket; aws s3 sync --force-glacier-transfer s3://my-bucket .
    • +
    +

    Note: You may wish to use the flag --size-only if files repeatedly transfer. There is a documented bug in some related to filenames with special characters causing files to resync, and timestamps are typically not relevant if size is the same size for backups and backups flow into the backup space from user space, although not universally true, especially if you have multiple user spaces flowing into a backup that need reconciled.

    +

    Sync new files to the bucket without considering glacier objects

    +

    Typically archive updates are additive, so we don't want to affect what's already in the archive. It saves time and prevents errors to avoid enumerating what was changed, so aws s3 sync is preferred. This

    +
      +
    • cd my-bucket; aws s3 sync . s3://my-bucket --size-only
    • +
    • --size-only is optional, it excludes date comparison. This helps avoid accidental updates if your local files have a date change without content change
    • +
    +

    Deleting from a bucket with sync

    +

    NOT RECOMMENDED for operating on buckets that contain source of truth (only use for cache buckets).

    +

    Consider deleting the individual objects using s3 rm instead of trying to delete with sync.

    +

    Deleting with sync is very dangerous because it removes any files in that are not in .

    +
      +
    1. before removing the files from local, sync from the bucket to local. Otherwise files added to the bucket from somewhere else would be deleted, since they aren't yet in local.
    2. +
    3. remove the desired files from local
    4. +
    5. run another s3 sync with the --delete flag. WARNING, this could delete any remote file not on your local. Not advised for backup operations.
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/budget-building-101/index.html b/docs/praxes/budget-building-101/index.html new file mode 100644 index 00000000..ac8ff695 --- /dev/null +++ b/docs/praxes/budget-building-101/index.html @@ -0,0 +1,3249 @@ + + + + + + + + + + + + + + + + Budget Building 101 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Budget Building 101

    +

    An introductory course on building a budget in Google Sheets. You can modify the included template for your own budget, try to avoid changing the calculations in some of the cells.

    +

    The template assumes a monthly income of $4092 based on a pretax salary of $70,000. The income does not take into account the 2 months you get 3 paychecks (26 paychecks in a 52 week year).

    +

    If you want to include the two extra checks in your choice making, simply take your salary after tax and divide it by 12. Figuring tax is annoying but you can figure it from your paycheck by taking your hourly earnings * hours and subtracting what you were actually paid. This is approximately your tax rate, but is not fully accurate. It also includes certain things your company gives you that are considered 'income', like a life insurance policy with them as the beneficiary that you pay for. That's late stage capitalism!

    +

    Template

    +

    Click the link to view the template. Make yourself a copy of this sheet and work from your copy.

    +

    https://docs.google.com/spreadsheets/d/1YHzrjfVjtNEITDNScakGoeyWAFbc789iKEZDwCndXn0/edit?usp=sharing

    +

    Incomplete How To

    +

    You can adjust this document to fit your needs, mostly adding new lines and deleting items you do not need. Make sure to copy and paste the calculations that go on each line.

    +
      +
    1. Make yourself a copy of the google sheet template listed in the Template section.
    2. +
    3. Add your income
        +
      • Multiply your BIWEEKLY paycheck by 2 and put it in the monthly income box.
      • +
      +
    4. +
    5. Add your expenses
        +
      • Use your debit card and credit card records
      • +
      • Review your checking account
      • +
      • Save receipts and enter them into the Transaction Log Optional to calculate unknown spends.
      • +
      • Your expenses might be fixed or variable. If it changes, just do your best.
      • +
      • Be as accurate as your decisions need you to be.
      • +
      +
    6. +
    7. Review and keep adding expenses (forever)
        +
      • The budget is a living document you should review regularly as a habit.
      • +
      • I review my budget when I get paid or before I consider a medium to large purchase.
      • +
      +
    8. +
    +

    Budget Categories

    +

    I used some categories in the spreadsheet:

    +
      +
    1. Core Budget Spend
        +
      • rent, electric, internet, water, phone, prescriptions, transit to work
      • +
      +
    2. +
    3. Debt Spend
        +
      • Student loans, credit cards, QUANTIFY IT
      • +
      +
    4. +
    5. Savings Spend
        +
      • Save a little, you will need it
      • +
      • Helps in employment negotiations too... you can afford to say no to a bad offer...
      • +
      +
    6. +
    7. Hygeine Spend
        +
      • Gotta brush those teeth
      • +
      +
    8. +
    9. Subscriptions Spend
        +
      • Netflix, Hulu, Spotify, New York Times, etc.
      • +
      +
    10. +
    11. Nonessential Spend
        +
      • Fun, uber/lyft, transit to fun, nail salon, etc.
      • +
      • Some things listed above can have an essential component
      • +
      • What if you have to uber to work because you would be late? goes in essential spend as a seperate uber line item than 'fun and nonessential'
      • +
      +
    12. +
    13. De-Annualized Spend
        +
      • Annual or non-monthly events - flights home, non-routine dr visits.
      • +
      +
    14. +
    15. Donations Spend
        +
      • Noisebridge, EFF, etc.
      • +
      +
    16. +
    +

    Making Spending Judgments

    +

    If something is a high percent of my income, I try to bring it down. There are different strategies for everything, it usually just comes down to two things:

    +
      +
    1. Adjust your habits
        +
      • Eating a $12 lunch at work every day costs $3120 per year - pack your lunch - or quit... just kidding
      • +
      • Find more things like this, especially daily or weekly habits that cost you.
      • +
      +
    2. +
    3. Shop Around
        +
      • Stop buying books and games and instead make a list of what you already have, read the top priority on that
      • +
      +
    4. +
    +

    Transaction Log

    +

    You can play around with this.

    +

    It also helps to have different transaction logs for different categories.

    +

    Don't let perfect be the enemy of good, it is hard to capture everything, be approximate where necessary, get precise if it is a big part of your budget.

    +

    I recommend doing it for at least a few months by saving every single receipt. It will help you capture more interesting budget line items that you use every day like 'deoderant', 'toothpaste', 'dish soap'.

    +

    As you start to track your spend, you might find more reasons to buy things in bulk as your finances allow, as the savings will be more apparent. No more 4 ounce bottles of dish soap at the bodega.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/docker-jupyter-datasciencenotebook/index.html b/docs/praxes/docker-jupyter-datasciencenotebook/index.html new file mode 100644 index 00000000..4d17223f --- /dev/null +++ b/docs/praxes/docker-jupyter-datasciencenotebook/index.html @@ -0,0 +1,3279 @@ + + + + + + + + + + + + + + + + Docker Jupyter Datasciencenotebook - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Guide for using the Jupyter datascience-notebook with Docker

    +

    (brew must be installed; cask must be installed) +brew cask install docker

    +

    Quick References

    +

    I guess what I would really like is one of these with sage math?

    +
      +
    • Guide covers this notebook
        +
      • Jupyter Notebook 5.2.x
      • +
      • Conda Python 3.x environment
      • +
      • pandas, matplotlib, scipy, seaborn, scikit-learn, scikit-image, sympy, cython, patsy, statsmodel, cloudpickle, dill, numba, bokeh pre-installed
      • +
      • Conda R v3.3.x and channel
      • +
      • plyr, devtools, shiny, rmarkdown, forecast, rsqlite, reshape2, nycflights13, caret, rcurl, and randomforest pre-installed
      • +
      • The tidyverse R packages are also installed, including ggplot2, dplyr, tidyr, readr, purrr, tibble, stringr, lubridate, and broom
      • +
      • Julia v0.6.x with Gadfly, RDatasets and HDF5 pre-installed
      • +
      • Unprivileged user jovyan (uid=1000, configurable, see options) in group users (gid=100) with ownership over /home/jovyan and /opt/conda
      • +
      • tini as the container entrypoint and start-notebook.sh as the default command
      • +
      • A start-singleuser.sh script useful for running a single-user instance of the Notebook server, as required by JupyterHub
      • +
      • A start.sh script useful for running alternative commands in the container (e.g. ipython, jupyter kernelgateway, jupyter lab)
      • +
      +
    • +
    • Jupyter Notebook Shortcuts
    • +
    +

    Steps

    +

    I recommend doing this from your home internet. It is about 2 GB.

    +
      +
    1. brew cask install docker
    2. +
    3. run docker (open spotlight search or press CMD+space, and type docker)
    4. +
    5. docker should be running in the top bar of the mac
    6. +
    7. docker pull jupyter/datascience-notebook . (2 GB)
    8. +
    9. docker images - see what's installed
    10. +
    11. docker run -p 8888:8888 jupyter/datascience-notebook
    12. +
    +

    Go to the URL it spits out (in iterm you can command+click the URL to open it in your browser)

    +

    Part II

    +

    ssh into your docker container.

    +
      +
    1. docker ps get the name of your container
    2. +
    3. docker exec -it /bin/bash
    4. +
    5. use generically: `docker exec -it
    6. +
    7. that home directory seems to be where notebooks go or something
    8. +
    9. i put a text file in jovyan@e47f8b66eea3:~/work/ and could see it
    10. +
    +

    Resources

    +

    This is based on the docker-stacks

    +

    The following is a summary of the linked diagram. The diagram is a superior explanation.

    +

    Docker stacks are very interesting: +1. tensorflow-notebook +1. datascience-notebook +1. pyspark-notebook --> all-spark-notebook

    +

    All these notebooks are based on the scipy-notebook, which is ubuntu base-notebook based. (And all descend from minimal-notebook).

    +

    There is a separate r-notebook

    +

    found on this list of notebooks:

    +
      +
    • https://hub.docker.com/r/jupyter/notebook/
    • +
    +

    i did not review all the docker containers that jupyter manages

    +
      +
    • https://hub.docker.com/u/jupyter/
    • +
    +

    Planet Labs maintains notebooks too!

    +
      +
    • https://github.com/planetlabs/notebooks
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/ergonomic-eval-alameda-20180228/index.html b/docs/praxes/ergonomic-eval-alameda-20180228/index.html new file mode 100644 index 00000000..f56f91c4 --- /dev/null +++ b/docs/praxes/ergonomic-eval-alameda-20180228/index.html @@ -0,0 +1,3268 @@ + + + + + + + + + + + + + + + + Ergonomic Eval Alameda 20180228 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Ergonomic Eval Alameda 20180228

    + +

    Ergonomic Assessment from Alameda County

    +

    Evaluator: Alfonso Mejorado, Associate Ergonomist +Company: VSI Risk Management and Ergonomics, Inc. +note: same company hired by Genentech

    +

    Focus

    +

    The focus of the ergonomic evaluation is my desk work.

    +

    Problems

    +
      +
    1. Radial Deviation and Ulnar Deviation are common issues I face
        +
      • Try not to rest wrists while typing, especially on the far right of the keyboard where I am weak.
      • +
      • When I plant my hand while deviating, it causes contact stress at the base of the hand.
      • +
      +
    2. +
    3. Seat bucket too deep, pressure on middle of thighs.
    4. +
    5. Seatback greater than 100 degrees moving me away from the desk.
    6. +
    +

    Behavioral Corrections

    +
      +
    1. When sitting, move forwards: RULE: Elbow, Shoulder, Ear should be VERTICALLY aligned
        +
      • I tend to always move my butt too far back which means my arms have to reach.
      • +
      • I do not want to reach with my arms because I end up planting my wrists and hunching my shoulders.
      • +
      +
    2. +
    3. Do not plant palms, too much contact stress.
    4. +
    5. Move the mouse as close to center as possible
        +
      • Avoid Right Shoulder Abduction when using the mouse
      • +
      +
    6. +
    7. Use TWO possible resting hand positions:
        +
      1. Hands resting on 'meat' of hand below pinkie 'extra padding below pinkie`
      2. +
      3. Hands resting in lap (neutral)
      4. +
      +
    8. +
    9. Do not PLANT the wrist forcefully, especially during radial and ulnar deviation.
    10. +
    11. Try to always free type, I think this means have your wrists up? Or maybe it was free flow type?
    12. +
    13. 90 degree sitting angle is an active posture using the muscles. This is good.
    14. +
    15. 100 degree sitting angle is relaxed but not moving you away from the desk. This is good.
        +
      • Requires seatback to be positioned for 100 degree resting angle.
      • +
      +
    16. +
    17. Always put my notebook on the right side so I don't twist when writing and reading from it.
    18. +
    + +
      +
    1. Hands turned in, extra padding below pinkie resting on keyboard rest
    2. +
    3. Shoulders fully at rest on arm wrests
    4. +
    5. Feet planted at 90 degrees on the ground
    6. +
    7. Back at 100 degrees resting on the backrest
    8. +
    9. Do not plant palms.
    10. +
    +

    Equipment Fixes

    +
      +
    1. Armwrests must not contact the desk (push them back)
        +
      • Otherwise they may prevent me from moving close to the desk.
      • +
      +
    2. +
    3. Armwrests should be below my neutral elbow height when typing and just barely high enough to fully REST shoulders when resting hands.
    4. +
    5. Move my coding screen up much higher so it is near the center of my vision
        +
      • Alfonso: "Coders always work at the bottom of their screen"
      • +
      • This can cause some right neck and shoulder issues (due to turning head and looking down?)
      • +
      • Use reams of paper to move the screen up
      • +
      +
    6. +
    7. Seatpan is moved as far forward as possible to support the mid thigh and prevent cut-off bloodflow.
        +
      • This is to avoid numbness in the legs and feet.
      • +
      +
    8. +
    9. Fix right armrest (this one is broken)
    10. +
    11. Use a "RFM Internet High-Back Chair": http://rfmseating.com/portfolio-view/internet/
        +
      • +
      +
    12. +
    13. Mouse is too narrow and activating my finger flexons or something. I am planting my hand while mousing in an ulnar deviation. BAD.
        +
      • Replace mouse with a wider one, Kensington Slim Blade Trackball and a blue mouse slider identical to my Genentech one.
      • +
      +
    14. +
    +

    Future Fixes (recommendations)

    +
      +
    1. Get a "Workright Electric Sit Stand Desk" - Needs approved and delivered
    2. +
    3. Repair the right armwrest of the "RFM Internet High-Back Chair"
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/exercise-calories-burning-reference/index.html b/docs/praxes/exercise-calories-burning-reference/index.html new file mode 100644 index 00000000..00ad3695 --- /dev/null +++ b/docs/praxes/exercise-calories-burning-reference/index.html @@ -0,0 +1,3360 @@ + + + + + + + + + + + + + + + + Exercise Calories Burning Reference - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Calories

    +

    General guide to calorie facts.

    +

    You use your bmr to determine how many calories you can eat.

    +

    There is a variance of 25% between individuals so you basically MUST build an empirical baseline for yourself.

    +

    Start at the low end of your calorie intake for a few weeks, then slightly adjust to achieve your ideal weight loss based on calorie expense. You should lose 1-2 lbs, but more importantly, that should be pretty consistent each week (aka NOT 1.2 lb then 1.8 lb then back to 1.2 lb).

    +

    How many calories do I burn in a day?

    +

    Calorimetry Device

    +

    Online BMR tests with rigid formulas are not the most accurate method of determining an individual's BMR. It is better to consult a certified specialist or measure BMR through a calorimetry device. These handheld devices are available in many health and fitness clubs, doctor offices, and weight-loss clinics.

    + +
    +

    Results from a hand-held calorimeter were similar to those obtained from metabolic cart studies. The Douglas bag method compared to the MedGem indicated a significant agreement with a p=0.286. The hand-held device compared to metabolic carts in 9 studies with mixed results. The predictive equations (Harris-Benedict, Mifflin St. Joer and FAO/WHO equations) were found to over and underestimate RMR compared to the MedGem. The Harris-Benedict was found to overestimate the RMR by 3-11%, the Mifflin St Joer equation overestimated the RMR by 1% and the FAO/WHO equation overestimated RMR by 12%.

    +

    Total energy expenditure (TEE) consists of three major components: basal metabolic rate (BMR), thermogenic effect of food, and the effect of physical activity or exercise.1 Basal metabolic rate is defined as the measurement of resting energy expenditure under the following conditions: a state of complete rest, ambient temperature is between 68° to 77° Fahrenheit. The subject is tested immediately upon waking after a minimum of a four hour sleep and in a post-absorptive state (12 hours after a meal). Thermogenic effect of food refers to the heat the body generates as food is digested. Physical activity is any activity in which work is performed which results in an increase in metabolic rate. Resting metabolic rate (RMR), which is synonymous with resting energy expenditure (REE), is not measured under basal conditions. It is a measurement taken during a fast (two to four hours after a meal) and allows for some movement with a rest period prior to testing.1,2 The RMR is usually higher than the BMR due to less restrictive conditions for measureing RMR. Therefore, basal metabolic rate accounts for 60- 75% 1 of TEE while RMR accounts for 50-70% of TEE.. Since the difference between BMR and RMR is only about 10%, it is more practical to measure RMR in a clinical setting.2 In clinical settings RMR is used to determine accurate energy expenditure of a patient's caloric needs. Resting metabolic rate can be measured either directly or indirectly.

    +
    +

    trent: the medgem seems fine until you have any deviation from normal including old age - see the details inside the study...

    +

    Harris-Benedict Formula

    +

    Calculator.net Calculations

    +
    +

    Muscle Mass – Aerobic exercise such as running or cycling has no effect on BMR. However, anaerobic exercise, such as weight-lifting, indirectly leads to a higher BMR because it builds muscle mass, increasing resting energy consumption. The more muscle mass in the physical composition of an individual, the higher the BMR required to sustain their body at a certain level.

    +
    +
      +
    • my bmr: 1955 calories / day
    • +
    • +

      calculator.net bmr calculator

      +
    • +
    • +

      men: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) + 5

      +
    • +
    • women: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) - 161
        +
      • Why do you just subtract a constant from the men's BMR to get the womens' BMR? This seems like bullshit.
      • +
      +
    • +
    +
    My Calorie Calculator
    +

    Using this calculator.net calculator

    +
      +
    • 3031 calories to maintain weight
    • +
    • 2531 calories to lose 1 lb per week
    • +
    • 2031 calories to lose 2 lb per week
    • +
    +
    How do I think about this?
    +

    Well, the BMR calculator said 1955, so 2031 - 1955 = 76 excess calories before factoring in exercise.

    +

    The resting exercise state is 1.2x and my moderately active state is 1.55x. 1.55-1.2 = 0.35x.

    +

    1955 * 0.35x = 684 calories/day spent to exercise related behavior

    +
    My Ideal Weight
    +

    Using this calculator.net calculator

    +
      +
    • Based on the Robinson formula (1983), your ideal weight is 177.5 lbs
    • +
    • Based on the Miller formula (1983), your ideal weight is 170.5 lbs
    • +
    • Based on the Devine formula (1974), your ideal weight is 186.3 lbs
    • +
    • Based on the Hamwi formula (1964), your ideal weight is 195.1 lbs
    • +
    • Based on the healthy BMI recommendation, your recommended weight is 148.0 lbs - 200.0 lbs
    • +
    +

    Healthline calculations

    +

    based on: https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula

    +
      +
    • BMR: Basal Metabolic Rate
        +
      • Sex, Age, Weight
      • +
      • men: 66 + 6.2 x weight + 12.7 x height + 6.76 x age = BMR for men
      • +
      • women: 655.1 + 4.35 x weight + 4.7 x height + 4.7 x age = BMR for women
      • +
      +
    • +
    • This is insane
        +
      • so a person with more fat needs more calories? shouldn't it be by lean bodymass?
      • +
      • An older person needs 50 more calories per decade??
      • +
      +
    • +
    • trent: 66 + 6.2 x 205 lbs + 12.7 x (12 x 6 + 3) + 6.76 x 34 = 66 + 1271 + 952.5 + 229.84 = 2519.34
    • +
    • activity level is moderately active (mod exercise 3-5 days per week)
        +
      • but I do hard exercise 3-5 days per week... which there is no choice for... kinda bullshit so you can only exercise hard 6-7 days per week...
          +
        • but, the difference is 1.55 versus 1.725 so i could fudge this constant easily...
        • +
        +
      • +
      +
    • +
    • total calories = 2519.34 * 1.55 = 3904.98 calores per day
        +
      • This is truly insane and I have no faith in this number
      • +
      +
    • +
    +

    BMR Effects

    +
      +
    • Cold environments raise BMR, external heat raises BMR (body trends towards homeostasis)
    • +
    • Starvation reduces BMR negatively impacting weight loss -- along with many negative effects: physical, psychological, permanent damage
    • +
    • Caffeine is supposed to raise BMR
    • +
    +

    References

    +

    If there are inconsistencies, prefer better vetted literature. Use more than one source for all facts!

    +
      +
    • https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/exercise-heart-rate-reference/index.html b/docs/praxes/exercise-heart-rate-reference/index.html new file mode 100644 index 00000000..27751fe1 --- /dev/null +++ b/docs/praxes/exercise-heart-rate-reference/index.html @@ -0,0 +1,3437 @@ + + + + + + + + + + + + + + + + Exercise Heart Rate Reference - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Exercise Heart Rate Calculations

    +

    Maximum Heart Rate

    +

    WARNING: This heart rate is your absolute MAXIMUM and could cause damage.

    +

    It may also be EVEN LOWER for you than the calculations, it's just an AVERAGE, so DON'T reach this heart rate.

    +
    +

    But reaching your MAXIMUM HEART RATE—the greatest number of beats per minute your heart can possibly achieve during exercise—requires an all-out effort that is extremely uncomfortable and impossible to maintain; even the most highly trained athletes can only maintain this intensity for a few minutes at a time. In addition, exercising at or near your maximum heart rate has not been shown to have significant benefits. In fact, it can actually be risky because of the stress it puts on your heart. (1)

    +
    +

    Reserve Heart Rate

    +

    You can get a more accurate picture by using the 'reserve heart rate' method from The Mayo Clinic.

    +

    Your reserve heart rate is: Maximum Heart Rate - Resting Heart Rate

    +

    Get your resting heart rate

    +
      +
    1. Get a stopwatch (try on your phone)
    2. +
    3. "Rest" for a few moments.
    4. +
    5. Put your finger on your pulse (I use my neck)
    6. +
    7. Start the timer on a beat, and count beats for 60 seconds.
        +
      • The number of beats per 60 seconds is your resting heart rate.
      • +
      +
    8. +
    9. "The American Heart Association recommends checking your resting heart rate first thing in the morning (but before you get out of bed." 1
    10. +
    +

    Target Heart Rate Range

    +

    Your Target Heart Rate (THR) Range is generally 70 to 85 percent of your maximum heart rate, although it is based on you individually and there are a few ways to calculate it.

    +

    IMPORTANT: There's no evidence that being at the high or low range of your Target Heart Rate is better...

    +
    +

    By knowing your TARGET HEART RATE you assure yourself that you optimize fitness improvement, calorie- and fat-burning, and you prevent overdoing it and not having fun during exercise. (1)

    +
    +

    How to improve at cardio

    +

    There is no reason to push your heart rate beyond the target range during non-competitive exercise. It is bad to go too close to the max at any time.

    +

    Going above your Target Heart Rate Range increases risk of damage.

    +

    If you want to push yourself then: increase the TIME you are at your target heart rate.

    +

    Calculate Target Heart Rate Range: Reserve Heart Rate Method

    +

    This method takes into account age and base heart rate. The method is from the Mayo Clinic.

    +

    Lets check target at some regular ages assuming 65 BPM Resting Heart Rate (RHR).

    +
      +
    • 20 YRS : (220-20-65)*.7+65 to (220-20-65)*.85+65 = 160-180
    • +
    • 30 YRS : (220-30-65)*.7+65 to (220-30-65)*.85+65 = 153-171
    • +
    • 40 YRS : (220-40-65)*.7+65 to (220-40-65)*.85+65 = 146-163
    • +
    • 50 YRS : (220-50-65)*.7+65 to (220-50-65)*.85+65 = 139-154
    • +
    • 60 YRS : (220-60-65)*.7+65 to (220-60-65)*.85+65 = 132-146
    • +
    • 70 YRS : (220-70-65)*.7+65 to (220-70-65)*.85+65 = 125-137
    • +
    • 80 YRS : (220-80-65)*.7+65 to (220-80-65)*.85+65 = 118-129
    • +
    +

    Lets also check with a heart rate of 80 BPM. Note that a high heart rate increases all cause mortality, and you should seek to have a heart rate between 60-75 through physical fitness

    +

    I don't love this one because it recommends people with higher resting heart rates need to reach a higher Target Heart Rate. I think this comes from lack of fitness, so it's sort of crummy advice to tell someone out of shape they need to work harder.

    +

    But the range is pretty close between both. My heart rate is very stable at my level of exertion at the gym, so each individual can figure out their comfortable level on a per-machine basis.

    +
      +
    • 20 YRS : (220-20-80)*.7+80 to (220-20-80)*.85+80 = 164-182
    • +
    • 30 YRS : (220-30-80)*.7+80 to (220-30-80)*.85+80 = 157-174
    • +
    • 40 YRS : (220-40-80)*.7+80 to (220-40-80)*.85+80 = 150-165
    • +
    • 50 YRS : (220-50-80)*.7+80 to (220-50-80)*.85+80 = 143-157
    • +
    • 60 YRS : (220-60-80)*.7+80 to (220-60-80)*.85+80 = 136-148
    • +
    • 70 YRS : (220-70-80)*.7+80 to (220-70-80)*.85+80 = 129-140
    • +
    • +

      80 YRS : (220-80-80)*.7+80 to (220-80-80)*.85+80 = 122-131

      +
    • +
    • +

      Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE

      +
        +
      • WARNING: This heart rate is your absolute MAXIMUM and could cause damage.
      • +
      • It may also be EVEN LOWER for you, it's just an AVERAGE.
      • +
      +
    • +
    • Reserve Heart Rate (HRR) @ 34 years (MHR-HRR): 186 - 66 = 120 BPM
        +
      • This is how much you have "left over" between your resting and your max.
      • +
      +
    • +
    • +

      Target Heart rate is approximately 70%-85% of Max Heart Rate, based on HRR: (186-66) * (70% to 85%) + 66 = 150 - 168 BPM

      +
        +
      • The exact calculation is HRR * (70% to 85%) + RHR = THR Range
          +
        • Think of it as using 70-85% of your reserve
        • +
        +
      • +
      • This is the range for an intense workout
      • +
      • I currently like to switch between 70% to 85% every 5 min for 25 min, this gives me some recovery.
      • +
      • I tend to stick closer to 146 right now, I consider 154 to be a really heavy workout.
      • +
      • I hit this something like 8 minutes into the workout? I measure what is a comfortable and natural ramp.
      • +
      +
    • +
    • +

      Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm

      +
        +
      • I easily hit this and warm up quite comfortably to 120 BPM within a few minutes
      • +
      • I think this is too low, but it is for mild exercise at 150 minutes per week
      • +
      • If I did moderate exercise I would do 150 mins per week, or 50 minutes per session at 120 BPM.
      • +
      +
    • +
    +

    Calculate Target Heart Rate Range: with General Method

    +

    This method takes into account age only and NOT resting heart rate. Lets check target against the resting method at some regular ages. These ranges are a lot broader and don't go nearly as high.

    +
      +
    • 20 YRS : (220-20)*.7 to (220-20)*.85 = 140-170
    • +
    • 30 YRS : (220-20)*.7 to (220-20)*.85 = 133-162
    • +
    • 40 YRS : (220-20)*.7 to (220-20)*.85 = 126-153
    • +
    • 50 YRS : (220-20)*.7 to (220-20)*.85 = 119-145
    • +
    • 60 YRS : (220-20)*.7 to (220-20)*.85 = 112-136
    • +
    • 70 YRS : (220-20)*.7 to (220-20)*.85 = 105-128
    • +
    • +

      80 YRS : (220-20)*.7 to (220-20)*.85 = 98-119

      +
    • +
    • +

      Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE

      +
        +
      • WARNING: This heart rate is your absolute MAXIMUM and could cause damage.
      • +
      • It may also be EVEN LOWER for you, it's just an AVERAGE.
      • +
      +
    • +
    • +

      Target Heart rate is 70%-85% of Max Heart Rate: 186 * (70% to 85%) = 130 - 158 BPM

      +
        +
      • You want to spend your workout in this range... but how much time at each part of the range? I like to alternate every 5 min for 25 min.
      • +
      • I hit this something like 8 minutes into the workout? Measure what is a comfortable and natural ramp.
      • +
      +
    • +
    • +

      Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm

      +
        +
      • I easily hit this and warm out quite comfortably to 120 BPM within a few minutes
      • +
      +
    • +
    +

    Intensity and Time Span

    +

    Summary: 150 min moderate exercise or 75 min vigorous exercise per week. Use the Rating of Perceived Exertion or 'borg' scale.

    +

    Intensity

    +

    You can use relative intensity to measure your workout. You are the judge of the intensity in this system. You probably need some experience to make this accurate.

    +

    The primary scale has two names: Borg Scale and Rating of Perceived Exertion (RPE) Scale.

    + +
    +

    Studies show that your perceived exertion compares well with your heart rate. So if you think you're working hard, your heart rate is probably higher than usual. (1)

    +
    +

    Time Span

    +

    The Mayo Clinic recommends every week do one of the following:

    +
      +
    1. 150 minutes of moderate aerobic activity or
    2. +
    3. 75 minutes of vigorous aerobic activity
    4. +
    +

    You may need to work up to vigorous aerobic activity. I certainly did in 2018.

    +

    You should also do:

    +
      +
    1. 2 strength training sessions - per week
        +
      • (including rock climbing, "heavy gardening")
      • +
      • Free weights are ideal
      • +
      • Weight machines
      • +
      +
    2. +
    +

    References

    +
      +
    1. CALCULATING YOUR TARGET HEART RATE
        +
      • This is the reference for some of these facts, and it has no citations.
      • +
      • Please verify ALL data with the AHA or other entity and remove this reference. I have read similar things elsewhere, but that's not a substitute for real citations.
      • +
      +
    2. +
    3. CDC Exercise Guide
    4. +
    5. CDC Activity Intensity
    6. +
    7. CDC Heart Rate Method
    8. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/git-make-diff-patch/index.html b/docs/praxes/git-make-diff-patch/index.html new file mode 100644 index 00000000..c9ce80a8 --- /dev/null +++ b/docs/praxes/git-make-diff-patch/index.html @@ -0,0 +1,3197 @@ + + + + + + + + + + + + + + + + Git Make Diff Patch - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Git Patch and General Patching

    +

    General patching, especially wrt git repositories, both:

    +
      +
    1. Committed Changes
    2. +
    3. Uncommitted Changes
    4. +
    +

    Processes

    +

    Some processes are listed below.

    +
      +
    1. Patch between two directories with diff/patch - NO SCM REQUIRED!
        +
      • No need for git, you can keep your files in a signed tarball. Not as useful in a world with popular, collaborative SCM tools.
      • +
      +
    2. +
    3. Patch individual files with git diff/patch.
        +
      • You could actually diff two different files, but in this case it's easier to git diff between the file at HEAD and the current file.
      • +
      +
    4. +
    5. Patch a git repository by applying actual commits with git diff/git apply
        +
      • A similar process exists for SVN but is not detailed below, it can also be used to push patches from git to SVN.
      • +
      +
    6. +
    +

    Individual Files and Uncommitted Changes: Use the patch command

    +

    This process does not require a git repository. You just need two files (or groups of files) to diff to get the output. Then anyone can apply the diff to the old file to get the new one.

    +
      +
    1. Make the patch in the desired directory: git diff --no-prefix > some-feature.diff
        +
      • This git feature can provide output that patch can use.
      • +
      • If you are using git: Find where you want to patch from and check the commit out headless, then you can proceed as if the changes are uncommitted (using patch).
      • +
      +
    2. +
    3. Apply the patch in the same directory: patch < some-feature.diff
        +
      • This is not a git feature, it only interacts with the filesystem.
      • +
      +
    4. +
    +

    Committed Changes: Use the git apply command

    +

    This process requires a git repository. You can patch commit history onto another .git instance.

    +
      +
    1. Use the git patch tools: git diff and git apply
        +
      • This isn't so different than the patch command: https://www.lullabot.com/articles/git-best-practices-upgrading-the-patch-process
      • +
      +
    2. +
    +

    Resources

    +
      +
    • http://scribu.net/wordpress/svn-patches-from-git.html
    • +
    • https://markjaquith.wordpress.com/2005/11/02/my-wordpress-toolbox/
    • +
    • patch manpage
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/gitolite-manual-reinstall-graft/index.html b/docs/praxes/gitolite-manual-reinstall-graft/index.html new file mode 100644 index 00000000..335186e2 --- /dev/null +++ b/docs/praxes/gitolite-manual-reinstall-graft/index.html @@ -0,0 +1,3172 @@ + + + + + + + + + + + + + + + + Gitolite Manual Reinstall Graft - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Gitolite Manual Reinstall Graft

    + +

    Gitolite Migration

    +

    Instructions for migrating gitolite3 to a new host.

    +

    Gitolite gitolite-admin management

    +

    If gitolite-admin is managed remotely, it simply needs the git remote path changed.

    +

    If gitolite-admin is managed locally, ensure the old admin.pub key is kept as it is committed in the repo.

    +

    Graft gitolite3 install onto a server and change your admin key

    +

    This process assumes you are doing a key change in your admin repo concurrent with reinstall.

    +

    If you do not need to do a keychange and keep gitolite-admin remote then the only thing you have to do is install gitolite through apt and graft the replacement directory. Much faster.

    +

    There may be an easier way, LMK if you try one. This method is intended to graft the magic, whole hog, rather than try to integrate new magic on top.

    +
      +
    1. ssh-keygen - have a local key for easy gitolite install
    2. +
    3. apt-get install gitolite3
        +
      • Do a default setup and DO point it to your local pubkey: /home/<user>/.ssh/id_rsa.pub
      • +
      • this pubkey is going to get wiped out anyways
      • +
      +
    4. +
    5. Move the generated keys (from ssh-keygen) to temporary files
        +
      • I like to put them in /home/<user> for now
      • +
      +
    6. +
    7. Add the old keys where the generated keys were
        +
      • This ensures you will be able to push to your grafted repository
      • +
      • id_rsa, id_rsa.pub`
      • +
      +
    8. +
    9. Copy the original gitolite-admin management repo to the new host
        +
      • The git remote can be set as localhost if it is managed locally
      • +
      +
    10. +
    11. Delete the gitolite management repo on the new host /var/lib/gitolite3
    12. +
    13. Copy the original gitolite installation directory to the new host /var/lib/gitolite3
        +
      • Chown the gitolite installation directory to gitolite:gitolite
      • +
      +
    14. +
    15. You should be able to git fetch with no issues
    16. +
    17. Add the new key to the gitolite-admin repository
        +
      • Replace gitolite-admin/keydir/admin.pub with your new id_rsa.pub
      • +
      • Push this commit
      • +
      +
    18. +
    19. Replace the old keys in .ssh with the generated keys
    20. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/lftp_automation/index.html b/docs/praxes/lftp_automation/index.html new file mode 100644 index 00000000..3a7ccd02 --- /dev/null +++ b/docs/praxes/lftp_automation/index.html @@ -0,0 +1,3177 @@ + + + + + + + + + + + + + + + + Lftp Automation - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Lftp Automation

    + +

    lftp FTPS/FTP Automation

    +

    We want to use ftps which uses FTP over TLS/SSL. This is not the same as sftp which is FTP over SSH.

    +
      +
    • FTP Server:
    • +
    • Port: 990
    • +
    • User name:
    • +
    • Password:
    • +
    +

    The user name does not allow @. This may be possible somehow.

    +

    Example with lftp command line FTP/FTPS program

    +

    FTPS Example

    +

    Note that you must specify ftps:// in the URL.

    +

    lftp -c "open -p990 -u <user>,<pass> ftps://<FTP Server>; ls"

    +

    FTP Example

    +

    $ lftp -c "open -u <user>,<pass> <FTP Server>; ls"

    +

    This can be used to send and receive files automatically via scripted action.

    +

    Security

    +

    Always use FTPS over port 990.

    +

    Standard (Port 21) or Implicit SSL/TLS (Port 990) are available.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/my-organization-tools/index.html b/docs/praxes/my-organization-tools/index.html new file mode 100644 index 00000000..478e1e03 --- /dev/null +++ b/docs/praxes/my-organization-tools/index.html @@ -0,0 +1,3065 @@ + + + + + + + + + + + + + + + + My Organization Tools - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    My Organization Tools

    +
      +
    1. pinboard.in
    2. +
    3. github.com
    4. +
    5. trello.com
    6. +
    7. would like to replace with oss with easy sync with iphone and offline mode
    8. +
    9. gmail.com
    10. +
    11. notetoself tag should be moved to trello
    12. +
    13. outlines.git
    14. +
    15. firefox bookmarks (would like to reduce/remove)
    16. +
    +

    Low Use Organizational Tools

    +
      +
    1. librarything.com *
    2. +
    3. todoist *
    4. +
    5. anki
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/optiplex/index.html b/docs/praxes/optiplex/index.html new file mode 100644 index 00000000..7ecd5133 --- /dev/null +++ b/docs/praxes/optiplex/index.html @@ -0,0 +1,3188 @@ + + + + + + + + + + + + + + + + Optiplex - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Setting up a Dell OptiPlex FX160

    +
      +
    1. Use a sata 22-pin extender to add a 2.5" drive
    2. +
    3. +

      Update the BIOS Settings

      +
        +
      1. +

        In System -> Boot Options (make sure both the drive and usb are inserted)

        +
          +
        1. Hard Drive
        2. +
        3. USB
        4. +
        5. (no option)
        6. +
        7. (no option)
        8. +
        9. (no option)
        10. +
        +
      2. +
      3. +

        In Drives -> SATA Operation select AHCI

        +
      4. +
      5. Optional: reset security settings by unseating the bios coin battery for 1 minute
      6. +
      7. Download xubuntu 16.04.2 iso and write to a flash drive
      8. +
      9. Attach a monitor, keyboard, mouse, and ethernet cable or USB wifi card
      10. +
      11. install xubuntu
      12. +
      13. Select: install 3rd party software and download updates during install
      14. +
      15. Set an appropriate: hostname, username, and password
      16. +
      17. Install vim, openssh-server, and openssh-client
      18. +
      19. Get a static IP on your local network (lan)
      20. +
      21. Paste the contents in the snippet below into /etc/network/interfaces
      22. +
      +

      ```

      +

      interfaces(5) file used by ifup(8) and ifdown(8)

      +

      default loopback interface (from install)

      +

      auto lo +iface lo inet loopback

      +

      auto enp2s0 +iface enp2s0 inet static +address 192.168.1.ddd +netmask 255.255.255.0 +gateway 192.168.1.1

      +

      google DNS

      +

      dns-nameservers 8.8.8.8 +```

      +
        +
      • Update your address and gateway for your local network
      • +
      • Additionally, your interface name may be different, here called enp2s0
          +
        • Find your interface by typing ifconfig, it is the one that is not lo
        • +
        • Make sure you are setting up the interface you will always be using
        • +
        +
      • +
      • Ubuntu guarantees consistent naming for these interfaces per hardware configuration
      • +
      • SSH into your computer through your local network at the correct local IP
      • +
      • If you will connect over the internet, test this too through a remote connection
      • +
      • Restart the computer, optionally test SSH again
      • +
      • If everything works, you can remove the peripherals and manage the machine through SSH
      • +
      • This guide does not cover securing or managing your installation.
      • +
      +
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/osx_disable_sip/index.html b/docs/praxes/osx_disable_sip/index.html new file mode 100644 index 00000000..5169783a --- /dev/null +++ b/docs/praxes/osx_disable_sip/index.html @@ -0,0 +1,3104 @@ + + + + + + + + + + + + + + + + Osx Disable Sip - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Osx Disable Sip

    + +

    How to get a terminal and remove System Integrity Protection in OSX

    +
      +
    1. Hold [CMD+R] to get a recovery menu.
        +
      • If this doesn't work (osx sierra bug) then use [CMD+OPT+R], internet recovery.
      • +
      +
    2. +
    3. In the top menu choose Utilities->Terminal
    4. +
    5. Type csrutil disable
        +
      • Success message will show
      • +
      +
    6. +
    7. Perform system modifications
    8. +
    9. csrutil enable - ENABLE SIP AGAIN. This is a pretty good defense mechanism.
    10. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/pcb-etching/index.html b/docs/praxes/pcb-etching/index.html new file mode 100644 index 00000000..b084cec4 --- /dev/null +++ b/docs/praxes/pcb-etching/index.html @@ -0,0 +1,3110 @@ + + + + + + + + + + + + + + + + Pcb Etching - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    + +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/raspi_home_setup/index.html b/docs/praxes/raspi_home_setup/index.html new file mode 100644 index 00000000..9222165e --- /dev/null +++ b/docs/praxes/raspi_home_setup/index.html @@ -0,0 +1,3274 @@ + + + + + + + + + + + + + + + + Raspi Home Setup - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Raspi Home Setup

    + +

    Raspberry Pi Home Setup

    +

    A history of how my two raspberry pi headless machines were set up at home.

    +

    Future

    +

    Consider writing a service to detect and deliver changes to raspberry PI IP addresses over a static location such as digitalocean/flask.

    +

    Configuration

    +

    System

    +
      +
    • +

      Apt

      +
        +
      1. sudo apt-get update
      2. +
      3. sudo apt-get upgrade
      4. +
      5. sudo apt-get install vim git tree tmux pwgen fail2ban
      6. +
      +
    • +
    • +

      SSH Port

      +
        +
      1. Add additional ssh port Port 2200 to /etc/ssh/sshd_config
      2. +
      3. Set PermitRootLogin to 'no' in /etc/ssh/sshd_config
      4. +
      5. Restart ssh server: sudo service sshd restart
      6. +
      7. Add ssh port forwarding on router
      8. +
      +
    • +
    • +

      Static IP: sudo vim /etc/dhcpcd.conf

      +
        +
      1. Append this to the file (change as necessary):
      2. +
      +
    • +
    +
    interface eth0    
    +static ip_address=192.168.1.111    
    +static routers=192.168.1.1    
    +static domain_name_servers=192.168.1.1 
    +
    + +

    raspi-config

    +
      +
    • +

      FIRST: Advanced Options -> Update (update the tool)

      +
        +
      • Note: if this triggers an update, this file will need updated too.
      • +
      +
    • +
    • +

      Expand Filesystem (select it to auto expand)

      +
    • +
    • +

      Change User Password: pi password to a pwgen -cn 12 password

      +
    • +
    • +

      Boot Options -> Console

      +
    • +
    • +

      Internationalization

      +
        +
      1. Set timezone to Pacific Ocean
      2. +
      3. Set keyboard to 101-key, US Standard
      4. +
      5. Set wifi country to United States
      6. +
      +
    • +
    • +

      Advanced Options

      +
        +
      1. Hostname -> Change to desired hostname
      2. +
      3. Memory Split -> 16 (headless needs no gpu)
      4. +
      5. SSH -> Enable (default)
      6. +
      +
    • +
    +

    User Management

    +
      +
    • +

      Add user

      +
        +
      1. adduser robbintt - use a new pwgen -cn 12 password. Add robbintt to sudo group
      2. +
      3. Create SSH keys ssh-keygen
      4. +
      5. Add SSH pubkey to bitbucket dotfiles.git as deployment key
      6. +
      7. cd ~; git clone git@bitbucket.org:robbintt/dotfiles.git .dotfiles
      8. +
      9. Unpack dotfile symlinks w/ make_symlinks.sh script
      10. +
      11. Log in as user, delete any pi account ssh keys.
      12. +
      13. Configure dotfiles ssh to include user, port.
      14. +
      15. Add authorized_keys from other machines as necessary and update .ssh/config in dotfiles. Redeploy dotfiles.
      16. +
      +
    • +
    • +

      Remove pi NOPASSWD sudo priveleges in visudo

      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/set_dvdplayer_region/index.html b/docs/praxes/set_dvdplayer_region/index.html new file mode 100644 index 00000000..c9d547f8 --- /dev/null +++ b/docs/praxes/set_dvdplayer_region/index.html @@ -0,0 +1,3105 @@ + + + + + + + + + + + + + + + + Set Dvdplayer Region - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Set a DVD Player's Region from Linux (Debian based)

    +

    Many DVD players have manufacturer limits in the firmware. Mine had a limit of 5 region resets.

    +

    There are 8 regions. You probably want a US region.

    +

    If you always need more than one region you will need multiple DVD drives.

    +

    In 2017, DVD drives are practically without value.

    +

    Procedure

    +

    Use the regionset utility to change the region. If you run out of resets, the DVD player keeps the final region you selected. Some DVD players may have firmware upgrades that reset the counter.

    +
      +
    1. apt install regionset
    2. +
    3. Run regionset and set the region if it is not already set.
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/site_asset_checklist/index.html b/docs/praxes/site_asset_checklist/index.html new file mode 100644 index 00000000..217caad8 --- /dev/null +++ b/docs/praxes/site_asset_checklist/index.html @@ -0,0 +1,3099 @@ + + + + + + + + + + + + + + + + Site Asset Checklist - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Site Asset Checklist

    + +

    Website Project Checklist

    +
      +
    1. favicon.ico
        +
      • 16x16
      • +
      • 32x32
      • +
      • ??
      • +
      +
    2. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/site_launch_checklist/index.html b/docs/praxes/site_launch_checklist/index.html new file mode 100644 index 00000000..fdb2dd8a --- /dev/null +++ b/docs/praxes/site_launch_checklist/index.html @@ -0,0 +1,3099 @@ + + + + + + + + + + + + + + + + Site Launch Checklist - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Site Launch Checklist

    + +

    Website Launch Checklist

    +
      +
    1. +

      Google Analytics ID Enabled

      +
    2. +
    3. +

      Amazon Cloudwatch Monitoring (when applicable)

      +
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/ssh_socks_proxy/index.html b/docs/praxes/ssh_socks_proxy/index.html new file mode 100644 index 00000000..4073a89d --- /dev/null +++ b/docs/praxes/ssh_socks_proxy/index.html @@ -0,0 +1,3157 @@ + + + + + + + + + + + + + + + + Ssh Socks Proxy - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Ssh Socks Proxy

    + +

    Procedure: Set up ssh as a SOCKS proxy over 443

    +

    "A simple VPN." - lee

    +

    Prerequisites

    +

    The remote server's sshd needs to accept ssh on 443 if you can only get 443 outbound.

    +

    Edit /etc/ssh/sshd_config to have the line Port 443 after any similar lines and service sshd restart

    +

    Server and client setup

    +
      +
    1. ssh -p443 -D localhost:443 <username>@<remote-host>
        +
      • macos: sudo ssh -i <path-to-ssh-key> -D localhost:443 <username>@<remote-host>
          +
        • make sure to use the path to the private key, not the public key!!
        • +
        +
      • +
      +
    2. +
    3. Configure your local system to send network traffic over a SOCKS proxy at localhost:443
        +
      • macos: System Preferences->Network
          +
        1. unlock administrative access (press the lock)
        2. +
        3. select 'wifi' for wifi
        4. +
        5. choose Advanced...->Proxies
        6. +
        7. Add localhost : 443 to the SOCKS Proxy, choose ok
        8. +
        9. In the 'network' window choose save
        10. +
        11. Check your IP at google.com by typing "whats my IP"
        12. +
        +
      • +
      +
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/ssh_tunnel_back/index.html b/docs/praxes/ssh_tunnel_back/index.html new file mode 100644 index 00000000..3d1b0d18 --- /dev/null +++ b/docs/praxes/ssh_tunnel_back/index.html @@ -0,0 +1,3162 @@ + + + + + + + + + + + + + + + + Ssh Tunnel Back - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Ssh Tunnel Back

    + +

    Setting up tunneling back into an SSH connection

    +

    This is for establishing a new connection back to the server through the original SSH connection.

    +

    This is typically used if you are behind a proxy but the machine you want to be on is not. You can access the machine, then use that tunnel to access your machine.

    +

    The best use case for this is if you have some non-ssh access to a remote machine and need to establish a tunnel back to your local machine in order to have direct ssh access to the remote machine.

    +

    One use case for this might be a citrix desktop.

    +

    Definitions

    +

    This gets confusing so we will use 2 terms to disambiguate each server.

    +
      +
    1. Establishing Server - The server which sends the first SSH connection. Its SSH connection will be tunneled back through.
    2. +
    3. Remote Server - The server that receives the original SSH connection and is used to tunnel back into the Establishing Server
    4. +
    +

    Setup

    +
      +
    1. Open /etc/ssh/sshd_config and add the line GatewayPorts yes
    2. +
    3. Create a tunnleable connection from the Establishing Server to the Remote Server.
        +
      • ssh -R 2000:localhost:22 yourusername@remoteservername -p22
      • +
      +
    4. +
    5. Tunnel back from the Remote Server to the Establishing Server
        +
      • ssh -p2000 yourusername@localhost
      • +
      +
    6. +
    7. This connection is only available through loopback/localhost
    8. +
    +

    References

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/ssh_vnc_reverse_proxy/index.html b/docs/praxes/ssh_vnc_reverse_proxy/index.html new file mode 100644 index 00000000..0b792daa --- /dev/null +++ b/docs/praxes/ssh_vnc_reverse_proxy/index.html @@ -0,0 +1,3172 @@ + + + + + + + + + + + + + + + + Ssh Vnc Reverse Proxy - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Ssh Vnc Reverse Proxy

    + +

    VNC Reverse Proxy

    +

    In order to create a reverse proxy, you will need access to the server behind the firewall and a computer with a static IP address to proxy/receive the connection from your laptop.

    +

    Steps

    +
      +
    1. Setup - proxy server/computer
        +
      • Make sure it has a static IP and that the sshd server is active
      • +
      • Set the sshd_config's GatewayPorts clientspecified - this is used to allow any domain to hit the proxy
      • +
      +
    2. +
    3. Installation - computer/server behind the firewall
        +
      • apt install autossh tightvncserver xfce4 xfce4-goodies firefox
      • +
      • store the vnc server password somewhere safe, choose connection 1 as that corresponds to port 5901
      • +
      • Write a systemd unit for connecting to the proxy
      • +
      • replace your_username_here with your username and 1.2.3.4 with the IP or DNS hostname of your proxy server
      • +
      • Install the systemd service, restart the daemon, start it, and enable it.
      • +
      +
    4. +
    +

    ```[Unit] +Description=AutoSSH Tunnel +After=network.target

    +

    [Service] +User=your_username_here +Environment="AUTOSSH_GATETIME=0" +ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR *:5901:localhost:5901 your_username_here@1.2.3.4 -p 22

    +

    [Install] +WantedBy=multi-user.target +```

    +
      +
    1. Connect to vnc server
        +
      • use the default mac client $ open vnc://1.2.3.4:5901
      • +
      • you should not need to specify a username or anything else
      • +
      • or use a specialized client
      • +
      +
    2. +
    +

    Future

    +
      +
    1. Configure the tightvncserver service or pick a different one if preferred.
    2. +
    3. Consider better macos, windows, linux vnc clients and special configuration options
    4. +
    5. Option: per-user vnc connection instead of per user proxy
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/training/20230724_training/index.html b/docs/praxes/training/20230724_training/index.html new file mode 100644 index 00000000..783ba7e9 --- /dev/null +++ b/docs/praxes/training/20230724_training/index.html @@ -0,0 +1,3487 @@ + + + + + + + + + + + + + + + + 20230724 Training - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Personal Training 20230724

    +

    Goal Ideas

    +

    This is just a rough scratchpad.

    +
      +
    • Compound weightlifting stuff, organize this better
        +
      • squats, deadlifts, i have like 8 others I am interested in, and whatever else too
      • +
      +
    • +
    • Lose 8 lbs, be at 8% body fat. Current target wt. 190.3 lbs.
        +
      • straightforwards: just 8 weeks of my current cardio/lifting without any cheeseburgers or pizza. I don't need to calorie count based on the low importance of the 8 week timeline.
      • +
      +
    • +
    • Develop a good routine: Dynamic Warmups before exercise, static stretching after exercise
    • +
    • Improve balance in each leg and between legs, half ball stuff, what else?
    • +
    • Mobility
        +
      • improve range of motion in shoulders and arms
      • +
      • Determine needs for hip mobility
      • +
      +
    • +
    +

    general tips

    +
      +
    • really feel and hold the squeeze at the top
    • +
    • use a slow negative/eccentric too, 3 seconds up, pause and flex the muscle 2 seconds, 3 seconds down
    • +
    +

    Questions:

    +
      +
    • How often should I foam roll? I don't want to do it like... 6 hours a week...
        +
      • my guess: more is better, watch TV and foam roll like every other day
      • +
      +
    • +
    • what is the squat case in which I can somehow put strain or sliding on the knees? Maybe it isn't one of my problems?
    • +
    • how can i improve mobility to get a bit deeper into my squat?
    • +
    • what works the anterior deltoids on the two arm seated cable pull out of A I Y T? Do I have anything in my workouts that works the anterior deltoids?
    • +
    • how does holding the squeeze go for say a curl, should i pause halfway down in the eccentric?
        +
      • how do i pause and flex "at the top" (or wherever) in other exercises than a pushup?
      • +
      +
    • +
    • how do you use the 2 lacrosse balls taped together? any more lacrosse ball tips?
    • +
    +

    Body Composition Machine

    +

    Nothing notable, 11.1% body fat.

    +

    I think recommended is 10%-20% and minimum acceptable is about 6%.

    +

    Based on this I don't need to lose any weight and can really only lose 21.9 - (198.3*.06) == 10.0 lbs

    +

    BUT - all body fat loss is good for my cholesterol, so maybe I will aim for a 7-8% body fat.

    +

    In this case, lose 21.9 - (198.3*.07) == 8 lbs. Target weight: 190.3 lbs

    +

    Squats

    +

    Squat Form

    +
      +
    • to get the leg form, clench your butt and feel the tension pushing your outside feet into the ground and your outside legs flexingand your hips widening outwards
    • +
    • knees should be above toes, going straight down
    • +
    • squat should be wide, toes might be slightly out, it's based on body type
    • +
    • low position is femurs parallel to the ground
    • +
    • go straight down, don't tip forwards
        +
      • squat facing and up against the mirror to prevent leaning forwards
      • +
      • i didn't do this, but may in the future
      • +
      +
    • +
    • i didn't tip back when i was holding a ~20 lbs kettlebell upside down and squatting with that
        +
      • if i just do a bunch of squats, will i stop tipping back as I get more stability?
      • +
      +
    • +
    • when going up activate the glutes A LOT
    • +
    • breathing: inhale before going down, part of the way up, start your exhale, queston: is this related to the glute activation time? i will get a feel for it...
    • +
    +

    Squat Stability

    +

    Two leg squat stability

    +
      +
    • stand on the half ball and squat, hold something for support
        +
      • ensure your feet are even forward and back
      • +
      • ball is more advanced, you can also use the big black cube things
      • +
      +
    • +
    +

    Single Leg squat Stability

    +
      +
    • stability exercise: stand on the half ball with one foot in the dead center
        +
      • move your other foot in front, then to the side, then back
      • +
      • this is not exaggerated, just a few inches on each one, rotate between front, parallel, back, parallel, front, etc.
      • +
      • maybe do this 10 times
      • +
      +
    • +
    • stability is a constant importance, even a 350 lbs squat was able to get to 420 by doing like 100 squats on a half ball
    • +
    • muscle imbalance shows up as the fast rocking back and forth on the half ball
    • +
    +

    Pushup Stability

    +
      +
    • pushups on the half ball, don't grip the outsides, keep your hands flat
    • +
    • we did this for 5 minutes, I had good pushup stability
        +
      • this was still a great exercise and I should repeat it
      • +
      +
    • +
    • 3 seconds down, 3 seconds up, 2 second flex at the top
        +
      • flex your muscles manually at the top for 2 seconds
      • +
      • this manual activation will improve the burn
      • +
      • even stop halfway down and hold it
      • +
      +
    • +
    • "time in position" or something? basically you hold it, that will give a good workout
    • +
    • more strengthening in the negative of the weightlifting
    • +
    • also pause/hold movement in tension for 2 seconds, e.g. halfway down
    • +
    +

    Two arm seated cable pull

    +

    Goal: Work the A and I positions into my back and core day, maybe move core day to leg day?

    +
      +
    • Shoulder Mobility, 4 positions: A, I, Y, T
        +
      • I do a 30 deg. bench dumbbell reverse fly in the T and Y positions
      • +
      • I felt very weak in the A position, both arms straight pulling down alongside my hips
      • +
      • I used the minimum weight
      • +
      • didn't really feel the activation much below my shoulderblades
      • +
      • need to work this a lot to get these muscles going
      • +
      • I felt weaker in the I position, both arms overhead, need to work on this too
      • +
      +
    • +
    +

    Broom Handle

    +

    I should get a broom handle for my house, as this doesn't need to be done in the gym and probably needs done daily.

    +
      +
    • Shoulder mobility
        +
      • find the minimum width where you can very smoothly clear the broom handle from in front of your hips to behind your hips
      • +
      • the whole exercise should be smooth, going from front to back, then back to front
      • +
      • keep the bar as far away from your body as you can throughout
      • +
      • repeat it 15 times or something
      • +
      • This is very wide for me, and I should be able to reduce the distance between my hands over time by doing this daily
      • +
      +
    • +
    +

    Planks

    +
      +
    • +

      Hold 12" ball between the elbow and the knee, then hold the opposite leg and arm up and out, at kind of a 45 degree angle

      +
    • +
    • +

      Elbow plank

      +
        +
      • should be called "forearm plank" keep the weight distributed on my forearms, avoid lots on the elbows.
      • +
      • keep the shoulders over the forearms
      • +
      • keep a strong stance throughout, try not to sag
      • +
      • 4 x 90 second plank is a good benchmark, get it in
      • +
      • i don't think elbow should be harder than hand?
      • +
      +
    • +
    +

    Foam rolling

    +

    Tools: foam roller (hard), lacrosse ball

    +

    Rolling is a misnomer, it should be foam pressing or something. You only roll to find the spot, then you hold it there.

    +
      +
    • lacrosse ball is great, you can go pretty hard, but don't go too hard
    • +
    • put a string on a lacrosse ball for using against the wall
    • +
    • +

      tape 2 lacrosse balls together for the legs, not sure why

      +
    • +
    • +

      You don't need to wait until you are tight to do this, do it early and do it often.

      +
    • +
    • Keep the pressure until you feel the release.
    • +
    • positions:
        +
      • between the hip flare bone and the hip bone there are muscles that fan out, whatever those are
      • +
      • anterior to the fan out is the hip flexor
      • +
      • posterior to the fan out is something that needs it too
      • +
      • similar to pidgeon to get the muscle outside of the shin - i definitely feel this
      • +
      • calves etc
      • +
      • classic leg foam rolling, i have done this a hundred times, hit the IT band, anywhere you can feel it, do it unti you get the release
      • +
      +
    • +
    +

    Dynamic warmups

    +

    Dynamic warmup before exercise, static stretching after exercise/cardio (end of workout)

    +
      +
    • For tomorrow: Alternatingly 25x - stand on one foot and sweep my arms up, sort of like a partial squat in the hips and knee. Switch feet each time.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/training/20230727_training/index.html b/docs/praxes/training/20230727_training/index.html new file mode 100644 index 00000000..bf22d77a --- /dev/null +++ b/docs/praxes/training/20230727_training/index.html @@ -0,0 +1,3167 @@ + + + + + + + + + + + + + + + + 20230727 Training - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Training Today

    +

    Exercises

    +
      +
    1. Dynamic Warmup - Lunges with Arms in stirrups
        +
      • lunge forwards and feel the arms pull out
      • +
      • use the T and the Y shapes to stretch the arms and shoulders
      • +
      • do this for a few minutes
      • +
      +
    2. +
    3. Barbell Rack Squats
        +
      • weights: bar, 25s, 35s, 45s
      • +
      • I only got like 4 of the barbell+45s, but will be able to do more later
      • +
      • SAFETY: when racking, walk bar into the rack all the way, then lower
      • +
      • SAFETY: when racking, don't jam your finger
      • +
      • pull the bar down onto the traps and engage the lats, keep it locked
      • +
      • hands are of a natural distance on the grip, outside the shoulders
      • +
      • keep using the broom handle daily to improve the shoulder mobility
      • +
      • take one step back from the rack only
      • +
      • ensure feet are aligned on a line on the floor
      • +
      • get some flat shoes
      • +
      • time to squat. Breathe in all the way before lowering
      • +
      • activate your abs and core, keep your lats activated, and lower
      • +
      • the bar should go STRIGHT DOWN AND UP
      • +
      • your butt should not go out a lot
      • +
      • your knees should not go forwards, only very slightly at the bottom and stay over your toes, not pass the toes
      • +
      +
    4. +
    5. RDL deadlifts?
        +
      • weights: barbell + 25 each
      • +
      • I think that means romanian deadlift
      • +
      • keep the bar pushing against your legs the whole time
      • +
      • keep the lats activated
      • +
      • remember feeling with trainer pulling bar away from my legs with a band
      • +
      • go from upright to a few inches below the knee
      • +
      • hands must be symmetrical on the bar
      • +
      • AVOID INJURY: activate the abs and core, otherwise you will activate the back too much
      • +
      +
    6. +
    7. balance, step backwards into foot saddle, lunge knee to ground
        +
      • sqeeze the back foot's glute as you get into the position
      • +
      • feel the front quad burn, feel the back hip stretch
      • +
      • go to the bottom to get your spacing when needed
      • +
      • should be a lunge position with front knee over foot
      • +
      +
    8. +
    9. Captain's chair: + a. 15 both leg raises, don't lower too far, lower abs + b. 10 (20 total) - one leg raises alternating + c. purpose: improve core to support squats
    10. +
    +

    Planning for this week

    +
      +
    • I would like to focus on technique with barbell rack squats
    • +
    • my feeling is I could do 4x12 every other day focusing solely on technique in addition to my normal workouts (maybe not leg day)
    • +
    • It's important to hit the captain's chair hard to build core stability
    • +
    • also do everything else
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/training/20230803/index.html b/docs/praxes/training/20230803/index.html new file mode 100644 index 00000000..fa289d66 --- /dev/null +++ b/docs/praxes/training/20230803/index.html @@ -0,0 +1,3407 @@ + + + + + + + + + + + + + + + + 20230803 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Personal Training 20230803

    +

    Focused on:

    +
      +
    • romanian deadlifts
    • +
    • exercises for squats
    • +
    • balance muscles
    • +
    • upper abs raises (both raises and twists)
    • +
    +

    Future:

    +
      +
    • will this help me get off my right big toe when walking/running?
        +
      • i am feeling optimisitic
      • +
      • might still need someone to help me specifically with this
      • +
      • GOAL: get off right big toe during walking/running, prevent damage/arthritis
      • +
      +
    • +
    • explosiveness
    • +
    • any additional mobility stuff?
    • +
    • more core - obliques, upper abs, what else?
    • +
    • more compound exercises
    • +
    • reviewing existing routines
    • +
    +

    Questions

    +
      +
    • In RDLs, how low should I eventually go? Always just beneath the knees or further? If so is there a limit?
    • +
    • How long is the pause at the bottom of a RDL? 1 second? 2 seconds? matters?
    • +
    +

    Romanian Deadlifts (RDLs) (barbell)

    +
      +
    • Legs hip width apart
    • +
    • hands are at natural resting place of hands when standing
        +
      • typically outside of hips a bit
      • +
      +
    • +
    • back is always rigid (breathe in at the top to support the trunk)
    • +
    • the exhale comes halfway up, with the power
    • +
    • throughout the movement, especially at the bottom, you should be able to tap your toes up and down, the weight should be distributed in the meat of foot, never the toes
    • +
    +

    Muscle Engagement

    +
      +
    • keep the lats engaged, pull the bar against your legs at all times
    • +
    • keep the traps engaged, like if you were trying to hold a pencil between them
    • +
    • keep the core engaged at all times to protect the back which is rigid
    • +
    • engage the glutes, which will create a tension pushing out down into the knees/feet
        +
      • don't move the knees/feet, just feel the tension from glutes pushing out
      • +
      +
    • +
    +

    Starting Position

    +
      +
    • bend all the way down to bring the weight up, this is a first deadlift but also the starting position.
    • +
    • grip the bar using the meat of your hand and thumb, DO NOT dangle from your fingers (damage)
        +
      • high weights you might use a clip in glove/grip so you can lift from your wrist
      • +
      +
    • +
    +

    Romanian Deadlift Movement

    +
      +
    • starting at the top, bend as hinge from the hip, sticking your butt out
    • +
    • the back should be completely rigid, abs remain engaged
    • +
    • keep the barbell against your legs
    • +
    • slowly lower the barbell down to just below your knees
    • +
    • you are holding your breath, engaging your abs and trunk, engaging your lats and traps, engaging your arms, engaging your glutes to keep force in back of feet, pushing the barbell into your legs
    • +
    • brief pause at the bottom, 1-2 seconds (which is it?)
    • +
    • maintaining your muscle engagement, raise it back up, especially engaging the glutes and whole posterior change with rigid back, all the muscles above still engaged, come to the top.
    • +
    +

    Squat Form

    +
      +
    • toes out slightly, legs pretty wide, find your squat position... too narrow ruins the squat, i am starting to understand mine, pretty wide.
    • +
    • form is good, want to get a deeper dip at the bottom of the squat
    • +
    • do normal calf extension stretches every day to get some more flexibility
    • +
    • stay well hydrated to prevent muscle tightness
    • +
    +

    Goblet Squats

    +
      +
    • use kettle bells upside down
    • +
    • goblet squats to practice going deeper.
    • +
    • you can goblet squat a lot, but start gradual. i did 17 KG before, but can probably raise that a lot. trainer mentions very heavy goblet squats.
    • +
    +

    Barbell "Landmine" rotation thingie squats

    +
      +
    • keep it nice and slow to properly engage each muscle group
    • +
    • do 4 x 12 of these to work on squat depth, squat form, and support muscles
    • +
    • barbell with 1 end in the landmine allowing it to rotate up, put a 45 lb plate on it
    • +
    • put your hands on the top of the bar standing in a good squat position, lower down all the way into a very deep squat.
    • +
    • you will find your proper distance when squatting, adjust accordingly
    • +
    • complete the squat with good form, but keep going, all the way up to your tippie toes with your head going under your shoulders and arms fully extended
    • +
    • repeat
    • +
    +

    Squat on a Slant Board

    +
      +
    • This engages the quads, good for support
    • +
    • do a bunch of these to build up your squat in the quads
    • +
    +

    Reverse Lunges

    +
      +
    • Can be done onto the ankle support pad bar, or a 12" soft balance pad / plyometrix box
    • +
    • start with kettle bell by handle in right hand and right foot forwards and up
    • +
    • drop right foot back and hook right ankle on the box/pad
    • +
    • lower the body into the reverse lunge, briefly tapping the knee on the ground
    • +
    • reverse back up into stance with right foot hovering in front of its resting position
    • +
    • use the first to find your proper distance for the left foot
    • +
    • make sure the left knee does not go forwards, it should stay behind the left toe
    • +
    • repeat 12 times, then switch to left foot
    • +
    +

    Upper ap lying leg raises and twists

    +
      +
    • repeat for 4 sets of 12 reps
    • +
    • Lay on the bench and grip the behind-head hand grips for this exercise
    • +
    • raise legs to about 70-90 degrees, this is the resting position
    • +
    • raise the butt off the mat by kicking legs up, this should engage the upper abs
    • +
    • lower the butt, keeping the legs up in the resting position
    • +
    +

    Upper ab and oblique twists

    +
      +
    • when kicking up, twist the body to the left
    • +
    • next twist the body to the right
    • +
    • repeat for 10 cycles (alternate each side, totaling 10 on each side)
    • +
    • i felt very weak at this, need to do it a lot
    • +
    • modification: hook the knee onto the side you want to twist and pull the body up
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/training/20230907_training/index.html b/docs/praxes/training/20230907_training/index.html new file mode 100644 index 00000000..8908b5ab --- /dev/null +++ b/docs/praxes/training/20230907_training/index.html @@ -0,0 +1,3168 @@ + + + + + + + + + + + + + + + + 20230907 Training - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Training Session

    +

    Deadlifts with Viper Grips

    +
      +
    • Was able to do bar+25s easily, with good form
    • +
    • Keel the shoulders down and back, pinch a pencil between your shoulderblades
    • +
    • Inhale on the way down, exhale on the way up, each of 10 reps
    • +
    • Was able to do bar+35s pretty easily as well
    • +
    • Feel confident this weight will go up as I keep practicing
    • +
    • The gloves should put a lot of the weight onto the wrists
        +
      • be sure to keep the bar tight against the hand and avoid holding it too tight with pinkies
      • +
      • the pain I had without was in the left ulnar side (electric shock from pinkie to outside of wrist)
      • +
      +
    • +
    +

    Farmer's Walk

    +
      +
    • Did 60s in each hand, used the viper hand grips for this as well.
    • +
    • Smaller steps are better!
    • +
    • Lower the weights by squatting down with a straight back
    • +
    • Walk about 10 meters, turn to the left or right (alternate) and walk back.
    • +
    • Keep your chest up and powerful (confident chest)
    • +
    • Each step should be well controlled
    • +
    • When I was getting tired I really started to feel the same engagement as a squat
        +
      • what I mean is squeezing the knees out and feeling the outsides of the hips engaged
      • +
      +
    • +
    • I really like this one, but I don't know exactly where the engagement should come from yet
        +
      • spend more time on this next week
      • +
      +
    • +
    • Hand position is at rest at the sides
    • +
    • Avoid - Alternate hand position is hands in front of shoulders at a 45 degree angle to the head, weight nearly over shoulders - max weight for this position was only 35-40 lbs, not sure)
        +
      • Avoid this due to pressure on the wrists
      • +
      +
    • +
    +

    Mobility

    +
      +
    • Plank with arms, keep the chest over the hands for a good plankl
        +
      • Weight should NOT be in the legs.
      • +
      • To keep yourself honest, plank in socks on a slippery floor. No friction on feet bc no feet support should be used.
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/using-scad-clj/index.html b/docs/praxes/using-scad-clj/index.html new file mode 100644 index 00000000..e32995f8 --- /dev/null +++ b/docs/praxes/using-scad-clj/index.html @@ -0,0 +1,3238 @@ + + + + + + + + + + + + + + + + Using Scad Clj - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Howto: Using the scad-clj OpenSCAD DSL on the CLI

    +

    This DSL domain specific language was used by adereth to make the dactyl keyboard. This howto is based on Adereth's blog post.

    +

    OpenSCAD becomes insane after awhile and what it needs most is lisp, because everything needs lisp.

    +

    Install leiningen

    +

    What is leiningen?

    +

    There are a lot of ways to do this.

    + +

    On 2017/12/28 the project page says:

    +
    +

    be sure you get version 2.x

    +
    +

    Check your version in a shell

    +
    $ lein -v
    +
    +Leiningen 2.8.1 on Java 1.8.0_144 Java HotSpot(TM) 64-Bit Server VM
    +
    + +

    Get scad-clj

    +

    Available on github: https://github.com/farrellm/scad-clj

    +

    Quickstart!

    +

    Based on Adereth's 2014/3/19 Post: 3d printing with Clojure

    +

    Save this code as example.clj in the git repository scad-clj that you just cloned:

    +
    ;; import scad-clj objects or something
    +(ns scad-demo.core
    +  (:use [scad-clj.scad])
    +  (:use [scad-clj.model]))
    +
    +;; make something called primitives
    +(def primitives (sphere 50))
    +
    +;; export primitives to scad
    +(spit "example.scad" (write-scad primitives))
    +
    + +
      +
    1. In a shell, cd into the scad-clj project directory: cd scad-clj
    2. +
    3. Run the example.clj file: $ lein repl < example.clj
    4. +
    5. Start the OpenSCAD program
        +
      1. Navigate to and open the generated example.scad in OpenSCAD
      2. +
      3. You can now make changes to example.clj as you wish, recompile them, and reload the file in OpenSCAD.
      4. +
      5. As an example, try changing the sphere to size 50 in example.clj
          +
        1. run the repl command
        2. +
        3. your OpenSCAD instance should auto reload
        4. +
        5. If this setting is not already chosen it is at (see the menu - TODO, add exact file->location_name)
        6. +
        7. If not, choose file->reload or CMD+r on a mac.
        8. +
        +
      6. +
      +
    6. +
    7. Todo: run from your own project directory, not scad-clj.
        +
      • Otherwise it's messy and hard to keep stuff under source control.
      • +
      +
    8. +
    9. Use adereth's dactyl project as a template (avoid users needing to know much about clojure/lein/OpenSCAD before starting)
    10. +
    +

    References

    +
      +
    1. OpenSCAD User Manual/The OpenSCAD Language
    2. +
    3. scad-clj source code (includes compiler)
    4. +
    5. Adereth's Blog Post
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/vacation_july_2023/index.html b/docs/praxes/vacation_july_2023/index.html new file mode 100644 index 00000000..0fe20e2d --- /dev/null +++ b/docs/praxes/vacation_july_2023/index.html @@ -0,0 +1,3550 @@ + + + + + + + + + + + + + + + + Vacation July 2023 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Vacation 2023

    +

    Some time to focus on my way of being.

    +

    Look back at 2023 New Year Goals

    +

    My Analysis: "it seems like i can just read scifi, workout, and program c++ for the rest of the year, and work on my creativity process which is my top one right now."

    +

    Lose 8 lbs

    +
      +
    • need to start doing this, i know exactly what to do.
    • +
    • i can be done by october if I start by the end of vacation.
    • +
    • tentative start date: 2023-7-27
    • +
    • goals: don't eat any burgers/fries, indian, pizza
    • +
    • 1 cheat meal per week, historically do it on a wednesday
    • +
    • probably want to leave it up to me to decide when
    • +
    +

    Keep participating actively and doing recall on my personal training

    +
      +
    • TODO - add my new personal fitness goals to my 2023 goals
        +
      • mobility - shoulders, hips, ??
      • +
      • compound weightlifting practice (squats, deadlifts, etc)
      • +
      • "at home" practice
      • +
      • better fitness "goalsetting"
      • +
      • what else?
      • +
      +
    • +
    +

    Work on my creative process

    +
      +
    • TODO - eed to review my summaries for the Michalko books, and keep reading.
    • +
    • TODO - Write a "creative process" markdown / outline / cliff notes for reviewing
    • +
    • TODO - review the learning how to learn stuff in the context of creativity
    • +
    • ONGOING - Find creative applications in my every day life
    • +
    +

    Write c++

    +

    I'm not really listless here so much as "uncollected"

    +
      +
    • TODO: get collected in my c++ learning
    • +
    • TODO - review the learning how to learn stuff in the context of c++
    • +
    • TODO: consider if I should learn java this year based on my H2 goals.
    • +
    +

    Read scifi

    +

    Goal: none yet, keep reading what I am reading in the gym

    +

    Can I add a paper book? Do I have too much reading going on already?

    +

    I have had a lot of boring scifi misses or light scifi. I am missing the "ringworld" style mindbenders that dream up whole new possibiltiies.

    +

    I would like to:

    +
      +
    • maintain a clear mind
        +
      • keep space in every thought and decision for innovation or creativity
      • +
      +
    • +
    • maintain my practices for: diet, fitness, and meditation
    • +
    • focus on big lifts
    • +
    • not get caught in the weeds of a particular lift
    • +
    +

    Non Goals

    +
      +
    • No "catching up"
        +
      • small projects fit in my regular life
      • +
      • don't waste big blocks of time on small projects
      • +
      • resist "catching up", it doesn't exist
      • +
      +
    • +
    • No "catching up" with books
        +
      • this is part of the regular practice
      • +
      • if there is a book, it should be related to my "vacation projects"
      • +
      +
    • +
    • No discord / slack / hacker news / reddit
        +
      • don't read the news, just take the time off
      • +
      • don't get on weird tangents
      • +
      +
    • +
    • No code for the sake of code
        +
      • I get enough of this
      • +
      • this fits in the "small projects" that fit in my regular life
      • +
      +
    • +
    • No Dragonrealms
        +
      • Spent enough time here, this is just for tinkering
      • +
      • This is tiny projects not worth a big block of time
      • +
      +
    • +
    • No Home Network & Home Automation
        +
      • This isn't important
      • +
      • This is fun to tinker with, but it's a good side project for smaller blocks of time
      • +
      +
    • +
    • No Financial Planning
        +
      • I have a full 10-11 year financial plan and it is on track
      • +
      • Any investment in this is overinvestment
      • +
      +
    • +
    • No Apartment/Housing Pain Points
        +
      • Discussing any housing situation changes
      • +
      • Materially improving our current apartment
      • +
      +
    • +
    • No Professional Development
        +
      • I can work on this after vacation
      • +
      • I just finished a major milestone and have room to breathe
      • +
      • this is doing fine
      • +
      +
    • +
    +

    Goals

    +
      +
    • set SMART goals for my goals/visions
        +
      • For broad goals/visions, set a few more specific SMART goals
      • +
      +
    • +
    • have an optimized diet and improve my practice
    • +
    • impove my meditation practice
    • +
    • break the habit mold of my exercise repeatibly
    • +
    • leverage learning, pratice, and trainer
    • +
    +

    Vacation Projects

    +

    Question: how will I balance deep dives / "big blocks" with "new discovery"

    +

    Things I am interested in: +1. woodworking +2. c++ +3. cross compiling c++ + - for esp32 + - for openwrt +4. embedded controllers +5. leveraging llms + - don't want to rabbit hole + - i will have this at work when I get back, for free +6. self documentation + - i have been doing this on the weekends + - might be worth a big block to: + 1. enumerate this stuff + 2. write a basic gpt4 assisted doc for each +7. inventors and creativity

    +

    Documentation

    +

    List of things I would like to document

    +
      +
    • diet: just start with current practice, let it flow
        +
      • not a huge priority, but want to get the draft down
      • +
      +
    • +
    • meditation: current practice
    • +
    • learning: learning how to learn / habit forming + chunking + ?
    • +
    • exercise: practice, current, and some alternatives and swapping in
        +
      • this is intended to be documented once then improved immediately and radically
      • +
      +
    • +
    +

    Woodworking

    +
      +
    • Idea: focus on copying others' designs to offload goal setting workload
    • +
    • Goal: Less planning, more small scale executive, more with the hands
    • +
    +

    Personal Maintenance

    +

    Vision: Document what I am doing in terms of maintenance so I can improve over time in a directed way.

    +

    Overarching goal: Use my markdown outlines and openai to standardize my important personal management practices.

    +

    Daily Skill Building

    +
      +
    • Spend some time every day writing down all my practices
    • +
    • spend some time with the creativity books every day
    • +
    +

    Meditation

    +
      +
    • write down some core of my practice into markdown
    • +
    • consistent daily practice
    • +
    • improve daily mindfulness and awareness
    • +
    • find some new meditations to listen to
    • +
    • do some directed research
    • +
    +

    Exercise

    +
      +
    • everything i learn will be well documented to carry forwards
    • +
    • break out of my typical exercise routine
    • +
    • extra time in the gym
    • +
    • research adian's ideas and expand on them
    • +
    • decouple some exercise routine from the gym, using substitution and alternative goals
    • +
    +

    Diet

    +
      +
    • done eating by 5 PM
    • +
    • eat from the refrigerator
    • +
    • solid well planned daily diet
    • +
    • no special foods, really eat regularly and healthily
    • +
    • no upset stomach
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/vim_registers_for_macro_templates/index.html b/docs/praxes/vim_registers_for_macro_templates/index.html new file mode 100644 index 00000000..122a0d10 --- /dev/null +++ b/docs/praxes/vim_registers_for_macro_templates/index.html @@ -0,0 +1,3252 @@ + + + + + + + + + + + + + + + + Vim Registers For Macro Templates - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Managing Registers for Vim Macro Templates

    +

    Problem: macro templating

    +

    If you want to slightly modify a macro for special cases, you need to be able to manipulate its register easily.

    +

    Vim Macro Review

    +

    In vim, macros can be used for repetitive tasks.

    +

    The typical use case is to record a macro and play it back when needed.

    +

    A macro is recorded into a register.

    +

    You can see your registers by typing reg in the ex prompt. It looks like this: :reg.

    +

    How to use Macro Templates

    +

    Macro Templates are not special features, they are simply lines of text you have stored to put back into a register for use as a macro.

    +

    You could store a file where some lines are macro templates and others have comments.

    +

    For example, you might paste an existing register, l, with "lp.

    +
    Methods for Copying Macros
    +

    A macro doesn't really exist in vim, it's really a register, e.g. register l that is played back with the macro key, @, e.g. @l.

    +
      +
    1. On any empty line, you can paste an existing register, j, into another register, l: "jp0"ld$
    2. +
    3. In ex mode, use the command: :let @l=@j
    4. +
    +

    Example

    +

    We will use the command buffer as an anonymous buffer to avoid needing to modify a file to modify the register.

    +

    The example looks like this: q:ij^[0"ld$:q

    +

    This example will fill the register l that executes j which moves the cursor down 1 line.

    +

    You should replace j with any vim macro you wish.

    +

    Breakdown of Example

    +
      +
    1. Access the command buffer: q: and enter insert mode with i
        +
      • You may paste a macro template instead of directly entering insert mode
      • +
      • To paste directly from register k, type "kp
      • +
      +
    2. +
    3. Make your modifications: j can be replaced by any line representing your macro.
    4. +
    5. Exit insert mode: 
    6. +
    7. Move your text into the l register: 0"ld$
        +
      • 0: go to the beginning of the line
      • +
      • "l: queue up the l register to be yanked
      • +
      • d: begin delete at cursor, yanking to l in the process
      • +
      • $: move cursor to where the delete will terminate, the end of the line without the newline, apparently also can be the g_ sequence.
      • +
      +
    8. +
    9. Quit command mode: :q
    10. +
    11. Run your macro: @l
    12. +
    +

    Detour: The Escape Key

    +

    In a browser you probably cannot see the escape character, typically rendered as ^[ but as one glyph, , not two.

    +

    This character simply means the escape key. You can also do this chord directly to escape, also written as ctrl+[.

    +

    It must be typed as the single character . It is accessed with the  character followed by the  character: 

    +

    In vim this sequence looks like this, ^V^[, but is only two characters long, not four.

    +

    The key sequence to type the ^[ character in vim can also be written as ctrl+v ctrl+[.

    +

    To get ^V you can type ctrl+v ctrl+v.

    +

    You should not use ctrl+c (also known as ^C or `) here because it will put you back intoex mode` with your typed command in the ex buffer. We want to stay in the command buffer so we can paste the macro back into the register.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/wp_backup_migrate/index.html b/docs/praxes/wp_backup_migrate/index.html new file mode 100644 index 00000000..a1a29224 --- /dev/null +++ b/docs/praxes/wp_backup_migrate/index.html @@ -0,0 +1,3335 @@ + + + + + + + + + + + + + + + + Wp Backup Migrate - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    + +
    + + + +
    +
    + + + + + + + + + +

    Wp Backup Migrate

    + +

    Basic Backup or Migration Protocols for WordPress Sites

    +

    A protocol for backing up and/or migrating a Wordpress site.

    +

    Future

    +
      +
    1. Integrate Install Needs section into ansible for ubuntu 16.04 systems.
    2. +
    +

    Backup

    +

    Components

    +

    This is the same pattern for any modern web application framework.

    +
      +
    1. MySQL Database
    2. +
    3. Project Directory
    4. +
    +

    Backing up the MySQL Database

    +
      +
    1. +

      Get the following from the wp-config.pyp:

      +
        +
      • Database Name
      • +
      • Username
      • +
      • Password
      • +
      +
    2. +
    3. +

      `mysqldump {Database Name} > ~/backups/mywpsite.bkp.yyyymmdd.sql -u {Username} -p

      +
        +
      • Enter password at the prompt
      • +
      +
    4. +
    +

    Backing up the Project Directory

    +

    tar -czvf ~/backups/myproject.bkp.yyyymmdd.tar.gz /my/project/root/directory/

    +

    Migration

    +

    Do these in order.

    +
      +
    1. +

      Back up the site and copy the tar.gz and the sql files to the new location

      +
    2. +
    3. +

      Rebuilding the project

      +
        +
      1. Unzip the tar.gz file into /var/www/websites
          +
        • The full path should be /var/www/websites/www.example.com/www/{wordpress root}
        • +
        +
      2. +
      3. Change the permissions of this path: chown -R www-data:www-data {path}
          +
        • If you wish to traverse symlinks, use -H flag.
        • +
        +
      4. +
      5. Make a symlink at /var/www/www.example.com to /var/www/websites/www.example.com
          +
        • Saves tons of work later if you need to redirect to another location
        • +
        +
      6. +
      +
    4. +
    5. +

      Set up the MySQL user, database, password on the new location

      +
        +
      1. Login to MySQL as the root user: $ mysql -u root -p
          +
        • enter password at prompt
        • +
        +
      2. +
      3. create database {Database Name};
      4. +
      5. create user '{User}'@'localhost' IDENTIFIED BY '{Password}'
          +
        • Does the next step create the user automatically if you don't do this?
        • +
        +
      6. +
      7. grant usage on {database}.* to '{User}'@'localhost' identified by '{Password}';
      8. +
      9. view your changes: mysql> select user, host, password from mysql.user;
      10. +
      11. mysql> FLUSH PRIVILEGES; then mysql> quit;
      12. +
      13. Ensure the wp-config.php has the same Database Name, Username, Password
      14. +
      15. Move the sql file to the wordpress root directory
      16. +
      17. $ wp-cli.phar db import mywpsite.bkp.yyyymmdd.sql
          +
        • wp db import
        • +
        • You need wp-cli.phar on your path if it is not already
        • +
        • Alternatively put a copy in local directory or specify /path/to/wp-cli.phar
        • +
        +
      18. +
      19. If your WordPress site URL has changed
          +
        1. Update the database with wp-cli
            +
          • wp-cli is usually aliased to wp
          • +
          • wp-cli.phar option update home 'http://www.example.com'
          • +
          • wp-cli.phar option update siteurl 'http://www.example.com'
          • +
          +
        2. +
        3. If you have urls in your posts, pages, etc.
            +
          • wp-cli.phar search-replace 'example.dev' 'example.com' --skip-columns=guid
          • +
          +
        4. +
        +
      20. +
      +
    6. +
    7. +

      Configure and restart apache2

      +
        +
      1. Use a template!
          +
        • Generally I just copy another site that follows the same pattern
        • +
        • Then search and replace your new website name
        • +
        +
      2. +
      3. Store in /etc/apache2/sites-available/{mywebsitename}.conf
      4. +
      5. Make sure your apache logs exist in {projectdirectory}/logs/
          +
        • For more info, check the path in your apache config file
        • +
        • access.log, error.log
        • +
        +
      6. +
      7. a2ensite {mywebsitename} then apache2 restart
      8. +
      +
    8. +
    9. +

      If you have errors, fix this configuration as you fix the error.

      +
    10. +
    11. WP Codex - Changing The Site URL
    12. +
    +

    WordPress Requirements

    +

    WordPress requires a great many packages and configuration settings. Here are some packages that were installed manually on a Ubuntu 14.04 server in the past.

    +
      +
    1. apt-get install postfix
        +
      • This is important so WordPress can send mail (doesn't need a real outbound address)
      • +
      • This needs configured more completely to try to evade spam filters
      • +
      • DigitalOcean WordPress Email Reference
      • +
      • FUTURE: There are alternatives like going through a gmail acount with wp-smtp plugin
      • +
      • FUTURE: WordPress Contact Form 7 Spam Reference - Apparently there are some nice tricks to avoid being treated as spam?
      • +
      +
    2. +
    3. Set up apache2 Virtual Hosts
    4. +
    5. Set up mysql root user
    6. +
    7. Set up php5 modules for apache2
    8. +
    9. Set up mod-rewrite for apache2
    10. +
    11. More...
    12. +
    13. Fix the php upload file sizes
    14. +
    15. Directory/File permission fixers (files vs dirs, see snips) for annoying hosts.
    16. +
    17. Other snips from my snips git repo
    18. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/wp_backup_restore/index.html b/docs/praxes/wp_backup_restore/index.html new file mode 100644 index 00000000..45f21c4c --- /dev/null +++ b/docs/praxes/wp_backup_restore/index.html @@ -0,0 +1,3211 @@ + + + + + + + + + + + + + + + + Wp Backup Restore - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Wp Backup Restore

    + +

    WordPress Backup and Restore Procedures

    +

    These procedures have been tested at least once on an ansible managed Ubuntu 16.04 server. The backup and restore procedures are very good automation targets.

    +

    Automation Constraints

    +
      +
    1. URL name length is different than mysql user, database, password maximum length
    2. +
    3. Use sudo -u www-data do-stuff to maintain ownership under apache2's www-data user.
    4. +
    5. It looks like a lot of PHP5 stuff might break on PHP7. PHP versioning could be very important.
        +
      • PHP versioning creates tons of security concerns. Requires compartmentalization/virtualization
      • +
      +
    6. +
    +

    WordPress Backup Procedure

    +

    This backup methodology is generic across projects and databases. The written protocol is specific for apache2, MySQL, and WordPress.

    +
      +
    1. Backup the database
        +
      1. $ sudo mysql -e "show databases; \q"
      2. +
      3. $ sudo mysqldump mydbname > ~/mydbname.dump.sql
      4. +
      +
    2. +
    3. Back up www project root directory, e.g. /var/www/websites/www.example.com
        +
      1. Back up the whole wordpress install - it can be used as a complete snapshot
      2. +
      3. The wordpress install is a specific version and is tiny anyways
      4. +
      5. $ cd /var/www/websites/
      6. +
      7. Prune any big logs in logs: access.log, error.log
      8. +
      9. $ tar -czvf ~/www.example.com.bad.YYYYMMDD.HHMM.tar.gz www.example.com
      10. +
      11. Move the backups from ~ to the appropriate archival location
      12. +
      +
    4. +
    +

    WordPress Restore Procedure

    +
      +
    1. Backup the bad database and files. Include bad in the backup filenames.
        +
      • Use the WordPress Backup Procedure
      • +
      +
    2. +
    3. Disable the site in apache2
        +
      1. sudo a2dissite www.example.com
      2. +
      3. sudo service apache2 reload
      4. +
      +
    4. +
    5. Delete the database being overwritten in mysql - feel free to login and combine steps. These are added this way for atomicity."
        +
      1. $ sudo mysql -e "DROP DATABASE mydbname; \q"
      2. +
      3. $ sudo mysql -e "CREATE DATABASE wwwthesketchycom; \q"
      4. +
      5. $ sudo mysql mydbname < mydbname.bkp.sql
      6. +
      7. User grants stay intact when a database is dropped; no need to modify users
      8. +
      +
    6. +
    7. Assess and restore the file backup to see which files will be restored.
        +
      1. Typically the restore will be the entire public_html directory
      2. +
      3. Delete the old directory that will be replaced.
      4. +
      5. As www-data, restore the backup.
          +
        1. cd /var/www/websites
        2. +
        3. rm -rf www.example.com
            +
          • use extra caution, write the command then go back and add the -rf flags.
          • +
          +
        4. +
        5. sudo -u www-data tar -xzvf ~/www.thesketchy.com.bkp.YYYYMMDD.HHMM.tar.gz
        6. +
        +
      6. +
      +
    8. +
    9. Re-enable the site:
        +
      1. sudo a2ensite www.example.com
      2. +
      3. sudo service apache2 reload
      4. +
      +
    10. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/praxes/wp_install_another/index.html b/docs/praxes/wp_install_another/index.html new file mode 100644 index 00000000..637321e9 --- /dev/null +++ b/docs/praxes/wp_install_another/index.html @@ -0,0 +1,3188 @@ + + + + + + + + + + + + + + + + Wp Install Another - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Wp Install Another

    + +

    Another method for installing WordPress

    +
      +
    1. Get the WordPress files
        +
      1. cd /var/www/websites
      2. +
      3. sudo -u www-data mkdir -p ./public_html/logs
      4. +
      5. sudo -u www-data touch ./public_html/logs/error.log ./public_html/logs/access.log
      6. +
      7. cd public_html
      8. +
      9. sudo -u www-data wp core download
      10. +
      +
    2. +
    3. INSERT CUSTOM WP CONTENT STEP
        +
      • remove original wp-content
      • +
      • download wp-base git repo from taui source, use submodules for 3rd party themes/plugins
          +
        • consider hosting stable mirrors of these 3rd party things and upgrading manually
        • +
        • this would be quite possible by simply hosting my own submodules and leaving the 3rd party sources as non upstream
        • +
        +
      • +
      +
    4. +
    5. Generate the database, user, and password for this WordPress instance
        +
      1. Login to MySQL as the root user: $ sudo mysql -u root
          +
        • No password required on MySQL 5.7 (or enter password at prompt on 5.5)
        • +
        • note that you must use root system privs to login to root mysql on 5.7
        • +
        +
      2. +
      3. create database {Database Name};
      4. +
      5. create user '{User}'@'localhost' IDENTIFIED BY '{Password}'
          +
        • Does the next step create the user automatically if you don't do this?
        • +
        +
      6. +
      7. GRANT ALL PRIVILEGES ON {db}.* To '{user}'@'localhost' IDENTIFIED BY '{passwd}';
      8. +
      9. view your changes: mysql> select user, host, password from mysql.user;
      10. +
      11. mysql> FLUSH PRIVILEGES; then mysql> quit;
      12. +
      +
    6. +
    7. Set the wp-config.php salts and database info according to the MySQL information.
        +
      • sudo -u www-data cp wp-config-example.php wp-config.php
      • +
      • sudo -u www-data vim wp-config.php
      • +
      • DB_NAME
      • +
      • DB_USER
      • +
      • DB_PASSWORD
      • +
      • DB_HOST
      • +
      • $table_prefix
      • +
      • Authentication Unique Keys and Salts
      • +
      +
    8. +
    9. Use wp-cli for first time install
        +
      • it is usually aliased to wp
      • +
      • `sudo -u www-data wp core install --url=www.example.com --title=Example --admin_user=ex-admin --admin_password=123xyz --admin_email=admin@ex.com
      • +
      • if installed in a subdirectory www.example.com/subdir then wp option update siteurl http://www.example.com/subdir
      • +
      +
    10. +
    +

    Future

    +
      +
    1. HOW DOES THIS WORK? wp db create - create a new database using the wp-config.php
        +
      • not needed with my manual steps, but would i benefit from it?
      • +
      +
    2. +
    3. How about sane default settings from wp-cli?
        +
      • correct url rewrite rule
      • +
      • traceback pingback settings in 'reading' or whatever
      • +
      • remove tagline!!
      • +
      +
    4. +
    5. Enumerate even more sane defaults
    6. +
    7. Create step 2. This will need to:
        +
      1. install the custom wp-base
      2. +
      3. enable theme and plugins for wp-base
      4. +
      +
    8. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/recipes/Coconut_Chicken_Curry/index.html b/docs/recipes/Coconut_Chicken_Curry/index.html new file mode 100644 index 00000000..55c33b39 --- /dev/null +++ b/docs/recipes/Coconut_Chicken_Curry/index.html @@ -0,0 +1,3192 @@ + + + + + + + + + + + + + + + + Coconut Chicken Curry - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Coconut Chicken Curry

    +

    From: https://www.theendlessmeal.com/creamy-coconut-chicken-curry/

    +

    Modification Ideas

    +
      +
    • I used canned chicken (meh) but would prefer to use sliced chicken breast
    • +
    • Try replacing the chicken with tofu and vegetable boullion
    • +
    • Try replacing olive oil with coconut oil. Why?
    • +
    • Might be able to shorten the cook time before adding the coconut milk
    • +
    +

    Ingredients

    +
      +
    • 2 tbsp olive oil
    • +
    • 1 yellow onion, diced
    • +
    • 1 bulb (10-12 cloves) Garlic, minced or crushed
    • +
    • 2 tbsp ginger, diced
    • +
    • 28 oz tomatoes, diced - 8x 3.5oz tomatoes
    • +
    • 8-16 oz chicken - 1 can chicken
    • +
    +

    Curry Mix

    +

    Grind the spices together in a coffee grinder.

    +
      +
    • 1 tbsp turmeric
    • +
    • 1 tbsp cumin seeds
    • +
    • 1 tbsp coriander seed
    • +
    • 1 tsp fenugreek seed
    • +
    • 1 tsp fennel
    • +
    +

    Additional Spices

    +
      +
    • 2 tsp salt
    • +
    • 1 tsp cayenne powder
    • +
    +

    Directions

    +

    I recommended cooking 2 cups basmati rice. I used a ricemaker.

    +
      +
    1. Saute the diced onion, garlic, and ginger in 2 tbsp olive oil
    2. +
    3. Stir in the Curry Mix and Additonal Spices and saute for 1 minute
    4. +
    5. Stir in chicken coating with spices, then stir in the diced tomato fully
    6. +
    7. Cook on low for 20 minutes with a lid, stirring frequently
    8. +
    9. Add a can of coconut milk, cook for an additional 5 minutes
    10. +
    11. Serve on a plate
    12. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/2018_election_information/index.html b/docs/references/2018_election_information/index.html new file mode 100644 index 00000000..d9006b3d --- /dev/null +++ b/docs/references/2018_election_information/index.html @@ -0,0 +1,3161 @@ + + + + + + + + + + + + + + + + 2018 Election Information - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    2018 Election Information

    +

    How do I best reduce which elections exist in all USA governments in 2018?

    +

    Census of Governments (COG): https://www.census.gov/govs

    +

    A census of governments is run by the US federal government every 5 years, in years ending in 2 and 7.

    +

    I will be using derivative data sources, so this may not be used, or may be used to validate completeness.

    +

    Each government is assigned a GID, the 2007 GID lookup is here.

    +

    The 2017 COG is expected to conclude in September 2018.

    +

    Code for America has outlined a project attempting to work with this data, and may still be working with this.

    +

    Wikipedia historically keeps good records

    +

    For streaming changes, Wikipedia might be the best bet.

    + +

    Reddit Politics - https://www.reddit.com/r/politics

    +

    Biased view, but generally in my direction. Has good data.

    + +

    Politico Election Results - https://www.politico.com

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/BranchPythonOperator_Concepts/index.html b/docs/references/BranchPythonOperator_Concepts/index.html new file mode 100644 index 00000000..19a46fc9 --- /dev/null +++ b/docs/references/BranchPythonOperator_Concepts/index.html @@ -0,0 +1,3360 @@ + + + + + + + + + + + + + + + + Branchpythonoperator Concepts - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Branchpythonoperator Concepts

    + +

    BranchPythonOperator

    +

    There isn't very good documentation for this feature yet.

    +

    Why?

    +

    The BranchPythonOperator is used to create control flow in a DAG.

    +

    Towards Automating Changes to Data

    +

    If there is unexpected input from a data source, then automate preprocessing the new data format so the automation can be improved.

    +

    NB: This type of branch would probably trigger another DAG.

    +

    Inter-task communication

    +

    There are two options:

    +
      +
    • variables
    • +
    • XComs
    • +
    +

    Variables sit in a global variables object, where as XComs are pushed and pulled between tasks.

    +

    For task-to-task communication, we will use XComs.

    +

    Passing Context to BranchPythonOperator

    +

    BranchPythonOperator inherits from PythonOperator and is defined in the same module. Both share use of provide_context=True as a keyword argument. If this is passed, the python_callable function must receive **kwargs. The context includes task_instance.xcom_pull which pulls information from other tasks.

    +

    Notes

    +

    Each branch must point to a task; if there isn't anything to do, use a DummyOperator.

    +

    References

    +

    General

    + +

    Examples

    + +

    Concepts & Tutorials

    + +

    API Reference

    +
      +
    • BaseOperator
    • +
    • TaskInstance.xcom_pull
        +
      • BaseOperator.xcom_pull imports TaskInstance.xcom_pull from context
      • +
      • You must pass key=None or any desired key/value to get tasks that are from xcom_push
      • +
      • By default tasks from xcom_push are ignored
      • +
      +
    • +
    +

    Source Code

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/aws-certs-and-trainings/index.html b/docs/references/aws-certs-and-trainings/index.html new file mode 100644 index 00000000..467e6250 --- /dev/null +++ b/docs/references/aws-certs-and-trainings/index.html @@ -0,0 +1,3276 @@ + + + + + + + + + + + + + + + + Aws Certs And Trainings - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    AWS Certifications

    +

    A redux for navigating the world of AWS certification.

    +

    Canonical Certification Resource

    +

    Certification Benefits

    +

    Learning Paths

    +

    Optional "foundational certification": AWS Certified Cloud Practitioner

    +

    Certification FAQ

    +
      +
    • There are 4 learning paths
        +
      • Cloud Practitioner (foundational)
      • +
      • Solutions Architect
      • +
      • Developer
      • +
      • Operations
      • +
      +
    • +
    +

    Associate Level Certificates

    +
      +
    1. AWS Certified Solutions Architect – Associate
    2. +
    3. AWS Certified Developer - Associate
    4. +
    5. AWS Certified SysOps Administrator - Associate
    6. +
    +

    Other Certificates

    +

    Check the available certificates

    +

    There are no prerequisites for any certificates.

    +
      +
    • Currently there are the following quantity of certificates:
        +
      • 1 foundational
      • +
      • 3 associate
      • +
      • 2 professional
      • +
      • 5 specialty
      • +
      +
    • +
    +

    Recertification

    +

    Certificates are valid for 3 years, recertification is apparently half price.

    +

    professional recertifications also cover the associate certificate for the learning path path.

    +

    It isn't clear -- it looks like the "Devops Engineer - Professional" certificate renews either, or both, SysOps Administrator - Associate and Developer - Associate certificates. Is it either or is it both?

    +

    Validation

    +

    You can validate someone's certificate number here

    +

    Training Resources

    +

    There are free training resources on the learning paths page.

    +

    aws.training

    +

    [Primary resource]((https://www.aws.training/) for scheduling in-person trainings and exams.

    +
      +
    • Schedule online practice exams or in-person real exams
    • +
    • Schedule courses
    • +
    +

    aws.training Learning Library

    +

    This can be tough to search, the filters don't seem super accurate.

    + +

    AWS Resources

    + +

    AWS Free Courses

    + +

    Udemy Courses

    +

    Udemy has a ton of competing courses on their platform.

    + + + +

    Practice Exams

    + +

    Developer Course - Freshstart Links JSON

    +
    {"title":"aws developer cert - current links","date":"23/8/2019","tabs":[{"title":"AWS Cloud Practitioner","url":"https://aws.amazon.com/training/path-cloudpractitioner/?tccta=icon","win":"406"},{"title":"Exam Readiness: AWS Certified Developer – Associate (Digital) | AWS Training & Certification","url":"https://www.aws.training/Details/Curriculum?id=19185","win":"406"},{"title":"AWS Cloud Practitioner Essentials (Second Edition) | AWS Training & Certification","url":"https://www.aws.training/Details/Curriculum?id=27076","win":"406"},{"title":"Learning Path - Operations","url":"https://aws.amazon.com/training/path-operations/","win":"406"},{"title":"AWS Training FAQs","url":"https://aws.amazon.com/training/faqs/?nav=tc&loc=8","win":"406"},{"title":"AWS Certified Cloud Practitioner","url":"https://aws.amazon.com/certification/certified-cloud-practitioner/","win":"406"},{"title":"Learning Path - Developer","url":"https://aws.amazon.com/training/path-developing/","win":"406"},{"title":"APN Partner Training and Certification","url":"https://aws.amazon.com/partners/training/","win":"406"}],"created":1566600444391}
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/bash_and_gnu_tricks/index.html b/docs/references/bash_and_gnu_tricks/index.html new file mode 100644 index 00000000..de7f3cd6 --- /dev/null +++ b/docs/references/bash_and_gnu_tricks/index.html @@ -0,0 +1,3171 @@ + + + + + + + + + + + + + + + + Bash And Gnu Tricks - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Bash And Gnu Tricks

    + +

    Tricks in GNU and bash

    +

    These are combined because you usually mash them together into a result.

    +

    History

    +

    Taken from https://www.washington.edu/computing/unix/history.html

    +

    It is also possible to use certain words from commands and do a regular expression type modifier. This may not be worth learning.

    +
      +
    • !! repeat last command
    • +
    • !-n repeat n commands ago, examples:
        +
      • !-2, repeat 2 commands ago
      • +
      • !-1 == !!, repeat last command
      • +
      +
    • +
    • !n repeat nth command as indexed in history command
    • +
    • !<substring> repeats most recent command beginning with <substring>
    • +
    +

    strace - trace system calls and signals

    +
      +
    1. Example: sudo strace -f -o slack.trace su robbintt -c 'slack'
    2. +
    +

    I used this to trace where my ubuntu 16.04 slack app was silently failing. I thought it must be a file permissions error because the command slack would run for root but not for user. Strace showed me the files touched before failing.

    + +

    Use ctrl+r and start typing. This 'reverse-I-search' is a +more convenient way to search history.

    +

    It is also a nice trick to tag commands you will need.

    +

    For example:

    +

    ls -la /some/long/directory # mytag

    +

    Then just search the tag in reverse i search

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/bazel_java/index.html b/docs/references/bazel_java/index.html new file mode 100644 index 00000000..ae3fbf8b --- /dev/null +++ b/docs/references/bazel_java/index.html @@ -0,0 +1,3180 @@ + + + + + + + + + + + + + + + + Bazel Java - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Bazel and Java

    +

    Installed bazel and adoptopenjdk via homebrew for now.

    +

    Goal

    +

    Get a java env up suitable for modern java dev. Make something interesting.

    +

    Subgoals:

    +
      +
    1. easily use tmux+vim to navigate and work
        +
      • build on file change
      • +
      +
    2. +
    3. follow modern java patterns
        +
      • maven
      • +
      • bazel
      • +
      +
    4. +
    5. deploy to aws lambda, ecs, or to local k3s
    6. +
    +

    How do I target AWS java

    +

    No idea, guess I install it and specify it in the bazel build?

    +
      +
    • amazon-corretto-11
    • +
    • amazon-corretto-8
    • +
    • java-1.8.0-openjdk
    • +
    +

    References

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/c_programming/index.html b/docs/references/c_programming/index.html new file mode 100644 index 00000000..0b7099d8 --- /dev/null +++ b/docs/references/c_programming/index.html @@ -0,0 +1,3744 @@ + + + + + + + + + + + + + + + + C Programming - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    C Programming

    + +

    Notes - K&R - The C Programming Language

    +
      +
    1. How to read "statements" in C (k&r: p. 19)
        +
      • One "statement" can be a single statement, like int c;, or a group of statements inside braces
      • +
      • A control flow keyword also initiates a single statement: +/* this is one statement, even though it is two nested control flow keywords */ +while ((c = getchar()) != EOF) + if (c == '\n') + ++nl;
      • +
      +
    2. +
    3. Assignments associate from right-to-left
        +
      • The following are equivalent:
          +
        • nl = nw = nc = 0
        • +
        • nl = (nw = (nc = 0))
        • +
        +
      • +
      +
    4. +
    5. Evaluations with && and || are left-to-right
        +
      • if (c == ' ' || c == '\n' || c == '\t')
      • +
      • Evaluation stops as soon as truth or falsehood is known, "short-circuit" or "minimal" evaluation
      • +
      +
    6. +
    +

    Resources

    +

    A list of resources, subdivide as it grows.

    +
      +
    1. The slideshow that got me started here +
    2. +
    3. comp.lang.c guide
    4. +
    5. C Standard Library
    6. +
    7. C POSIX Library
    8. +
    9. C++ STL - Standard Template Library
    10. +
    11. gcc docs
    12. +
    13. LLVM Sanitizers (Google)
    14. +
    15. What is the datatype of a pointer in c?
        +
      • henner says: a long in any particular system should be able to hold a pointer
      • +
      +
    16. +
    17. Tips on printf (escape sequences)
    18. +
    19. Wikipedia "Escape sequences in C"
    20. +
    21. a make guide
    22. +
    23. gnu make guide
    24. +
    25. Ascii table: man ascii
    26. +
    27. Learn x in y minutes: C
    28. +
    +

    Definitions

    +
      +
    1. gcc - gnu compiler collection
    2. +
    3. gnu binutils - sister project of gcc
    4. +
    5. avr-gcc - version of gcc for the avr class of microcontrollers
        +
      • has 3 available compilers: c, c++, ada
      • +
      • compiler does not assemble or link the final code
      • +
      +
    6. +
    7. gas - gnu assembler
    8. +
    9. GNU Libc - GNU C Standard Library
        +
      • +
      +
    10. +
    11. AVR Libc - AVR GCC C Standard Library
    12. +
    13. GNU Make - Building software / Makefile stuff
        +
      • Some distributions of the toolchains, and other AVR tools such as MFile, contain a Makefile template written for the AVR toolchain and AVR applications that you can copy and modify for your application.
      • +
      +
    14. +
    15. AVRDUDE - program your device
    16. +
    17. avr-gdb, avr-insight, and ddd
        +
      • avr versions of common make tools.
      • +
      +
    18. +
    19. AVaRICE - AVaRICE is a back-end program to AVR GDB and interfaces to the Atmel JTAG In-Circuit Emulator (ICE), to provide emulation capabilities.
    20. +
    21. SimulAVR - SimulAVR is an AVR simulator used as a back-end with AVR GDB.
    22. +
    23. SRecord is a collection of powerful tools for manipulating EPROM load files. It reads and writes numerous EPROM file formats, and can perform many different manipulations.
    24. +
    25. MFile is a simple Makefile generator is meant as an aid to quickly customize a Makefile to use for your AVR application.
    26. +
    +

    Codebases to read and participate in

    +
      +
    1. sqlite3
    2. +
    3. python3
    4. +
    +

    how 2 be 1337

    +

    Knuth Reward Check - In the preface of each of his books and on his website,[7] Knuth offers a reward of $2.56 (USD) to the first person to find each error in his published books, whether it be technical, typographical, or historical. Knuth explains that $2.56, or 256 cents, corresponds to one hexadecimal dollar.[8] "Valuable suggestions" are worth 32 cents, or about  1⁄8 of the errors in the book (0.001 hexadecimal dollars or 0.1 hexadecimal cents). In his earlier books a smaller reward was offered. For example, the 2nd edition of The Art of Computer Programming, Volume 1, offered $2.00.

    +

    Learn C The Hard Way (Zed Shaw)

    +

    Some notes as I read through lcthw.

    +

    Quickref

    +
      +
    1. : ? (same category as && || !) is logical ternary. Expression a:b?c maps to if a then b else c
    2. +
    +

    Keywords - Alphabetical

    +
      +
    • case: A branch in a switch-statement.
    • +
    • char: Character data type.
    • +
    • const: Make a variable unmodifiable.
    • +
    • continue: Continue to the top of a loop.
    • +
    • default: Default branch in a switch-statement.
    • +
    • do: Start a do-while loop.
    • +
    • double: A double floating point data type.
    • +
    • else: An else branch of an if-statement.
    • +
    • enum: Define a set of int constants.
    • +
    • extern: Declare an identifier is defined externally.
    • +
    • float: A floating point data type.
    • +
    • for: Start a for-loop.
    • +
    • goto: Jump to a label.
    • +
    • if: Starts an if-statement.
    • +
    • int: An integer data type.
    • +
    • long: A long integer data type.
    • +
    • register: Declare a variable be stored in a CPU register.
    • +
    • return: Return from a function.
    • +
    • short: A short integer data type.
    • +
    • signed: A signed modifier for integer data types.
    • +
    • sizeof: Determine the size of data.
    • +
    • static: Preserve variable value after its scope exits.
    • +
    • struct: Combine variables into a single record.
    • +
    • switch: Start a switch-statement.
    • +
    • typedef: Create a new type.
    • +
    • union: Start a union-statement.
    • +
    • unsigned: An unsigned modifier for integer data types.
    • +
    • void: Declare a data type empty.
    • +
    • volatile: Declare a variable might be modified elsewhere.
    • +
    • while: Start a while-loop.
    • +
    +

    Keywords - Grouped

    +

    Note: keywords in C only fall into two categories: data management and control flow

    +
    Data Types & Modifiers
    +
      +
    • int: An integer data type.
    • +
    • long: A long integer data type.
    • +
    • +

      short: A short integer data type.

      +
    • +
    • +

      signed: A signed modifier for integer data types.

      +
    • +
    • +

      unsigned: An unsigned modifier for integer data types.

      +
    • +
    • +

      char: Character data type.

      +
    • +
    • +

      float: A floating point data type.

      +
    • +
    • +

      double: A double floating point data type.

      +
    • +
    • +

      const: Make a variable unmodifiable.

      +
    • +
    • volatile: Declare a variable might be modified elsewhere.
    • +
    • extern: Declare an identifier is defined externally.
    • +
    • void: Declare a data type empty.
    • +
    • static: Preserve variable value after its scope exits.
    • +
    • register: Declare a variable be stored in a CPU register.
    • +
    • auto: Give a local variable a local lifetime.
    • +
    +
    Compound Data Types
    +
      +
    • +

      struct: Combine variables into a single record.

      +
    • +
    • +

      union: Start a union-statement.

      +
    • +
    • +

      enum: Define a set of int constants.

      +
    • +
    • +

      typedef: Create a new type.

      +
    • +
    +
    Data Introspection
    +
      +
    • sizeof: Determine the size of data.
    • +
    +
    Control Flow
    +
      +
    • if: Starts an if-statement.
    • +
    • +

      else: An else branch of an if-statement.

      +
    • +
    • +

      for: Start a for-loop.

      +
    • +
    • +

      do: Start a do-while loop.

      +
    • +
    • +

      while: Start a while-loop.

      +
    • +
    • +

      continue: Continue to the top of a loop.

      +
    • +
    • +

      break: Exit out of a compound statement.

      +
    • +
    • +

      switch: Start a switch-statement.

      +
    • +
    • case: A branch in a switch-statement.
    • +
    • +

      default: Default branch in a switch-statement.

      +
    • +
    • +

      goto: Jump to a label.

      +
    • +
    • +

      return: Return from a function.

      +
    • +
    +

    LCTHW References

    +
      +
    • man 3 printf
    • +
    • gdb quickref - learn c the hard way page 36-37
        +
      • mentions: run, break, backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach pid, detach, list
      • +
      +
    • +
    • lldb quickref - learn c the hard way page 37-38
        +
      • mentions: run [args], breakpint set, thread backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach -p pid, detach, list
      • +
      +
    • +
    • use gdb or lldb to debug your compiled program
        +
      • type run in the debugger command line to run the application
          +
        • a bunch of helpful gdb debugging flags from zed
        • +
        • gdb --args ./ex3 myarg1 myarg2 myargetc pass args to program
        • +
        +
      • +
      • apple: lldb has the same commands available but you have to read the manpages for the llvm names
      • +
      +
    • +
    • valgrind - track all your memory and tell you when you messed it up
        +
      • gotta know how to work with the heap
      • +
      • valgrind ./ex3
      • +
      +
    • +
    • apple does not have valgrind:
        +
      • gdb --batch --ex run --ex bt --ex q --args ./ex3
      • +
      • "a very lame alternative to valgrind, the most useful command for debugging c code"
      • +
      +
    • +
    • splint linter
    • +
    • address sanitizer - asan +
    • +
    +

    LCTHW Makefile References

    +
      +
    • always use tabs in Makefiles. Never spaces.
    • +
    • -g generate debug information
    • +
    • -Wall (gnu gcc)
        +
      • From the manpage:
      • +
      +
    • +
    +
    +

    This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.

    +
    +

    Macros (source)

    +
    +

    A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.

    +

    You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator defined (see Defined) can never be defined as a macro, and C++'s named operators (see C++ Named Operators) cannot be macros when you are compiling C++.

    +
    +

    Others' Resources

    +
      +
    • zv says: man ld.so - it's worth your time in my view to at least skim the ld.so manpage
    • +
    +

    Mitch says:

    +

    "The C Programming Language by Kernighan and Ritchie"

    +

    TheAceOfHearts says:

    +

    "C is a very small and simple language but the tooling and patterns are old and mysterious."

    +
      +
    1. make
    2. +
    3. autoconf
    4. +
    5. how the compiler + preprocessors work
        +
      • what do all the flags even mean!?!?!
      • +
      +
    6. +
    7. how making cross platform stuff works
    8. +
    9. how to pull in and use c "libraries"
    10. +
    11. C-isms
    12. +
    13. how to test
    14. +
    15. +

      etc

      +
    16. +
    17. +

      some platform standards

      +
        +
      • autotools in GNU, msbuild on win
      • +
      +
    18. +
    +

    Lizzie says:

    +

    make - Some people do it strangely but ime 90% of makefiles do the exact same thing: "compile .c files to .o files with CFLAGS. link all the relevant .o files with LDFLAGS"

    +
      +
    1. +

      learn to use asan and ubsan right off the bat. They are compiler extensions for dynamic bounds / overflow checking.

      +
        +
      1. asan: Address Sanitizer
      2. +
      3. ubsan: GCC Undefined Behavior Sanitizer
      4. +
      5. -fsanitize=address -fsanitize=undefined
      6. +
      +
    2. +
    3. +

      learning gdb also helps a lot

      +
        +
      1. gdb
      2. +
      +
    4. +
    5. +

      klib - a fast generic datastructure library for c

      +
    6. +
    7. +

      c Language Lawyer perspective

      +
    8. +
    9. +

      Programming Lanugages - C // International Standard 9899:201x Draft April 2011

      +
    10. +
    11. +

      Check out struct initializers - not a common pattern but been around for 20 years.

      +

      c +struct mystruct mydata = {.b = c, .d = e}; +vs +c +struct mystruct mydata; +memset(&mydata, 0, sizeof(mydata)); +mydata.b = c; +mydata.d = e; +- removes potential bugs: + - passing the wrong size to memset + - getting the size and value arguments to memset reversed on accident. + - using mydata before it's initialized + - memsetting a pointer, which is UB +- note from henner: + - > I am always annoyed that the designated initializers ( { .a = 42} ) don't work in C++. Sometimes I just sprinkle in a C file for initializers

      +
    12. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/corewar/index.html b/docs/references/corewar/index.html new file mode 100644 index 00000000..b6e578af --- /dev/null +++ b/docs/references/corewar/index.html @@ -0,0 +1,3116 @@ + + + + + + + + + + + + + + + + Corewar - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + + + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/django-general/index.html b/docs/references/django-general/index.html new file mode 100644 index 00000000..1cf17779 --- /dev/null +++ b/docs/references/django-general/index.html @@ -0,0 +1,3259 @@ + + + + + + + + + + + + + + + + Django General - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    + +
    +
    + + + +
    +
    + + + + + + + + + +

    Razzi's Class

    +

    Django is used in industry! Pinterest, NASA, Venmo, Sighten, Instagram, etc.

    +

    Overview

    +
      +
    • Django is designed to make development fast...
    • +
    • Razzi: "Django is the present, not the future."
    • +
    • If you choose an unsupported database, you will be fighting the framework.
    • +
    • BUT - Django keeps up with internet trends! So it could end up being the future.
    • +
    • If you are not using a relational database, you may not need Django. It's for working with RDBMS.
    • +
    • Django can serve REST or GraphQL APIs as well, great backend for modern frontend.
        +
      • For example, Razzi's company switched to Single Page Apps (SPAs) on the frontend with their same django app on the backend (kept old django templates at the time probably)
      • +
      +
    • +
    +

    Django Benefits

    +
      +
    • Out-of-the-box functionality: don't reinvent security, authentication sessions, database access, email...
    • +
    • Ease of prototyping: easier to start and deploy your project using a well-supported framework
    • +
    • Scales well to large teams, large projects
        +
      • Django apps make it easy to split up and reuse functionality
      • +
      +
    • +
    +

    django is the present, not the future

    +
      +
    • Designed around rendering html pages
    • +
    • If you chose an unsupported database, you'll be fighting the framework
    • +
    • The django framework keeps up with internet trends, though, and now supports asynchronous programming
    • +
    • Django can serve REST and GraphQL APIs as well, making it a great backend for a modern frontend
    • +
    +

    Django has some premade social networks, we will roll our own

    +
      +
    • Vataxia https://github.com/buckyroberts/Vataxia
    • +
    • Bootcamp https://github.com/vitorfs/bootcamp
    • +
    +

    Our Class Schedule

    +
      +
    1. Signup / login / logout (today)
    2. +
    3. Posting (March 5, next Monday)
    4. +
    5. Messaging (March 12)
    6. +
    7. API, static frontend (March 19)
    8. +
    +

    First Time Setup

    +

    The manage.py is executable by default in Python 3. Simply ./manage.py runserver or any other argument.

    +

    You can python manage.py runserver 80 for example, to run on any port.

    +
      +
    1. Python 3 in a virtualenv
    2. +
    3. pip install django
    4. +
    5. django-admin startproject
    6. +
    7. python manage.py migrate
    8. +
    9. python manage.py createsuperuser
    10. +
    11. python manage.py startapp social
    12. +
    +

    Specific Technologies

    +
      +
    • DocRaptor for html to pdf in Django - Razzi used it at a company. stack overflow
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/emacs/index.html b/docs/references/emacs/index.html new file mode 100644 index 00000000..e5350fc8 --- /dev/null +++ b/docs/references/emacs/index.html @@ -0,0 +1,3309 @@ + + + + + + + + + + + + + + + + Emacs - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Emacs

    + +

    Simpler Emacs

    +

    I intend to install a number of packages from spacemacs.

    +

    Quickref

    +
      +
    1. M-x: get a prompt
    2. +
    +

    At the prompt

    +

    nb: RET is return key, the whitespace is for readability.

    +
      +
    • package-list-packages RET: list packages
    • +
    • package-install RET: get a package install prompt
        +
      • evil RET: i did not find evil-mode in the packages, so installed evil
      • +
      +
    • +
    +

    Installing Packages

    +

    The emacs wiki has a guide.

    +

    Installing use-package

    +

    An easier way to install packages? People like it. Seems heavy to me...

    + +

    Customize Group

    +
      +
    • M-x customize-group seems to have context for customizing stuff
    • +
    • try it and choose undo-tree
    • +
    +

    Notes

    +
      +
    1. M-: You can press escape then the key instead of meta.
    2. +
    +

    Future

    +
      +
    1. Evil Plugins
        +
      • lots of additional features
      • +
      +
    2. +
    3. Undo Tree should go to a directory in $HOME? right now it goes to $TMPDIR in macos which may be deleted??
    4. +
    5. Undo Tree & Persistent Buffer - done?
        +
      • emacswiki.org: Category Undo
      • +
      • UndoTree: like vim?
          +
        • apparently has a corruption bug with this feature, a fork is incomplete
        • +
        • apparently undo-tree does this but it has a major corruption bug with this specific feature, and the solution right now is to use emacs server, so i'm going to do that
        • +
        +
      • +
      +
    6. +
    7. emacs server - the only way to get persistent undo for now as you never exit the session
    8. +
    +

    Desired Spacemacs Packages

    +
      +
    1. helm
    2. +
    3. evil-mode
    4. +
    +

    Resources

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/fight-global-internet-propaganda-review/index.html b/docs/references/fight-global-internet-propaganda-review/index.html new file mode 100644 index 00000000..a5f1f65a --- /dev/null +++ b/docs/references/fight-global-internet-propaganda-review/index.html @@ -0,0 +1,3232 @@ + + + + + + + + + + + + + + + + Fight Global Internet Propaganda Review - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Fighting Global Internet Propaganda Review

    +

    Some people are fighting online trolls as a team online, essentially as a campaign.

    +

    This is some information about this movement.

    +

    Intentions of Propaganda

    +

    This section could use some well researched information, but there are some obvious ones:

    +
      +
    1. Remove thoughtful people from the political process
    2. +
    3. Polarize the political process to create deeper fractures in ideology
    4. +
    5. Overfocus people on literally anything
        +
      • prevent them from seeing the big picture
      • +
      +
    6. +
    7. Appeal to emotion
    8. +
    9. Apply self-consistency logic (you agree to this, therefore you must agree to that)
        +
      • Self consistency is the primary driver for human motivation.
      • +
      +
    10. +
    +

    Primary Targets for Propaganda

    +
      +
    • reddit
    • +
    • twitter
    • +
    • facebook
    • +
    +

    Potential Tactics for Distributing Propaganda

    +
      +
    1. Networks of trolls with simulated traffic
        +
      • 'record and playback' real account activity using real network topography as a template to evade detection
      • +
      • build many disjoint layers of fake networks that can be activated for particular purposes
      • +
      +
    2. +
    3. Recruit vulnerable people
        +
      • identify more intimate online forums for people seeking more personal attention: 4chan, something awful
          +
        • create new online forums to cultivate this:
        • +
        • voat, gab, PewTube, WrongThink, Infogalactic, GoyFundMe, wasp.love
        • +
        • "The Alt-Right Created a Parallel Internet. It's an unholy mess." - NYT Article
        • +
        +
      • +
      • misdirected people can exert influence on real social networks
      • +
      • viral sharing is already addictive
      • +
      • use narrative storytelling to move people further than the mainstream pool of facts
      • +
      +
    4. +
    +

    Trollfare

    +
    +

    the purpose of this sub is, for a start, to have free-form discussions about how american or allied reddit users can more effectively combat RU and other hostile propaganda on reddit and elsewhere on the internet.

    +
    + +

    Securing Democracy

    +

    Tracking Russian influenced twitter hashtags.

    + +

    Twitter banned 70 million accounts

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/git/index.html b/docs/references/git/index.html new file mode 100644 index 00000000..bfda1a45 --- /dev/null +++ b/docs/references/git/index.html @@ -0,0 +1,3109 @@ + + + + + + + + + + + + + + + + Git - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Git

    + +

    Git References

    +

    Removing files from a repository history

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/html5-game-dev/index.html b/docs/references/html5-game-dev/index.html new file mode 100644 index 00000000..ebe2d32a --- /dev/null +++ b/docs/references/html5-game-dev/index.html @@ -0,0 +1,3375 @@ + + + + + + + + + + + + + + + + Html5 Game Dev - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Learning HTML5 Native Game Dev

    +

    It looks like there are a lot of different ways to do this, and games are typically packaged for ios using phonegap or cordova.

    +

    Goals

    +
      +
    1. Make some simple games in html5
    2. +
    3. Somehow translate the games to mobile native (Android & iOS)
        +
      • Otherwise I may have to relearn a lot of platform specific knowledge...
      • +
      +
    4. +
    5. Leverage existing javascript libraries for multiplayer, maybe even run a server/api for play between phone and browser users
    6. +
    +

    Trajectory

    +
      +
    1. Package someone else's game for iOS with Phonegap (or Cordova) just to see it happen.
    2. +
    3. I plan to use the default phonegap hello world app to test this out.
    4. +
    5. Make modifications to the game and package again to iOS.
    6. +
    +

    More Engines!

    + +

    Notes

    +
      +
    • SVG Keyframe animations may be sort of restricted to data visualization, not games
    • +
    • Game Engines tend to use webgl and fallback to canvas
    • +
    • Converting to iOS +
    • +
    +

    Option: phaser.js

    +

    They offer a community edition and a paid product. They claim it is intended to be packaged for native apps. I wonder if many examples of this exist. I should get it up and running for ios and android. It is the 2nd most starred on github after pixi.js.

    +

    Phase is a 2d game engine.

    +

    Resources

    +
      +
    • +
    +

    Option: react-game-kit

    +

    Pitch from the dev:

    +
      +
    • Use the same game code for web, iOS, android
    • +
    • Use react
    • +
    • Hot reload game logic
    • +
    • Don't have to learn unity
    • +
    +

    References

    +

    source

    +

    interactive guide

    +

    Recommendations

    +

    Jeffrey built this (source).

    +
    +

    i made this once. this uses matter.js as well as react-game-kit, the status of which i’m unaware. seems straightforward enough, although it uses the DOM instead of canvas, which i’m iffy about - Jeffrey

    +

    Formidable Labs does great stuff - Nick

    +
    +

    Option: PlayCanvas

    +

    I signed up for this with a google account. It seems to provide an environment for pretty rich 3d art. I doubt you would develop the assets in playcanvas, but I don't know that much about it. It doesn't seem like quite what I am looking for.

    +

    PlayCanvas is a suite of products:

    +
      +
    • PlayCanvas Engine
        +
      • Open Source / MIT Licensed on Github: PlayCanvas Engine
      • +
      • "The open-source PlayCanvas Engine is the world's most advanced WebGL game engine. Use JavaScript to program anything from simple 2D games to advanced 3D graphics simulations. All written in standards-compliant, cross-platform HTML5 for every major browser and device."
      • +
      • Tiny footprint, mobile optimized: "The PlayCanvas Engine has a tiny footprint that loads and executes incredibly quickly. The PlayCanvas Engine gives incredible performance, even on devices such as the iPhone 4S."
      • +
      +
    • +
    • a webgl authoring tool, with a UI similar to adobe products.
    • +
    +

    Option: pixi.js

    +

    2D Sprite Managment. PixiJS is a rendering library, so you still need the game framework. It's sounding like there is a standard way to pack javascript into a native app, so that might not be important.

    +

    References

    + +

    Option: Unreal Engine 4

    +

    Does html5, maybe overkill.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/html5-phaser-pixi-phonegap/index.html b/docs/references/html5-phaser-pixi-phonegap/index.html new file mode 100644 index 00000000..ef2c683a --- /dev/null +++ b/docs/references/html5-phaser-pixi-phonegap/index.html @@ -0,0 +1,3475 @@ + + + + + + + + + + + + + + + + Html5 Phaser Pixi Phonegap - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Phaser3, Pixi, and Phonegap

    +

    This build toolchain is easy to set up, with practice.

    +

    Questions

    +
      +
    1. What version of pixi.js does phaser3 use? Check phaser3 source.
    2. +
    3. What pixi.js plugins does phaser3 use? - Check phaser3 source.
    4. +
    5. How do canvas sizes interact with platform builds? Is there a dynamic canvas size or some canvassize detection method? Or is it done another way? +
    6. +
    7. Question for later: Do I need to be using phonegap? Why not just use cordova?
        +
      • Well... how would I build the IPA? Figure this out later...
      • +
      +
    8. +
    +

    Phonegap

    +

    Phonegap build is a webapp that will build from your hosted repos, but you do need to provide an app key from Apple, which takes awhile to set up.

    +

    Set Up

    +
      +
    1. You can build and test directly in phonegap. This development environment is intended to be faithful to all platforms
        +
      • What issues exist and can be checked for, and how?
      • +
      +
    2. +
    3. Apple Developer account + $99+tax fee
    4. +
    5. Register devices for testing
    6. +
    7. Generate a key and get it signed for your account and device
    8. +
    9. Build, Download, and Install the app on your device (phone, tablet, even laptop via steam??)
    10. +
    +

    Build

    +
      +
    1. Use the phaser + phonegap framework managed by Adobe (see trello to fill this in).
    2. +
    3. npm install -g phonegap@latest
    4. +
    5. phonegap create ./MyPhaserApp --template phonegap-template-phaser
    6. +
    7. You can then use phonegap (I used the macos app ui) to test the project.
    8. +
    9. You can also use phonegap (I used the phonegap-build webapp) to build the project for target devices.
    10. +
    +

    Build from a custom/local phonegap app template

    +

    I replaced the phonegap-template-phaser, which I guess defaults to the NPM package, and I used a filepath instead. It copied everything over, but didn't create everything that the node app created. It seemed to skip three folders: .phonegap --template` just wraps cordova --template.

    +

    The above worked fine but when building my phaser .ipa demo, I actually copied a phaser2 project (the project created from the phonegap --template command), then added the phaser 3.10.1 files to that.

    +

    My Phaser3 retrofit app runs with the Phaser3 "hello world" demo!

    +

    Issues

    +

    I think you can also use a git remote with cordova because of the phonegap source code. However, I tried to specify one and it told me it can't find the package.json, so something seems to be going wrong?

    +

    Install

    +
      +
    1. Drop the .ipa file into your phone with the Apple official app: Apple Configurator 2
    2. +
    +

    Using Phaser3 and Pixi

    +

    Both phaser.js and pixi.js are MIT licensed, so bundle away.

    +

    Phaser3 is under active development, and phaser3 has already been released.

    +

    Pixi.js is also actively developed.

    +

    Phaser 2 Examples

    +

    here

    +

    Phaser 3 Examples

    +

    Phaser 2 Sandbox

    +

    There's a Phaser 2 sandbox for quick and dirty testing.

    +

    Phaser 3 Sandbox

    +

    If this is broken you can get a phaser 3 sandbox in the phaser examples app.

    +

    This also exists.

    +

    Use pixi.js in phaser2

    +

    This is from 2016

    +
    +

    All Phaser display objects (group, sprites...) are based on PIXI ones. PIXI objects can be rendered in phaser render tree. the only problem is the update and postUpdate function.

    +

    I solved it adding this simple patch:

    +
    +
    PIXI.DisplayObject.prototype.update = function () { };
    +PIXI.DisplayObject.prototype.postUpdate = function () { };
    +
    + +
    +

    this patch adds a empty function for "update" and "postUpdate" methods in PIXI displayObjects prototype. In that case Phaser update tree founds a function to execute.

    +
    +

    Input in Phaser

    +

    We want mobile-first multiplatform, which means we really only have multitouch events to go off of, and the relationship of those events to regions of the screen...

    +

    some info

    +

    Building for Multiple platforms

    +

    Discuss how to build for android and ios, or multiple iphones.

    +

    stub

    +

    Emulating platforms

    +

    Discuss

    +

    stub

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/html5-phonegap-for-ios/index.html b/docs/references/html5-phonegap-for-ios/index.html new file mode 100644 index 00000000..26f84435 --- /dev/null +++ b/docs/references/html5-phonegap-for-ios/index.html @@ -0,0 +1,3218 @@ + + + + + + + + + + + + + + + + Html5 Phonegap For Ios - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    HTML5

    +

    Use PhoneGap to build a html5 app to iOS

    +

    I read somewhere that phonegap CLI is easier once you downaload the ios and android SDKs.

    +

    Issues (All heresay at this point)

    +

    These issues are mostly around game dev focusing on 60fps games.

    +

    There is less criticism for business apps.

    +
      +
    • a lot of intermittent problems (sound issues, android issues)
    • +
    • issues with having a high number of elements
    • +
    • issues on phones older than iphone 6 and similar android generations
    • +
    • may not use canvas and webgl due to the type of iphone browser emulation?
        +
      • +
      +
    • +
    +

    Alternatives for game dev

    +
      +
    1. Get an apple developer account - individual is faster
        +
      1. enroll
          +
        • you have to pay $99 + tax (no tax if you have a ADUNS, TIN)
        • +
        • individual can do apple ID
        • +
        • company can use ADUNS number to get company apple id
        • +
        • other requirements listed at the link (above)
        • +
        +
      2. +
      +
    2. +
    3. Get an apple iOS signing certificate
        +
      1. lots to this, follow phonegap instructions
      2. +
      +
    4. +
    5. Build the app in phonegap
        +
      • attach the github link, it will build
      • +
      • i have no idea what the app needs to build properly... lol
      • +
      +
    6. +
    7. Download the .ipa file!
        +
      • iPhone apps are .ipa files, cool.
      • +
      +
    8. +
    9. Install Apple Configurator 2 by Apple (in the app store)
        +
      • This can be used to configure apple devices
      • +
      • Drag the .ipa file onto Apple Configurator 2
      • +
      +
    10. +
    11. Open the app by pressing the new icon on your phone
    12. +
    +

    Future - TestFlight

    +

    It would be nice to distribute beta apps to testers via TestFlight

    +

    Resource: https://medium.com/@dmathewwws/steps-to-put-your-app-on-testflight-and-then-the-ios-app-store-10a7996411b1

    +

    How to set up a HTML5 project to work on Phonegap/iOS

    +

    Ionic has some sort of descriptive (html-like) language for native-like components. Ionic also has released capacitor which is similar to cordova. The phonegap project is also based on cordova.

    +
      +
    1. Install phonegap for macos.
        +
      • also checkout phonegap-cli
      • +
      +
    2. +
    3. Open phonegap and make a new project
    4. +
    5. (build your app in this project template, using phaser.js?)
    6. +
    +

    Guidelines for what Apple will accept as a mobile app

    +

    Found here

    +
    +

    If you’re building an application to be distributed through the Apple and Google Play app stores, you need to play by their rules. Make sure you comply with the Apple App Store Review Guidelines and the Google Play Developer Program Policies. This is where the benefit of distributing your application as a Progressive Web Application comes in – using the open web means we don’t need to jump through somebody else’s hoops.

    +

    Apple especially can be a bit fickle with their application of the guidelines, but if you break any of them (sometimes even if you don’t) your application may be rejected and you will have to fix the problem and resubmit. Here are a few gotchas to watch out for that might see your application be rejected:

    +

    Your app is more like a web page than a mobile application

    +

    You don’t handle online/offline states

    +

    Your app is slow or unresponsive

    +

    Your application doesn’t make use of native features (i.e. there isn’t really a reason for it to be > distributed as a native app instead of a website)

    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/http1.1/index.html b/docs/references/http1.1/index.html new file mode 100644 index 00000000..e3e87f95 --- /dev/null +++ b/docs/references/http1.1/index.html @@ -0,0 +1,3455 @@ + + + + + + + + + + + + + + + + Http1.1 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Modern HTTP/1.1 RFCs

    +

    HTTP/1.1 RFC2616 replaced in 2014 by RFCs 7230-7237

    +

    Any connection, port, protocol can be used and is out of scope of the RFC.

    +

    The HTTP URI scheme http indicates TCP over IP with default tcp port 80.

    +

    This document highlights rfc7230, rfc7231, and rfc7232 as of January 2019.

    +

    Future

    +
      +
    • Digesting the cacheing RFC will take some time (rfc7234).
    • +
    • Range requests are used for multi-part downloads, particularly in the browser.
        +
      • MDN on Range Requests
          +
        • This has some good curl examples that help to show how range requests are done in the app backend
        • +
        +
      • +
      +
    • +
    +

    Primary RFCs Summarized Below

    +

    These are the eight HTTP/1.1 RFCs. Other RFCs are discussed inside these RFCs.

    + +

    rfc7230 Highlights

    + +

    rfc7231 Highlights

    +

    This contains request methods, method header fields, and content representation, among other things.

    +
      +
    • Representation Headers
        +
      • data type of representation data is determined by header fields Content-Type and Content-Encoding
      • +
      • two-layer encoding model: representation-data := Content-Encoding( Content-Type( bits ) )
      • +
      +
    • +
    • Content Negotation
        +
      • proactive or reactive for negotiating formats, languages, or encodings
      • +
      • could influence which representation, among those available, would be best to deliver
      • +
      +
    • +
    • +

      Request Methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE

      +
        +
      • All general purpose servers must support GET and HEAD (all others optional)
      • +
      • See IANA HTTP Methods Registry in this document's References for an up to date index of HTTP methods and their RFCs.
      • +
      • +

        Concept of safe methods

        +
          +
        • Safe methods must be implemented in a safe way, beyond scope of spec
        • +
        • Of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe.
        • +
        +
        +

        Request methods are considered "safe" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server.

        +

        This definition of safe methods does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it.

        +
        +
      • +
      +
    • +
    • +

      idempotent Request methods: PUT, DELETE, safe request methods

      +
      +

      Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response.

      +
      +
    • +
    • +

      Method Definitions - for all methods

      +
    • +
    • +

      Request Header Fields

      +
    • +
    • +

      Response Status Codes

      +
        +
      • Range is 1xx-5xx, extensible
      • +
      • See IANA Status Code Registry URL in References in this document for an up-to-date list of Status Codes and their:
          +
        • Description
        • +
        • RFC Reference URL
        • +
        +
      • +
      • Details on each status code through the link
      • +
      • +

        Cacheable by default: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501

        +
        +

        Responses with status codes that are defined as cacheable by default (e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in this specification) can be reused by a cache with heuristic expiration unless otherwise indicated by the method definition or explicit cache controls [RFC7234]; all other status codes are not cacheable by default.

        +
        +
      • +
      +
    • +
    • +

      Response Header Fields

      +
        +
      • detailed index to be aware of if parsing responses
      • +
      +
    • +
    • +

      HTTP Semantics - Security Considerations

      +
        +
      • be aware of these, read them over
      • +
      +
    • +
    +

    rfc7232 Highlights

    +
    +

    This specification defines two forms of metadata that are commonly used to observe resource state and test for preconditions: modification dates (Section 2.2) and opaque entity tags (Section 2.3). Additional metadata that reflects resource state has been defined by various extensions of HTTP, such as Web Distributed Authoring and Versioning (WebDAV, [RFC4918]), that are beyond the scope of this specification. A resource metadata value is referred to as a "validator" when it is used within a precondition.

    +
    +
      +
    • Header Fields Defined by this RFC
        +
      • ETag
      • +
      • If-Match
      • +
      • If-Modified-Since
      • +
      • If-None-Match
      • +
      • If-Unmodified-Since
      • +
      • Last-Modified
      • +
      +
    • +
    • +

      Last-Modified Header Field

      +
      +

      The "Last-Modified" header field in a response provides a timestamp indicating the date and time at which the origin server believes the selected representation was last modified, as determined at the conclusion of handling the request.

      +
      +
    • +
    • +

      ETag == entity-tag

      +
      +

      An entity-tag can be more reliable for validation than a modification date in situations where it is inconvenient to store modification dates, where the one-second resolution of HTTP date values is not sufficient, or where modification dates are not consistently maintained.

      +
      +
    • +
    +

    rfc7233 Highlights

    +

    rfc7234 Highlights

    +

    rfc7235 Highlights

    +
      +
    • oauth2/bearer Authorization is covered in rfc7235 and its spec resides in rfc6750
        +
      • Note that oauth2/bearer aka The OAuth 2.0 Authorization Framework, supercedes outh rfc6749.
      • +
      • oauth2 Authorization headers are very common for HTTP APIs, particularly modern JSON APIs
      • +
      +
    • +
    • There is a IANA Authentication Scheme Registry in the References of this document.
    • +
    • rfc7235 supercedes rfc2617.
    • +
    +

    rfc7236 Highlights

    +

    This document is a sparse reference to grandfather HTTP Authentication Methods established before the IANA HTTP Authentication Scheme Registry was established.

    +

    rfc7237 Highlights

    +

    This document is a sparse reference to grandfather HTTP Methods established in RFCs other than RFC7231 before the IANA HTTP Scheme Registry was established.

    +

    References

    + +

    Obsolete

    +
      +
    • https://tools.ietf.org/html/rfc1945
    • +
    • https://tools.ietf.org/html/rfc2068
    • +
    • https://tools.ietf.org/html/rfc2145
    • +
    • https://tools.ietf.org/html/rfc2616
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/icestick_setup/index.html b/docs/references/icestick_setup/index.html new file mode 100644 index 00000000..a0ce8a67 --- /dev/null +++ b/docs/references/icestick_setup/index.html @@ -0,0 +1,3196 @@ + + + + + + + + + + + + + + + + Icestick Setup - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Icestick Setup

    + +

    Lattice Icestick Evaluation Board - Resources & Information

    +

    My "Lattice Semiconductor" Icestick

    +
      +
    • iCE40 HX1K-TQ144 "iCEstick Evaluation Kit"
    • +
    +

    Offical Resources

    +

    Documentation

    +

    You must create an account with an email and login to download the software.

    + +

    Project IceStorm

    +
    +

    Project IceStorm aims at reverse engineering and documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. The IceStorm flow (Yosys, Arachne-pnr, and IceStorm) is a fully open source Verilog-to-Bitstream flow for iCE40 FPGAs. +The focus of the project is on the iCE40 LP/HX 1K/4K/8K chips. (Most of the work was done on HX1K-TQ144 and HX8K-CT256 parts.)

    +
    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/infopages/index.html b/docs/references/infopages/index.html new file mode 100644 index 00000000..23d310b4 --- /dev/null +++ b/docs/references/infopages/index.html @@ -0,0 +1,3283 @@ + + + + + + + + + + + + + + + + Infopages - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Infopages

    + +

    info pages

    +

    info pages are like man pages. They apparently have hypertext before web type hyperlinks, and are emacs style documentation.

    +

    Henner says info pages are good references for C.

    +

    I should probably read all of coreutils.info and info info

    +

    FUTURE

    +

    Take notes on info info and include below.

    +

    Running info

    +

    Info can be used a few different ways

    +
      +
    • info to get the directory root node for info files.
    • +
    • info printf to get info on the node "printf".
    • +
    • `info --apropos="printf" to search for "printf" on all nodes of all info pages on the info page path.
    • +
    + +
      +
    • space: page down
        +
      • Also carries you to the next node regardless of level
      • +
      +
    • +
    • backspace: page up
        +
      • Also carries you to the previous node regardless of level
      • +
      +
    • +
    • b: go to the top of the current node
    • +
    • C-l: redraw the page (control-L)
    • +
    • ?: open a quick reference (close it with C-x 0)
    • +
    • [: go to the next node in the current document
    • +
    • ]: go to the previous node in the current document
    • +
    • n: go to the next node at the same level in the current document
    • +
    • p: go to the previous node at the same level in the current document
    • +
    • u: go the parent node
    • +
    • l: go to the last node
    • +
    • follow a link: move cursor over a link, a word preceded by an asterisk, press enter
    • +
    • q: quit
    • +
    • m: go to the menu item you write if it exists
        +
      • Try searching for a menu to quickly find the menu's options?
      • +
      +
    • +
    • f Cross: follow a cross-reference starting with 'Cross'
        +
      • f?: fetch a list of cross references for the current node
      • +
      • C-g: give up when fetching cross references (instead of typing one of the options)
      • +
      • a cross reference can lead to another manual, even on a remote machine
      • +
      +
    • +
    • i Cross: automate - go to index for info manual, search node for 'Cross', and go there
    • +
    • d: go to the directory
    • +
    • t: go to the top node in a manual
    • +
    • n n: go directly to info for experts
    • +
    +

    Using vi type keybindings

    +
      +
    • $ info --vi-keys printf: use vi type keybindings
        +
      • FUTURE: map out exactly what varies between standard nav and vi mode
      • +
      +
    • +
    +

    Notes from info info

    +

    Many notes on info info are integrated elsewhere in this outline.

    +

    The ? reference is very large and worth further study.

    +

    info calls its hyperlinks Cross References.

    +

    Check out the 'info for experts' section by typing n n or type d i and type 'Advanced'.

    +

    Notes from man info

    +

    Notes on man info are integrated elsewhere in this outline.

    +

    info coreutils printf: get printf in coreutils (if there are more than one printf files)

    +

    I read that there are some flags to store and restore keystrokes pressed in an info file.

    +

    References

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/iptables/index.html b/docs/references/iptables/index.html new file mode 100644 index 00000000..e16f1d46 --- /dev/null +++ b/docs/references/iptables/index.html @@ -0,0 +1,3194 @@ + + + + + + + + + + + + + + + + Iptables - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Iptables

    + +

    Managing traffic: iptables and ip6tables

    +

    iptables is used to manage IPv4. ip6tables is used to manage IPv6.

    +

    Using iptables rules

    +

    Ubuntu recommends using ufw to easily manage iptables rules.

    +
      +
    1. View current rules: iptables -L
    2. +
    3. Rules are applied in order
        +
      • One a rule ACCEPTs or DROPs a packet, no further rules are applied
      • +
      +
    4. +
    5. Three chains: INPUT, FORWARD, OUTPUT
    6. +
    +

    Saving & Restoring iptables rules

    +
      +
    1. iptables-save dumps the current iptables to stdout.
    2. +
    3. iptables-restore flushes iptables and restores a iptables-save dump.
    4. +
    5. Procedure
        +
      1. When your iptables is correct, run as root: $ iptables-save > dump.iptables
      2. +
      3. To flush iptables and reload, run as root: $ iptables-restore < dump.iptables
      4. +
      +
    6. +
    7. There are additional options to maintain packet/byte counters, skip flushing, or save only one table by name.
    8. +
    +

    Permanently modifying iptables in a debian/ubuntu system

    +

    By default, iptables is only stored in memory. Management tools exist for iptables including ufw and the iptables service.

    +
      +
    1. iptables initial ruleset comes from /etc/network/interfaces (may be /etc/sysconfig/iptables)
    2. +
    3. +
    +

    Resources

    +
      +
    1. help.ubuntu.com IptablesHowTo
    2. +
    3. nixCraft: How Do I Save Iptables Rules and Settings?
    4. +
    5. askubuntu managing iptables with ip6tables
    6. +
    7. manpages: iptables, iptables-save, iptables-restore
    8. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/javascript_notes/index.html b/docs/references/javascript_notes/index.html new file mode 100644 index 00000000..91f97601 --- /dev/null +++ b/docs/references/javascript_notes/index.html @@ -0,0 +1,3409 @@ + + + + + + + + + + + + + + + + Javascript Notes - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Javascript Notes

    + +

    Javascript Reference Notes

    +

    Understanding: JavaScript Versions

    + +

    Understanding: Modern node.js

    +
    +

    In September 2015, Node.js v0.12 and io.js v3.3 were merged back together into Node v4.0.[36] This brought V8 ES6 features into Node.js, and a long-term support release cycle.[37] As of 2016, the io.js website recommends that developers switch back to Node.js.[38]

    +
    +

    Understanding: JavaScript Engines

    + +

    Understanding: ES6 Browser Support

    +

    Each browser just depends on its JavaScript Engine.

    +
      +
    • Edge 14, Firefox 45, and Chrome 51 support most of ES6.
    • +
    • Safari 6.1/7 seems to have almost no support.
    • +
    • Safari 7.1/8 seems to have only 20% coverage.
    • +
    • Safari 9 has 50% coverage.
    • +
    • Safari TP supports most of ES6. What is safari TP?
    • +
    +

    Javascript Refresher:

    +
      +
    • ES6 Reserved Words
    • +
    • JavaScript 'String' type and String Escapes
    • +
    • ES6 Template Literals (previously template strings)
    • +
    • MDN JavaScript Reference
    • +
    • Comparison Operators
        +
      • Use strict equals and not equals as much as possible: === and !==
      • +
      +
    • +
    • Expressions and Operators (advanced operators)
    • +
    • Functions Reference
    • +
    • Error handling: throw, try, catch, finally
    • +
    • Arrays
        +
      • myarray.push(thingy); to append thingy to the end.
      • +
      • var shifted_thingy = myarray.pop(); to remove the last (rightmost) thingy.
      • +
      • myarray.unshift(thingy); to left-append thingy to the beginning.
      • +
      • var shifted_thingy = myarray.shift(); to remove the leftmost thingy.
      • +
      • shift and pop return the removed value.
      • +
      • push and unshift return the new length of the array.
      • +
      • push and unshift can take multiple arguments.
      • +
      • Join array values to make a long string: myarray.join(', ');
      • +
      • Combine arrays: new_array = myarray.concat(another_array);
      • +
      • Find the index of a value in an array: i = myarray.indexOf('apple');. If apple doesn't exist, return -1.
      • +
      +
    • +
    • Objects
        +
      • var shifted_thingy = myarray.shift();
      • +
      • for... in loop for objects. for (var key in myobject) { console.log(key, " : ", myobject[key]); }
      • +
      • window is the global object in the browser. document and screen exist inside window but are aliased in the global scope, as far as I understand.
      • +
      • View these in the browser console by typing window or document to view the objects. Also check out window.location or window.location.host etc.
      • +
      • Also: window.document.head === document.head. THUS: Document Object Model. The document object is your .html, .php, .aspx, etc object.
      • +
      +
    • +
    • Ellipses / ... / Spread Syntax
        +
      • Ellipses are the same as a * operator in python on an argument list.
      • +
      • Ellipses supports both modes, in functions and when passing arrays to functions.
      • +
      +
    • +
    +

    JavaScript Browser API: MDN Web API Reference

    + +

    Special Note on innerText/textContent (from treehouse docs):

    +
      +
    • Mozilla didn't implement innerText but has implemented textContent.
    • +
    • innerText can be used in older versions of Internet Explorer and all versions of Chrome and Safari.
    • +
    • textContent can be used in Internet Explorer 9 onwards and all other browsers.
    • +
    • Here's some cross-browser compatible code for the edit button:
    • +
    +
      // cross compatible code
    +  if (typeof editButton.innerText === "undefined")  {
    +    editButton.textContent = "Edit";
    +  } else {
    +    editButton.innerText = "Edit";
    +  }
    +
    + +
    [The four-P's Problem Solving Method] (https://medium.com/@MatHelme/the-four-ps-of-problem-solving-6e15a39a0712#.u6oj4sst7):
    +
    - Preparation: Understand the problem. Think up a high-level solution.
    +- Plan: Plan out the solution.
    +- Perform: Perform what is required.
    +- Perfect: Perfect our solution incrementally. Nothing is ever 'perfect'.
    +
    + +
    Arrow Functions
    +
    - `var myfunc = (param1, param2, , paramN) => { // multiline-statements }`
    +
    + +
    event.preventDefault
    +
    - Cancels the default action bound to the element, e.g. onClick submit a form is cancelled.
    +- See plotly react tutorial Part II for a use case and example.
    +
    + +

    Resources

    +

    JavaScript Engine in WebKit browsers

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/kali_vm_setup/index.html b/docs/references/kali_vm_setup/index.html new file mode 100644 index 00000000..e3d5b8db --- /dev/null +++ b/docs/references/kali_vm_setup/index.html @@ -0,0 +1,3309 @@ + + + + + + + + + + + + + + + + Kali Vm Setup - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Kali Vm Setup

    + +

    Noisebridge infosec meetup 2017.08.31

    +

    Organizer: Kelly Albrink +Topic: Kiopatrix 3 (kiopatrix 1.2)

    +

    VirtualBox

    +

    I installed vmware but I used VirtualBox because I am more familiar with it.

    +

    Network: NatNetwork

    +

    In virtualbox->preferences->network I added a new NatNetwork called PartyTime.

    +

    I attached both the attacker and kiopatrix1.2 virtual machines to the PartyTime network.

    +

    Both attacker and defender must be on the same VirtualBox NatNetwork. You can change this for machine in its settings->network.

    +

    Getting internet connectivity

    +

    After setting up the host-only network, the route might be messed up in the attacker machine. You have to fix your routing:

    +
      +
    • Run:
        +
      • dhclient eth0
      • +
      +
    • +
    +

    Get ssh server up on attacker

    +

    So I can use my native terminal.

    +

    - https://lmgsecurity.com/blog/enable-start-ssh-kali-linux/

    +

    Attacker VM

    +

    The VM can be ssh'd into from the host. It's got a DHCP IP on 192.168.56.0/24.

    +

    Setting up the attacker vm for native terminal (no virtualbox window)

    +
      +
    1. Install sshd and set it up.
    2. +
    3. Make sure root can login with a password
    4. +
    5. From host: ssh root@192.168.1.<D>
        +
      • you should just have to accept the host key and give the password: toor
      • +
      +
    6. +
    +

    I set up kali linux light .ova file as my attacker machine. It seems to work just like an ovm machine (you import it as an appliance in VirtualBox.

    +
      +
    • username: root
    • +
    • password: toor
    • +
    +

    Defender VM

    +

    I set up the Kiopatrix vmdk file as my defender by making a new vm and adding the VMDK as the attached drive. I specified ubuntu but it didn't seem to take that setting. I assume I could have set anything and it would just use the VMDK and do nothing. Weird.

    +

    Kiopatrix says: set up your /etc/hosts in your attacker VM:

    +

    <kiopatrix ip> kioptrix3.com

    +

    Resources

    +
      +
    1. Kali Linux VMs
    2. +
    3. kiopatrix 3
    4. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/learning_methods/index.html b/docs/references/learning_methods/index.html new file mode 100644 index 00000000..daa47405 --- /dev/null +++ b/docs/references/learning_methods/index.html @@ -0,0 +1,3126 @@ + + + + + + + + + + + + + + + + Learning Methods - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    + +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/linksys_wrt160n_info/index.html b/docs/references/linksys_wrt160n_info/index.html new file mode 100644 index 00000000..30df8da7 --- /dev/null +++ b/docs/references/linksys_wrt160n_info/index.html @@ -0,0 +1,3244 @@ + + + + + + + + + + + + + + + + Linksys Wrt160N Info - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Linksys Wrt160N Info

    + +

    Information on the Linksys WRT 160N Router

    +

    My router

    +

    Probably a v1.1 router.

    +

    It has 16 MB ram according to DD-WRT.

    +

    The v1.0 is supposed to have 32 MB ram.

    +

    Patrick offered me this router

    +
      +
    • https://wiki.openwrt.org/toh/netgear/wndr3800
    • +
    +

    DD-WRT Info

    +
      +
    • https://www.dd-wrt.com/wiki/index.php/Telnet/SSH_and_the_Command_Line#Overview
    • +
    • 160N v3 condensed thread
    • +
    • http://www.dd-wrt.com/phpBB2/viewtopic.php?t=63444&start=15
    • +
    +

    OpenWRT Info

    +
      +
    • https://wiki.openwrt.org/doc/howto/build
    • +
    • https://wiki.openwrt.org/doc/howto/buildroot.exigence
    • +
    • +

      https://github.com/openwrt/openwrt/releases

      +
    • +
    • +

      https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm47xx

      +
    • +
    • +

      https://wireless.wiki.kernel.org/en/users/Drivers/b43/soc

      +
    • +
    • +

      https://wiki.openwrt.org/toh/hwdata/linksys/linksys_wrt160n_v3

      +
    • +
    • https://wiki.openwrt.org/toh/linksys/wrt160nl
    • +
    +

    Resources

    +
      +
    • https://wikidevi.com/wiki/Linksys_WRT160N_v1.0
    • +
    • https://wikidevi.com/wiki/Linksys_WRT160N_v1.1
    • +
    • https://wikidevi.com/wiki/Linksys_WRT160N_v3#Upgrading
    • +
    • https://www.dd-wrt.com/wiki/index.php/WRT150N
    • +
    • https://en.wikipedia.org/wiki/Linksys_routers#WRT160N
    • +
    +

    Modifications

    +

    External Antenna

    +

    https://wikidevi.com/wiki/WikiDevi:Network/Hardware_modifications/Linksys_WRT160N_v1.0_Modified_with_External_Antenna

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/manpages/index.html b/docs/references/manpages/index.html new file mode 100644 index 00000000..95febf7c --- /dev/null +++ b/docs/references/manpages/index.html @@ -0,0 +1,3241 @@ + + + + + + + + + + + + + + + + Manpages - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    + +
    +
    + + + +
    +
    + + + + + + + + + +

    Manpages

    + +

    Using manpages

    +

    Ever wonder if "man" has a man page? Ever stare deep into man's soul? Now you don't have to type "man man" to see man's deepest features.

    +

    This document is derived mostly from man man and its references.

    + +

    Use man <manpage> -wa to see all manpages that would be opened

    +

    Another option: man -aW man | xargs ls -l

    +
      +
    1. See what manpage files would be opened man -w <manpage> or man --path <manpage>
        +
      • Supposedly -W gives one per line with no description
      • +
      +
    2. +
    3. Use man <manpage> -a to sequentially view all manpages with the given title
    4. +
    +

    man checks $PATH for manpages

    +

    If an application is on $PATH, man finds it on system path.

    +
      +
    1. Specify folders: man man -M /usr/share/man:/usr/local/share/man
        +
      • Can search and open local manpages this way
      • +
      +
    2. +
    3. Or specify MANPATH in your man config.`
    4. +
    +

    Configuration

    +

    Check out $ man man.conf for config file details

    +
      +
    1. +

      man -C config_file: Specify a configuration file

      +
        +
      • Default is /private/etc/man.conf
      • +
      +
    2. +
    3. +

      See also: roff, groff, nroff, troff, ditroff

      +
    4. +
    +

    Using a custom 'Pager'

    +

    This is probably best set in either $PAGER or $MANPAGER in .bashrc

    +
      +
    1. default pager: /usr/bin/less -is
    2. +
    3. override: man man -P "/usr/bin/less -Nis
        +
      • gives you line numbers
      • +
      • overrides MANPAGER environment variable
          +
        • MANPAGER overrides PAGER environment variable
        • +
        • Consider setting this in .bashrc
        • +
        +
      • +
      +
    4. +
    +

    Supporting and Coordinating Applications

    +
      +
    1. man -k <string> - same as apropos
        +
      • likely man -k is the most convenient method, "equivalent to apropos"
      • +
      • apropos - search the whatis database for "strings".
      • +
      +
    2. +
    3. man -f <complete keyword> - same as whatis
        +
      • whatis - search the whatis database for "complete keywords".
      • +
      • only displays complete word matches
      • +
      • the whatis database is created with the command /usr/libexec/makewhatis
      • +
      +
    4. +
    5. man -K <something>
        +
      • Search for a specified string in all man pages.
      • +
      • Continues search even after you say 'y' and open a manpage
      • +
      • still pretty slow, tested with man -K vimtutor
      • +
      +
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/migrate_mysql_to_postgresql/index.html b/docs/references/migrate_mysql_to_postgresql/index.html new file mode 100644 index 00000000..16b736b4 --- /dev/null +++ b/docs/references/migrate_mysql_to_postgresql/index.html @@ -0,0 +1,3207 @@ + + + + + + + + + + + + + + + + Migrate Mysql To Postgresql - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    + +
    +
    + + + +
    +
    + + + + + + + + + +

    Migrating from MySQL to PostgreSQL

    +

    There are a number of guides for this.

    +

    MediaWiki-Vagrant Test Environment

    +

    This environment was setup.

    +

    The git/gerrit user given was anonymous during setup.sh.

    +

    MediaWiki specific migration

    +

    Note that the postgres backend is volunteer supported.

    + +

    MediaWiki Test Environment

    +

    This env probably starts with a MySQL database, so it will need reconfigured

    + +

    Configuring for PostgreSQL

    +

    todo...

    +

    Postgres Wiki

    + +

    Specific Tooling: pgloader

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/molecular_geometry/index.html b/docs/references/molecular_geometry/index.html new file mode 100644 index 00000000..8430f9dc --- /dev/null +++ b/docs/references/molecular_geometry/index.html @@ -0,0 +1,3401 @@ + + + + + + + + + + + + + + + + Molecular Geometry - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Molecular Geometry

    + +

    Molecular Geometry

    +

    A redux of molecular geometry intended for writing a software module for describing the properties.

    +

    Key Principles

    +

    Mathematical Chemistry

    + +

    Topology

    + +
    +

    In chemistry, topology provides a convenient way of describing and predicting the molecular structure within the constraints of three-dimensional (3-D) space. Given the determinants of chemical bonding and the chemical properties of the atoms, topology provides a model for explaining how the atoms ethereal wave functions must fit together. Molecular topology is a part of mathematical chemistry dealing with the algebraic description of chemical compounds so allowing a unique and easy characterization of them.

    +

    Topology is insensitive to the details of a scalar field, and can often be determined using simplified calculations. Scalar fields such as electron density, Madelung field, covalent field and the electrostatic potential can be used to model topology.[1]

    +

    Each scalar field has its own distinctive topology and each provides different information about the nature of chemical bonding and structure. The analysis of these topologies, when combined with simple electrostatic theory and a few empirical observations, leads to a quantitative model of localized chemical bonding. In the process, the analysis provides insights into the nature of chemical bonding.

    +

    Applied topology explains how large molecules reach their final shapes and how biological molecules achieve their activity.

    +

    Circuit topology is a topological property of folded linear polymers. This notion has been applied to structural analysis of biomolecules such as proteins and RNAs.

    +
    +

    Topological Index

    + +
    +

    In the fields of chemical graph theory, molecular topology, and mathematical chemistry, a topological index also known as a connectivity index is a type of a molecular descriptor that is calculated based on the molecular graph of a chemical compound.[1] Topological indices are numerical parameters of a graph which characterize its topology and are usually graph invariant. Topological indices are used for example in the development of quantitative structure-activity relationships (QSARs) in which the biological activity or other properties of molecules are correlated with their chemical structure.[2]

    +
    +

    Chemical Graph Theory

    + +
    +

    Chemical graph theory is the topology branch of mathematical chemistry which applies graph theory to mathematical modelling of chemical phenomena.[1] The pioneers of the chemical graph theory are Alexandru Balaban, Ante Graovac, Ivan Gutman, Haruo Hosoya, Milan Randić and Nenad Trinajstić[2] (also Harry Wiener and others). In 1988, it was reported that several hundred researchers worked in this area producing about 500 articles annually. A number of monographs have been written in the area, including the two-volume comprehensive text by Trinajstic, Chemical Graph Theory, that summarized the field up to mid-1980s.[3]

    +

    The adherents of the theory maintain that the properties of a chemical graph (i.e., a graph-theoretical representation of a molecule) give valuable insights into the chemical phenomena. The opponents contend that graphs play only a fringe role in chemical research.[4] One variant of the theory is the representation of materials as infinite Euclidean graphs, particularly crystals by periodic graphs.

    +
    +

    Cheminformatics

    + +
    +

    Cheminformatics (also known as chemoinformatics, chemioinformatics and chemical informatics) is the use of computer and informational techniques applied to a range of problems in the field of chemistry. These in silico techniques are used, for example, in pharmaceutical companies in the process of drug discovery. These methods can also be used in chemical and allied industries in various other forms.

    +

    Cheminformatics combines the scientific working fields of chemistry, computer science and information science for example in the areas of topology, chemical graph theory, information retrieval and data mining in the chemical space.[5][6][7][8] Cheminformatics can also be applied to data analysis for various industries like paper and pulp, dyes and such allied industries.

    +
    +

    Chemical Space

    +

    Concept: Theoretical Space vs. Concrete Space.

    + +
    +

    Chemical space is a concept in cheminformatics referring to the property space spanned by all possible molecules and chemical compounds adhering to a given set of construction principles and boundary conditions.

    +
    +

    Molecule Mining

    +

    This article lists 20 different computer programming models for mining molecules.

    + +
    +

    Molecular query methods: Warmr[12][13], AGM[14][15], PolyFARM[16], FSG[17][18], MolFea[19], MoFa/MoSS[20][21][22], Gaston[23], LAZAR[24], ParMol[25] (contains MoFa, FFSM, gSpan, and Gaston), optimized gSpan[26][27], SMIREP[28], DMax[29], SAm/AIm/RHC[30], AFGen[31], gRed[32], G-Hash[33]

    +

    Methods based on special architectures of neural networks BPZ[34][35], ChemNet[36], CCS[37][38], MolNet[39], Graph machines[40]

    +

    This page describes mining for molecules. Since molecules may be represented by molecular graphs this is strongly related to graph mining and structured data mining. The main problem is how to represent molecules while discriminating the data instances. One way to do this is chemical similarity metrics, which has a long tradition in the field of cheminformatics.

    +

    Typical approaches to calculate chemical similarities use chemical fingerprints, but this loses the underlying information about the molecule topology. Mining the molecular graphs directly avoids this problem. So does the inverse QSAR problem which is preferable for vectorial mappings.

    +
    +

    Molecular Query Language

    + +
    +

    The Molecular Query Language (MQL) was designed to allow more complex, problem-specific search methods in chemoinformatics. In contrast to the widely used SMARTS queries, MQL provides for the specification of spatial and physicochemical properties of atoms and bonds. Additionally, it can easily be extended to handle non-atom-based graphs, also known as "reduced feature" graphs. The query language is based on an extended Backus–Naur form (EBNF) using JavaCC.

    +
    +

    SMARTS: Smiles arbitrary target specification

    +

    The article has tons of detail about SMARTS which is apparently a contrasting method to MQL (Molecular Query Language).

    + +
    +

    SMiles ARbitrary Target Specification (SMARTS) is a language for specifying substructural patterns in molecules. The SMARTS line notation is expressive and allows extremely precise and transparent substructural specification and atom typing.

    +

    SMARTS is related to the SMILES line notation[1] that is used to encode molecular structures and like SMILES was originally developed by David Weininger and colleagues at Daylight Chemical Information Systems. The most comprehensive descriptions of the SMARTS language can be found in Daylight's SMARTS theory manual,[2] tutorial [3] and examples.[4] OpenEye Scientific Software has developed their own version of SMARTS which differs from the original Daylight version in how the R descriptor (see cyclicity below) is defined. The standard may require updates to accommodate for new the elements named in 2016.[5]

    +
    +

    Transferability

    +

    Both bond length and bond angle are transferable.

    +

    The opposite of transferable is conserved e.g. standard atomic weight.

    +

    From: wikipedia: Tranferability (chemistry)

    +
    +

    Transferability, in chemistry, is the assumption that a chemical property that is associated with an atom or a functional group in a molecule will have a similar (but not identical) value in a variety of different circumstances.

    +
    +

    My ideas about constraints

    +
      +
    • you could use experimental bond angle ranges predictively
    • +
    • how much synthesis/prediction can really be done
    • +
    • how often do symmetric molecules 'flip flop' or are they really static? what effect from/on brownian motion?
    • +
    +

    Resources

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/pinebook/index.html b/docs/references/pinebook/index.html new file mode 100644 index 00000000..a73de4c0 --- /dev/null +++ b/docs/references/pinebook/index.html @@ -0,0 +1,3140 @@ + + + + + + + + + + + + + + + + Pinebook - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Suspend

    +

    Two methods... you have to adjust the brightness afterwards

    +
      +
    1. Press Fn-Esc
    2. +
    3. Type $ systemctl suspend
    4. +
    +

    Adjusting brightness

    +

    stack overflow says any value 0 to 20 works, but it was at 255 after suspend

    +

    sudo su -c 'echo 255 > /sys/class/backlight/lcd0/brightness'

    +

    sudo su -c 'echo 0 > /sys/class/backlight/lcd0/brightness'

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/pivot_tables/index.html b/docs/references/pivot_tables/index.html new file mode 100644 index 00000000..1934fb90 --- /dev/null +++ b/docs/references/pivot_tables/index.html @@ -0,0 +1,3118 @@ + + + + + + + + + + + + + + + + Pivot Tables - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + + + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/python-reference/index.html b/docs/references/python-reference/index.html new file mode 100644 index 00000000..762d7d10 --- /dev/null +++ b/docs/references/python-reference/index.html @@ -0,0 +1,3201 @@ + + + + + + + + + + + + + + + + Python Reference - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Python Reference

    + +

    Python Reference Materials

    +

    Try to migrate the key component of these reference materials into this document. Links will inevitably become unavailable and the document should preserve the information. Most information here will likely be from a derivative source anyways, so some long term effort could be made to resubstantiate each section with a primary reference in the Python reference, library, PEPs, source code, etc.

    +

    Sections

    +

    Quick HTTP Server

    +
      +
    • python -m http.server
    • +
    +

    Python Operator Precedence

    +

    Original Source

    +

    Helpful and and or Idioms

    +
      +
    1. +

      Set a default value with or

      +

      python +`def thing(foo, *, opt=None): opt = opt or {}`

      +
    2. +
    3. +

      Avoid a zero division error with and when adding if statements

      +

      python +b = 0 +a = (b and 100 / b) +a

      +
    4. +
    +

    'sqlite3' Context Manager

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/python_generator_pattern/index.html b/docs/references/python_generator_pattern/index.html new file mode 100644 index 00000000..4789ebfe --- /dev/null +++ b/docs/references/python_generator_pattern/index.html @@ -0,0 +1,3316 @@ + + + + + + + + + + + + + + + + Python Generator Pattern - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Python Generator Pattern

    + +

    Python Generators from Principles

    +

    Outline notes come from here. The code has been slightly modified to sum to the first n inclusive.

    +
    Future:
    +
      +
    1. Include information about converting list comprehensions into generator comprehensions.
    2. +
    +

    A simple use case for a generator, described without any generators

    +
    def firstn(n):
    +    """
    +    The code works. 
    +    Problem: the function sends the entire list at once (using memory).
    +    Memory constrained applications need a different way.
    +    """
    +    num = 0
    +    nums = []
    +
    +    while num <= n:
    +        nums.append(num)
    +        num += 1
    +
    +    return nums
    +
    +for i in range(10):
    +    print(i, sum(firstn(i)))
    +
    + +

    Constructing a generator from scratch

    +
    class firstn(object):
    +    """
    +    The generator pattern (an iterable)
    +
    +    From: https://wiki.python.org/moin/Generators
    +
    +    Notes: This pattern is compacted into the Python `generator function` and
    +    can be accessed by using the `yield` keyword in a function.
    +    """
    +
    +    def __init__(self, n):
    +        self.n = n
    +        self.num = 0
    +        self.nums = []
    +
    +    def __iter__(self):
    +        return self
    +
    +    # Python 3 compatibility
    +    def __next__(self):
    +        return self.next()
    +
    +
    +    def next(self):
    +        if self.num <= self.n:
    +            cur = self.num
    +            self.num += 1
    +            return cur
    +        else:
    +            raise StopIteration()
    +
    +for i in range(10):
    +    print(i, sum(firstn(i)))
    +
    + +

    Using the generator pattern and yield keyword

    +
    def firstn(n):
    +    """ 
    +    The same code as a generator.
    +    From: https://wiki.python.org/moin/Generators 
    +    """
    +    num = 0
    +    while num <= n:
    +        yield num
    +        num += 1
    +
    +for i in range(10):
    +    print(i, sum(firstn(i)))
    +
    + +

    Problem: How do we get a list out of a generator?

    +
    # Python 2 `xrange` generator example, Python 3 would use `range` in the `for` loop.
    +items = []
    +for i in xrange(10):
    +    # generate the list
    +    items.append(i)
    +
    +print(items)
    +
    + +

    Generator Comprehensions

    +
    
    +
    + +

    Generators can be composed from other generators

    +

    Open question: why not use Python 2 xrange or Python 3 range in a generator composition?

    +
    def irange(start, stop=None, step=1):
    +    """ Implementation of irange from Python wiki (https://wiki.python.org/moin/RangeGenerator)
    +    """
    +    if step == 0:
    +        raise ValueError("irange() step argument must not be zero")
    +
    +    if stop is None:
    +        stop = start
    +        start = 0
    +
    +    continue_cmp = (step < 0) * 2 - i
    +
    +    while cmp(start, stop) == continue_cmp:
    +        yield start
    +        start += step
    +
    +square = (i*i for i in irange(1000000))
    +
    +total = 0
    +
    +for i in square:
    +    total += i
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/react-basic/index.html b/docs/references/react-basic/index.html new file mode 100644 index 00000000..4aaad930 --- /dev/null +++ b/docs/references/react-basic/index.html @@ -0,0 +1,3471 @@ + + + + + + + + + + + + + + + + React Basic - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    React Basic

    + +

    React Basics

    +

    This is a draft version of a react outline from basics. Send PRs to correct any misconceptions.

    +

    Resources

    +
      +
    1. react-boilerplate
    2. +
    3. React official docs
    4. +
    5. plot.ly React Tutorial
        +
      • Part 1: This section is confusingly written but the example is quite nice. See below.
      • +
      • Part 2-6: The weather app seems like a nice example, but I don't plan to use create-react-app
          +
        • Plan: Try building this part in a static file with a transpiler service?
        • +
        • Result: Parts 2, 3 are complete, using babel-standalone transpiler served from cdnjs
        • +
        +
      • +
      +
    6. +
    7. Babel is the de facto JSX transpiler.
    8. +
    9. babel-standalone - might be used as a static site transpiler?
    10. +
    11. Official React Tutorial
    12. +
    +

    Getting Started

    +
      +
    1. +

      Basics Capabilities - React Official Docs

      +
        +
      1. React can be used in:
          +
        • Frontend Stack
        • +
        • React Native (mobile)
        • +
        • Server Side (node)
        • +
        +
      2. +
      3. React Components:
          +
        • Keep state out of DOM
        • +
        • Encapsulated
        • +
        • Compose them to make complex UIs
        • +
        • Build them
        • +
        +
      4. +
      5. Declarative Views
          +
        • Design Simple Views for each state in your application
        • +
        • React efficiently updates and renders just the right components when the data changes
        • +
        +
      6. +
      +
    2. +
    +

    Plot.ly Introduction - Weather App

    +
      +
    1. +

      Who uses react? Netflix, Airbnb, etc.

      +
    2. +
    3. +

      Why React? For "building large applications with data that changes over time"

      +
        +
      • Components: composable, reusable, encapsulated
      • +
      +
    4. +
    5. +

      Lets Build: A Counter that updates state.

      +
        +
      1. react.jsbin.com - a fully featured react environment
      2. +
      3. +

        React is 2 Libraries:

        +
          +
        1. React - allows you to create ReactElements
        2. +
        3. ReactDOM - renders the ReactElements
        4. +
        5. Why the split? You could theoretically render those ReactElements anywhere
        6. +
        7. +

          Boilerplate HTML for this section

          +

          html + <!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <title>React</title> + <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.css"> + <script src="//fb.me/react-with-addons-0.14.3.js"></script> + <script src="//fb.me/react-dom-0.14.3.js"></script> + </head> + <body> + <div id="container"></div> + </body> + </html>

          +
        8. +
        +
      4. +
      5. +

        Example

        +

        javascript +ReactDOM.render( + React.createElement('h1', {className: 'heading'}, 'Hello World!'), + document.getElementById('container') +);

        +
      6. +
      7. +

        ReactDOM.render() will render a ReactElement created by React.createElement()

        +
          +
        • The DOM node we want to render (2nd argument) is called the entry point
        • +
        • ReactElements take three arguments:
            +
          1. The node we want to create (HTML Element)
          2. +
          3. A JavaScript Object of information (like 'type')
          4. +
          5. Optionally a child such as innerText or another ReactElement
              +
            • A child element like this does get null for the second argument
            • +
            +
          6. +
          +
        • +
        +
      8. +
      9. +

        Components: Creating a ReactComponent

        +
          +
        1. +

          Component is a function that receives props - short for properties

          +

          ```javascript +// What is the purpose of props here? Does it allow us to pass the child ReactElement? +var Wrapper = function(props) { + return( + React.createElement('div', { className: 'wrapper'}, props.children); + ); +} +React.createElement(Wrapper, {}, 'Hello World!');

          +

          ReactDOM.render( + React.createElement(Wrapper, null, + React.createElement('h1', { className: 'heading' }, 'Hello World!') + ), + document.getElementById('container') +); +```

          +
        2. +
        +
      10. +
      11. +

        Converting our ReactComponent to JSX

        +
          +
        1. +

          JSX is 'nothing but a wrapper on React.createElement

          +
            +
          • To use Javascript in JSX, wrap it in curly braces.
          • +
          • JSX always must be transpiled with a build tool.
          • +
          +
        2. +
        3. +

          How to transpile JSX in your build environment?

          +

          - Babel / Gulp - npm install --save-dev babel-cli babel-preset-react

          +

          javascript +var Wrapper = function(props) { + return ( + <div className="wrapper">{ props.children }</div> + ); +}; +ReactDOM.render( + <Wrapper> + <h1 className="heading">Hello World!</h1> + </Wrapper>, + document.getElementById('container') +); + 7. Classes - + 1. Event handlers like onClick, onMouseOver, etc. CANNOT go in a ReactComponent. +- These handlers must be attached to an actual DOM node. +- This 'Counter' object actually demonstrates passing Event Handlers.

          +
          ```javascript
          +class Counter extends React.Component {
          +    render() {
          +        return (
          +            <div>
          +                <p>This is a Counter component!</p>
          +                <Button text="Click me!" onClick={function() { console.log('click!') }} />
          +            </div>
          +        );
          +    }
          +}
          +// Button pulls `props` from ReactComponent JSX (React.CreateElement)
          +var Button = function(props) {
          +    return (
          +        <button onClick={ props.onClick }>{ props.text }</button>
          +    );
          +}
          +ReactDOM.render(
          +    <Counter />
          +    document.getElementById('container')
          +);
          +```
          +
          + +
        4. +
        5. +

          Handling State - State is a plain object in react, with any number of properties.

          +
            +
          • constructor is used to assign initial state
          • +
          • Lets make counter do what it is supposed to do with state.
          • +
          • +

            The { } JSX notation works with any variable, example { myPotato }

            +

            ``javascript +class Counter extends React.Component { + constructor() { + super(); + this.state = { + clicks: 0 + }; + // "thisis undefined inincrementbecause of the wayES6 Classeswork + // This explanation is terrible. Why again must we bindthis? + // Trent: According to MDN, bind will make a newbound functionand bind whatever you pass asthis` for that function. The bound function wraps the original function object. + // Trent: But why is increment set in the constructor? Is increment constructed before the constructor? Maybe... not sure. Alternative idea: Can you bind a function and then define it? + this.increment = this.increment.bind(this); + }

            +
            increment() {
            +    this.setState({
            +        clicks: this.state.clicks + 1
            +    });
            +};
            +
            +render() {
            +    return (
            +        <div>
            +            <p>This is a Counter component! The button was clicked { this.state.clicks } times.</p>
            +            <Button text="Click me!" onClick={function() { console.log('click!') }} />
            +        </div>
            +    );
            +}
            +
            + +

            } +// Button pulls props from ReactComponent JSX (React.CreateElement) +var Button = function(props) { + return ( + + ); +} +ReactDOM.render( + + document.getElementById('container') +); +```

            +
          • +
          • +

            Whenever the state changes, the <p> element is updated.

            +
          • +
          +
        6. +
        +
      12. +
      +
    6. +
    +

    Plot.ly Part II - Your First App

    +
      +
    1. New Concepts
        +
      • XMLHttpRequest asynchronous w/ event listener triggers React state change
          +
        • Receiving data with an API on the client side
        • +
        • Note that you can set a cookie for the client and use it to authenticate against your own API for that user...
        • +
        +
      • +
      • handling this by alias inside a child function with its own this
      • +
      • Using arrow functions to manage state.
      • +
      • Using preventDefault to prevent a form's default submit behavior
      • +
      • Declaring a variable currentTemp and managing its default value and state.
      • +
      +
    2. +
    +

    Plot.ly Part III - Plot.ly - Adding a Forecast Graph

    +
      +
    1. New Concepts
        +
      • ComponentDidMount, ComponentDidUpdate
      • +
      • build Plot component around plot.ly library (imported with cdnjs)
      • +
      • Interacting with a plot.ly graph's plotly_click event handler.
      • +
      • Managing state with a complex UI -- still kind of a rats nest.
      • +
      • Tie plot.ly event handler and CSS IDs into onPlotClick component (props.onPlotClick)
      • +
      +
    2. +
    +

    Plot.ly Part IV - State Management with Redux

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/rust_plan/index.html b/docs/references/rust_plan/index.html new file mode 100644 index 00000000..2ce27178 --- /dev/null +++ b/docs/references/rust_plan/index.html @@ -0,0 +1,4061 @@ + + + + + + + + + + + + + + + + Rust Plan - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    A Plan to Learn Rust

    +

    I was planning on learning C but it's tough to get up to speed and people seem to have wildly varying practices. It would be better to learn low level things in a modern context with less baggage.

    +

    The Plan

    +

    Todo

    +
      +
    • Go through the book (2nd edition) and check out the community maintained git repo.
    • +
    • Skip the git project of examples for now, I've checked them out before and should learn the rust book before checking them out again.
    • +
    • How do I get a .gitignore to be generated when I do cargo new --bin variables or similar?
    • +
    • What's the deal with shadowing? Sure it's fine, but you could end up with a bunch of values that never get garbage collected, what other tradeoffs are there? Perhaps the same type management issues that Python is attempting to solve with type annotation. Why use shadowing?
    • +
    +

    Done

    +
      +
    • Learn about rustup and how to maintain your rust toolchain. Hopefully build an analogy to python-virtualenv.
    • +
    +

    Ingesting Anthologies and Aggregators of Rust Information

    +

    More Resource Compilations to Ingest

    + +

    Already Ingested Here & Date

    + +

    Tools

    +

    Tools for Rust.

    +

    Places to get help

    +
    +

    there are a number of places you can get help. The easiest is the #rust IRC channel on irc.mozilla.org, which you can access through Mibbit. At that address you can chat with other Rustaceans (a silly nickname we call ourselves) who can help you out. Other great resources include the Users forum and Stack Overflow.

    +
    +

    Local Documentation

    +

    try: rustup doc

    +

    rustup

    +

    Switch between stable and nightly

    +

    you will need some or all of these:

    +
      +
    • rustup update
    • +
    • rustup install nightly
    • +
    • switch with: rustup default nightly or rustup default stable
    • +
    +
    +

    rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated. It makes cross-compiling simpler with binary builds of the standard library for common platforms. And it runs on all platforms Rust supports, including Windows. (emphasis mine)

    +

    rustup is a toolchain multiplexer. It installs and manages many Rust toolchains and presents them all through a single set of tools installed to ~/.cargo/bin. The rustc and cargo installed to ~/.cargo/bin are proxies that delegate to the real toolchain. rustup then provides mechanisms to easily change the active toolchain by reconfiguring the behavior of the proxies.

    +
    +

    Clippy

    +

    Linter - nightly only. Use it!

    +

    Playpen

    +

    You can put your rust in a gist and put it in Playpen and then share it with others who can see it run. Good tool for collaboration.

    +

    Crater

    +

    I don't think this is useful until I'm trying to switch between stable and nightly with tons of dependencies.

    +
      +
    • detect regressions in rust compiler against a bunch of crates
    • +
    • github project
    • +
    • Check the differences between stable and target
        +
      • only for sandboxed environments, it's very destructive... so I guess only on vms.
      • +
      +
    • +
    +

    Cargo

    +
      +
    • howto: specify cargo dependencies
        +
      • This is manual... but I prefer cargo-edit so far for add/rm/upgrade
      • +
      +
    • +
    • +

      Make sure to cargo install cargo-edit

      +
        +
      • This gives you the ability to use cargo add/rm/upgrade <crate> for example cargo add num_bigint
      • +
      +
    • +
    • +

      Rust cargo guide

      +
    • +
    +
    +

    Cargo is a tool that allows Rust projects to declare their various dependencies and ensure that you’ll always get a repeatable build. To accomplish this goal, Cargo does four things:

    +
      +
    1. Introduces two metadata files with various bits of project information.
    2. +
    3. Fetches and builds your project’s dependencies.
    4. +
    5. Invokes rustc or another build tool with the correct parameters to build your project.
    6. +
    7. Introduces conventions to make working with Rust projects easier.
    8. +
    +
    +

    GDB

    + +

    "The Book 2nd Ed." aka "The Rust Programming Language"

    +
    +

    When you finish this you will be an intermediate rust programmer.

    +

    In general, this book assumes that you’re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a topic; we typically revisit the topic in a later chapter.

    +

    You’ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you’ll learn about an aspect of Rust. In project chapters, we’ll build small programs together, applying what you’ve learned so far. Chapters 2, 12, and 20 are project chapters; the rest are concept chapters.

    +
    +

    Rust 101 Youtube (20 Jan 2017)

    + +

    Exercises

    + +

    Macros

    +

    Macros are syntactic sugar for functions that take a variable number of arguments...

    +

    Need more content, see rust book v2.

    +

    Inclusive and Exclusive Ranges

    +
      +
    • .. is an exclusive range, ..= is an inclusive range
        +
      • This is true for both matches and expressions
      • +
      • The old match-only inclusive range syntax ... is still acceptable in match-only but not recommended and does not work in expressions
      • +
      • See rust book v2 appendix 6
      • +
      +
    • +
    +

    Notes

    +
      +
    • Rust is an expression based language
        +
      • Statements are instructions that perform some action and do not return a value.
          +
        • let y = 6; is a statement, it does not return a value
        • +
        +
      • +
      • Expressions evaluate to a resulting value.
          +
        • Expressions can be parts of statements: in let y = 6, the 6 is an expression that evaluates to 6.
        • +
        • calling a function or calling a macro is an expression
        • +
        • calling the block to create new scopes, {}, is an expression
        • +
        • a function can have an expression and it will be returned by the function
        • +
        +
      • +
      • other languages don't have the same distinctions
      • +
      +
    • +
    • blocks of code inside if expressions or match expressions are sometimes called arms
    • +
    • Remember that blocks of code evaluate to the last expression in them
    • +
    +

    Chapter 2

    +
    +

    Switching from an expect call to a match expression is how you generally move from crashing on an error to handling the error. Remember that parse returns a Result type and Result is an enum that has the variants Ok or Err. We’re using a match expression here, as we did with the Ordering result of the cmp method.

    +

    --- snip ---

    +

    If parse is not able to turn the string into a number, it will return an Err value that contains more information about the error. The Err value does not match the Ok(num) pattern in the first match arm, but it does match the Err(_) pattern in the second arm. The underscore, _, is a catchall value; in this example, we’re saying we want to match all Err values, no matter what information they have inside them. So the program will execute the second arm’s code, continue, which tells the program to go to the next iteration of the loop and ask for another guess. So effectively, the program ignores all errors that parse might encounter!

    +
    +

    Chapter 3

    +
    +

    Function bodies are made up of a series of statements optionally ending in an expression. So far, we’ve only covered functions without an ending expression, but you have seen an expression as part of a statement. Because Rust is an expression-based language, this is an important distinction to understand. Other languages don’t have the same distinctions, so let’s look at what statements and expressions are and how their differences affect the bodies of functions.

    +

    We’ve actually already used statements and expressions. Statements are instructions that perform some action and do not return a value. Expressions evaluate to a resulting value. Let’s look at some examples.

    +

    So how do you know which type of integer to use? If you’re unsure, Rust’s defaults are generally good choices, and integer types default to i32: this type is generally the fastest, even on 64-bit systems. The primary situation in which you’d use isize or usize is when indexing some sort of collection.

    +

    Floating-point numbers are represented according to the IEEE-754 standard. The f32 type is a single-precision float, and f64 has double precision.

    +

    Rust’s char type represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust. Unicode Scalar Values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive. However, a “character” isn’t really a concept in Unicode, so your human intuition for what a “character” is may not match up with what a char is in Rust. We’ll discuss this topic in detail in “Strings” in Chapter 8.

    +
    +

    Chapter 4: Understanding Ownership (ownership, references, borrowing, slices)

    +

    Lifetimes are not covered in this chapter, see chapter 10. I think this most related to borrowing with async, which sounds like a hairball.

    + +
    +

    Structs and enums (discussed in Chapter 6) are the building blocks for creating new types in your program’s domain to take full advantage of Rust’s compile time type checking.

    +
    +
      +
    • Use let to instantiate struct with kv pairs (not ordered).
    • +
    • Use dot notation to get a value back from a struct.
    • +
    • Entire struct instance must be mutable, not certain fields of struct instance.
        +
      • Mutability is on the instance not the struct definition
      • +
      +
    • +
    +
    Struct Instantiaton Example
    +

    This valid expression is returned from the function and expressed in the function signature:

    +
    fn build_user(email: String, username: String) -> User {
    +    User {
    +        email: email,
    +        username: username,
    +        active: true,
    +        sign_in_count: 1,
    +    }
    +}
    +
    + +

    Resources

    +

    Resources from main rust site.

    +

    "Are we _ yet?"

    + +

    Articles

    +

    Summaries go below.

    + +

    "Rust for Python Developers" by Armin Ronacher

    +
    Mutability, Borrows, and Owners
    +
    +

    Functions that operate on immutable borrows are marked as &self and functions that need a mutable borrow are marked as &mut self. You can only loan out references if you are the owner. If you want to move the value out of the function (for instance by returning it) you cannot have any outstanding loans and you cannot loan out values after having moved ownership away from yourself.

    +

    This is a big change in how you think about programs but you will get used to it.

    +
    +
    Three rust things Armin wishes he learned earlier
    +
    RUST'S OWNERSHIP MODEL FOR JAVASCRIPT DEVELOPERS
    +
    github py2rs
    +
    rust for node developers
    +
    rust for c developers / "I used to use pointers - now what?"
    +
    rust for clojurists
    +

    Intro

    + +

    Detailed

    + +

    Rust Community

    + +

    Cool Projects

    + +

    Embedded

    +
      +
    • Need llvm, there is an avr llvm project
    • +
    • Does esp32 have access to llvm yet?
    • +
    • llvm now supports arm64 which is good for the future...
        +
      • This is fall 2018, 18 months later... does this work yet? check
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/scansf/index.html b/docs/references/scansf/index.html new file mode 100644 index 00000000..6ae61710 --- /dev/null +++ b/docs/references/scansf/index.html @@ -0,0 +1,3382 @@ + + + + + + + + + + + + + + + + Scansf - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Scansf

    + +

    Police Scanner Reference

    +

    Purpose

    +

    Gain some fluency with police radio codes and common abbreviations or slang.

    +

    Workflow

    +
      +
    1. When possible, if you hear a new code, toss it on the "Heard at least once" list.
    2. +
    3. As a call becomes common, transfer it to the relevant list.
    4. +
    +

    Scan and Scan Code Sources

    +
      +
    1. ScanSF Online Scanners
    2. +
    3. ScanSF SFPD Radio Codes
    4. +
    5. SFPD Scan Code Flash Cards
    6. +
    7. More scan codes based on Santa Barbara and others
    8. +
    9. Another site - seems to have MISS (mississipi?) codes
    10. +
    11. Scan San Diego Codes
    12. +
    +

    Common Radio Codes

    +
      +
    1. +

      Unknown

      +
        +
      • "273.5 was observed."
      • +
      • "I'll get my own" or "We'll get our own" - Maybe case number. Common for traffic stop (585).
      • +
      • "if you want to break each other one at a time apparently they are serving again up here."
      • +
      • 908 - Muni bus inspection program (quizlet)
          +
        • Could be related to indecent exposure.
        • +
        • Maybe related to suspicious person?
        • +
        +
      • +
      • 10-04E - aka 'ten four edward'
      • +
      • one four edward for a 415 on 19th avenue - 14e?
      • +
      • '13 edward' - maybe 13e - no code for that
          +
        • I think it might be the station, e.g. 'charlie 15 edward to 13 edward'
        • +
        • 10-13 is 'advise conditions at scene'
        • +
        +
      • +
      • 'david one six edward' - maybe d-16e
          +
        • note: 10-16 is pick up prisoner
        • +
        +
      • +
      • 'david twelve edward, can you put us on this run, we are 98'
      • +
      • 'henry eleven edward' we have that car that was on mission
      • +
      • '115' on the close 5 of that
      • +
      • i will give result to the '110' - 'three ida one ten'
      • +
      • 'charlie 12 edwards can you copy a plate'
      • +
      • What is a "one five edward"?
          +
        • "ida one five edward"
        • +
        +
      • +
      +
    2. +
    3. +

      Serious

      +
        +
      • Code 3 - Emergency/lights and siren "I'm going to be code 3 to this run."
      • +
      • Code 33 - Mobile Emergency - Clear this radio channel
      • +
      • 10-30 - Person/Vehicle wanted/stolen (ex: I don't know if that is 10-30 or not)
      • +
      • 152 - Drunk Driver
      • +
      • 211 - Robbery (holdup)
      • +
      • 212 - Strongarm
      • +
      • 216 - Shots fired
      • +
      • 217 - Shooting
      • +
      • 221 - Person with gun
      • +
      • 240 - Assault
      • +
      • 418 - Fight or dispute, no weapons
      • +
      • 918 - Person screaming for help
      • +
      • 602 - Breaking and entering
      • +
      • 914 - Person down (ex. I have a 914 bleeding but stable)
      • +
      +
    4. +
    5. +

      Heard at least once

      +
        +
      • 10-07I - Out of service (investigation)
      • +
      • 10-09 - Repeat last transmission
      • +
      • 10-10A - Off duty, at home
      • +
      • 10-26 - Clear (example: "still waiting on the 10-26")
      • +
      • 10-28 - vehicle registration info (ex. "The 10-28 is going to be (car plate letters) etc..."
      • +
      • 10-29 or 29- Check for warrants (ex. "can you run a 29 for me)
      • +
      • 10-49 - Proceed to ______
      • +
      • Code 1 - Do so at your convenience
      • +
      • 207 - Kidnapping
      • +
      • 311 - indecent exposure
      • +
      • 407 - Prisoner transport
      • +
      • 459 - Robbery (suspect tried to break the window then ran off)
      • +
      • 488 - petty theft
      • +
      • 496 - Stolen property receiving (example: phone)
      • +
      • 518 - Vehicle accident no injury
      • +
      • 519 - Vehicle accident with injury
      • +
      • 520 - Accident (non-vehicle) (example: like going off the road)
      • +
      • 529 - Explosion
      • +
      • 588 - Driveway violation - tow
      • +
      • 594 - Malicious Mischief (vandalism)
      • +
      • 601 - Trespassers
      • +
      • 800 - Mentally-disturbed person
      • +
      • 802 - Coroner's Case (unexpected or possibility of a law being broken)
      • +
      • 851 - Stolen vehicle
      • +
      • 852 - Auto boost/strip (heard a 852 misreported as a 459)
      • +
      • 809 - Missing Person
      • +
      • 904 - Meet with officer non-emergency (example: marin county warrant search)
      • +
      • 905 - Meet with city or public service employee (fire dept etc)
      • +
      • 910 - Check on well-being
      • +
      • 913 - Complaint Unknown
      • +
      • 914 - Person down
      • +
      +
    6. +
    7. +

      Very Frequent

      +
        +
      • 10-01 - Reception is poor
      • +
      • 10-08 - In service, ready for assignment
      • +
      • 10-22 or 22 - Disregard that last assignment (example: "22 all that")
      • +
      • 408 - Send ambulance (example: they are sending a 408)
      • +
      • 410 - Requested assistance responding (ex: 'request 408' 'confirm you have a 410')
      • +
      • 415 - Noise complaint
      • +
      • 585 - Traffic stop
      • +
      • 587 - Parking violation
      • +
      • 811 - Intoxicated person (question: is this ever used for a person in vehicle? 152?)
      • +
      • 901 - Call ______ (example: "can you 901 my cell", "give me a 901 please")
      • +
      • 909 - Citizen requests interviews
      • +
      • 915 - Homeless (call for service) - slang refers to people chronically city-camping
      • +
      • 916 - Suspicious person in vehicle
      • +
      • 917 - Suspicious person
      • +
      • 10-32 or 32 - Person/vehicle clear - '32 all around'
      • +
      • 10-98 or 98 - Available for assignment
      • +
      • 11-98 or 98 - Meet: ______ (possible example: I am 98 to you? are you still at X?)
      • +
      +
    8. +
    9. +

      Every Transmission

      +
        +
      • 10-20 or 20 - Location (example: Your 20?)
      • +
      • 10-04 - Copy/Ok
      • +
      • Code 4 - No further assistance needed
      • +
      • 10-97 or 97 or nine seven - Arrived at scene, or at the scene (ex. "Are you still 97 on mission?")
      • +
      +
    10. +
    11. +

      Slang

      +
        +
      • 302 - protesters, protest, also called a 'demo'
      • +
      • CAD - Computer Aided Dispatch (ex: "Can you put another plate in CAD for me?")
      • +
      • Operator on scansf used 470/fraud code to portray repeat suicide threat offender "do you think he is really 801 or is he 470?"
      • +
      • X - female (from scansf sfpd radio codes, typically "X yelling for help"
      • +
      • 418 - any dispute people are having?
          +
        1. mostly verbal disputes
        2. +
        3. fistfights
        4. +
        5. someone disputes someone elses behavior? (complaint about burnouts?)
        6. +
        +
      • +
      • LoJack - stolen vehicle recovery system
          +
        • This is a system that consumers install on their vehicle and which can be used by police for recovering a vehicle if stolen
        • +
        +
      • +
      • G.O.A - gone on arrival (example: person of interest was G.O.A.)
      • +
      • A.M.F. - probably very intoxicated and unable to move: 'adios mother f---er'
      • +
      • R.P. - relevant person (usually not a suspect)
      • +
      • R.O. - registered owner (usually of a stolen vehicle)
      • +
      • O.M. - oriental male
      • +
      • B.M. - black male
      • +
      • white male - white male
      • +
      • L.M. - latin male - also apparently are LMAs (ex. five LMAs in a red honda)
      • +
      • the city - slang for san francisco in registration data (address etc.)
      • +
      • merit - a crime, something concrete to report
      • +
      • shots fired - shots fired (observed directly by officer?)
      • +
      • In the aves (sunset), officers use the letter of the alphabet to describe location.
          +
        • 40th and K = 40th and Kirkham (etc.)
        • +
        +
      • +
      • Hot Sheet - A list of stolen property and crimes under investigation compiled and held by the police. The use of 'hot' means known or wanted by the police; suspect. Source: Quora
      • +
      • blue on blue - there are men with guns, we do not know if there are uniformed officers or not (undercover). Please be aware of any blue on blue (don't shoot the other cops!)
      • +
      • "broken down" - telling people camping on the street they need to move their camp elsewhere.
      • +
      • suspect information followed by 'verbal' or 'documented' - whether they said it or showed their ID.
      • +
      • lower great highway from sloat to taraval is utl - unable to locate (suspect)
          +
        • "so far the fire is utl."
        • +
        +
      • +
      +
    12. +
    13. +

      Police ID Format (Speculative)

      +
        +
      • L##L - Letter:Number:Number:Letter
      • +
      +
    14. +
    15. +

      Case Number Format Info

      +
        +
      • Case 017 000 239 at 129 am new years day
      • +
      +
    16. +
    17. +

      SFPD Preferred Phoenetic Alphabet

      +
        +
      • Adam
      • +
      • Boy
      • +
      • Charlie
      • +
      • David
      • +
      • Edward
      • +
      • Frank
      • +
      • George
      • +
      • Henry
      • +
      • Ida
      • +
      • John
      • +
      • King
      • +
      • Lincoln
      • +
      • Mary, Medic?
      • +
      • Norah
      • +
      • Ocean
      • +
      • Paul
      • +
      • Queen
      • +
      • Robert, Red
      • +
      • Sam
      • +
      • Tom, Tim
      • +
      • Union
      • +
      • Victor
      • +
      • William
      • +
      • Xray
      • +
      • Yellow
      • +
      • Zebra
      • +
      +
    18. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/security_resources/index.html b/docs/references/security_resources/index.html new file mode 100644 index 00000000..32e596f2 --- /dev/null +++ b/docs/references/security_resources/index.html @@ -0,0 +1,3121 @@ + + + + + + + + + + + + + + + + Security Resources - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Security Resources

    + +

    A Resource List for Security

    +

    Mailing Lists

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/skyrim_creation_kit/index.html b/docs/references/skyrim_creation_kit/index.html new file mode 100644 index 00000000..b42c6595 --- /dev/null +++ b/docs/references/skyrim_creation_kit/index.html @@ -0,0 +1,3345 @@ + + + + + + + + + + + + + + + + Skyrim Creation Kit - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Skyrim Creation Kit

    + +

    Skyrim Creation Kit Information

    +

    Questions

    +
      +
    1. Is it better to use the creation kit from the Bethesda Launcher or the Steam Library Toolkit?
    2. +
    +

    Creation Engine Data Format

    +
      +
    1. Master Files - .esm files; large collections of data.
    2. +
    3. Plugins - .esp files; small collections of data loaded on top of Master Files. May modify or reference data in a master file, or add new data.
    4. +
    +

    In the game, multiple Plugins may be loaded.

    +

    In the Creation Kit, only one plugin may be considered the 'active file', meaning any changes will be saved to that plugin when the user saves.

    +

    First Plugin

    +
      +
    1. Use the skyrim.esm and Update.esm files as your plugin's master files. Load them with the menu: File>Data. Ignore any warnings, they are supposed to happen...
    2. +
    3. Create your plugin in the menu: File>Save. Since you have no active plugin, you will be prompted to create a new .esp file. NOTE: There is no "save as" feature. All saves will overwrite the current plugin. Versioning must be done outside the program. Your saved plugins are found directly in your Skyrim\Data\ folder.
    4. +
    5. Load Plugins in Special Edition: In the main game menu choose Mods>Load Order and activate your local plugins.
    6. +
    +
    Demo Console Commands:
    +`TGM` - Toggle God Mode
    +`TWF` - ToggleWireframe
    +`COC RiverwoodSleepingGiantInn` - teleport to Riverwood inn
    +
    +Save games made with mods or console commands might be broken!! Make sure any saves you care about are backed up before testing and don't save over them.
    +
    + +

    Papyrus Scripting Info for Experienced Programmers

    +
      +
    • Papyrus Primer
    • +
    • [Papyrus Events & Properties (goog cache)] (https://webcache.googleusercontent.com/search?q=cache:eXVPDMVDaTsJ:https://www.creationkit.com/index.php%3Ftitle%3DBethesda_Tutorial_Papyrus_Events_and_Properties+&cd=1&hl=en&ct=clnk&gl=us)
    • +
    • Level Design Series
    • +
    +

    Papyrus Programming References

    + +

    Creation Kit Wiki References

    + +

    Creation Kit Wiki Categories

    + +

    Additional Resources

    + +

    Community Resources

    +
      +
    • https://www.reddit.com/r/skyrimmods/wiki/guides_and_resources
    • +
    • http://forums.bethsoft.com/forum/117-v-skyrim-skyrim-special-edition/
    • +
    • http://forums.bethsoft.com/forum/184-the-creation-kit/
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/slic3r/index.html b/docs/references/slic3r/index.html new file mode 100644 index 00000000..c4f29cc0 --- /dev/null +++ b/docs/references/slic3r/index.html @@ -0,0 +1,3136 @@ + + + + + + + + + + + + + + + + Slic3R - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Slic3R

    + +

    Some tips for using Slic3r

    +

    Issues rendering a preview

    +

    I had problems rendering a preview. As I brought the slider up from 0% rendered to 100% (top of model) rendered, the computer was running out of memory.

    +

    There is a guide that has helpful information

    +

    Things I did (did not help render preview without crashing):

    +
      +
    1. Set resolution to 0.01mm (default is 0mm).
    2. +
    3. Set threads to 1
        +
      • may not have mattered
      • +
      +
    4. +
    +

    Things I am doing (TBD): +3. Opened each file in meshlab, allowed it to delete duplicate vertices, and saved the file again. + - In the original pass I did simplify mesh according to this howto + - See if the simplify mesh actually matters... removing duplicate vertices may have been enough

    +

    Information:

    +
      +
    1. In top, CPU seemed to be the bottleneck. Memory was not observed to increase as the model rendering slowed (between 35% to 45%)
    2. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/spacemacs/index.html b/docs/references/spacemacs/index.html new file mode 100644 index 00000000..5dfe51a7 --- /dev/null +++ b/docs/references/spacemacs/index.html @@ -0,0 +1,3533 @@ + + + + + + + + + + + + + + + + Spacemacs - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Spacemacs Reference Document

    +

    A general reference for getting into spacemacs from vim. Mostly derivative of other guides.

    +

    Table of Contents

    +

    This does not have all sections listed, just main sections and popular reference areas.

    +
      +
    1. Reference
        +
      1. Notes
          +
        1. Spacemacs State Color Codes
        2. +
        +
      2. +
      +
    2. +
    3. Spacemacs Fixes
    4. +
    5. Greg's elisp notes
    6. +
    7. Why I switched
    8. +
    +

    Reference

    +

    Useful Sequences

    +
      +
    1. See all active minor-modes and major mode: C-h m
        +
      1. another get major-mode: C-h v major-mode
      2. +
      3. another get minor-mode: C-h v minor-mode-list
      4. +
      5. spacemacs minor-mode stuff
      6. +
      +
    2. +
    3. Reload stuff/settings: SPC f e R
    4. +
    5. Load up non-GUI mode: $ emacs -nw
    6. +
    7. Insert any character: C-q
    8. +
    9. Increment by q (q=1 by default): q SPC n -
        +
      • has some sort of minor mode where you can keep pressing stuff, try it
      • +
      +
    10. +
    11. Clear search highlighting: SPC s c
    12. +
    13. Navigate buffers: SPC b b
        +
      • Check out the Messages buffer
      • +
      • kill buffer: SPC b d
      • +
      • next or prev buffer: SPC b n or SPC b p
      • +
      +
    14. +
    15. Jump between matched tags: %
    16. +
    17. Exit insert mode (evil-escape): fd
        +
      • note that this should take you to evil normal mode from anywhere
      • +
      • this may work identically to C-g
      • +
      +
    18. +
    19. Find a file and open in a new buffer: SPC f f
    20. +
    21. "help describe": SPC h d
        +
      • "help describe function" SPC h d f
      • +
      • "help describe key" SPC h d k
      • +
      +
    22. +
    23. guide-key, a menu of stuff: SPC
    24. +
    25. Insert lorem ipsum: SPC i l l
        +
      • (lorem-ipsum) has several nice insert options SPC i l
      • +
      +
    26. +
    27. Note that the vim . repeater works on SPC-leader macros..
        +
      • try SPC i l l . . . . .
      • +
      +
    28. +
    29. Using evil-nerd-commenter
        +
      • comment or uncomment a block of lines SPC c l
      • +
      • toggle comment on each line in a block of lines SPC c ;
          +
        • can be used to simultaneously uncomment and comment neighboring lines
        • +
        +
      • +
      +
    30. +
    31. SPC m is aliased to , and accesses the current major-mode menu
    32. +
    +

    Interesting Sequences

    +
      +
    1. Incremental Search: C-s stuff
        +
      • Note: / style search is already incremental in spacemacs.
      • +
      +
    2. +
    3. Learn emacs lisp: SPC h i elisp RET
    4. +
    +

    Future

    +
      +
    1. Mess with iedit and iedit-insert states
    2. +
    3. Try out the other SPC s search options
    4. +
    5. Test out spacemacs regex SPC x which uses pcre2el package +
    6. +
    7. editing lisp code & lisp keybindings
    8. +
    9. managing projects
    10. +
    11. compiling code
    12. +
    +

    External References

    +
      +
    1. Spacemacs documentation
    2. +
    3. Migrating from Vim
        +
      1. Remapping keys
      2. +
      +
    4. +
    5. guide-key
    6. +
    7. learn elisp in 15 minutes
    8. +
    9. GNU emacs manual
    10. +
    11. Configuration "Tutorial" Orientation for contributing layers
    12. +
    13. Chaotic Migration Guide
    14. +
    +

    Subreddits:

    +
      +
    1. /r/emacs/
    2. +
    3. /r/spacemacs/
    4. +
    5. /r/evilmode/
    6. +
    7. /r/orgmode/
    8. +
    +

    Notes (From References)

    +

    Each note should have a #### header and be included in the TOC.

    +

    What is setq?

    +

    Set Quoted. (set (quote scroll-margin) 5) is equivalent to (setq scroll-margin 5).

    +

    Spacemacs State Color Codes

    +

    There are 10 states.

    +

    The state table is from the Spacemacs documentation.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    StateDefault ColorDescription
    normalorangelike the =normal mode of Vim=, used to execute and combine commands
    insertgreenlike the =insert mode of Vim=, used to actually insert text
    visualgraylike the =visual mode of Vim=, used to make text selection
    motionpurpleexclusive to =Evil=, used to navigate read only buffers
    emacsblueexclusive to =Evil=, using this state is like using a regular Emacs without Vim
    replacechocolateexclusive to =Evil=, overwrites the character under point instead of inserting a new one
    hybridblueexclusive to Spacemacs, this is like the insert state except that all the emacs key bindings are available
    evilifiedlight brownexclusive to Spacemacs, this is an =emacs state= modified to bring Vim navigation, selection and search.
    lisppinkexclusive to Spacemacs, used to navigate Lisp code and modify it (more [[#editing-lisp-code][info]])
    ieditredexclusive to Spacemacs, used to navigate between multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]])
    iedit-insertredexclusive to Spacemacs, used to replace multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]])
    +

    Spacemacs Fixes

    +

    Things I think need fixed.

    +

    Identified as needs fixed for spacemacs

    +
      +
    1. Make default colors the same as default terminal colors...
    2. +
    3. not sure how to let these pass through, spacemacs has magic colors
    4. +
    5. Consider moving my hotkeys to a helm menu or something, with a space leader instead of C- pattern. Also includes vim functions.
    6. +
    7. Rewrite vim functions for spacemacs
    8. +
    9. Consider alias for bash for spacemacs nongui as default emacs -nw
    10. +
    11. Also, consider installing the emacs-plus package from homebrew cask on mac
    12. +
    13. The emacs-plus package is apparently the recommended package by spacemacs, no idea why
    14. +
    15. Store undo history between sessions for all edited files.
    16. +
    17. manage branching undo history better? may just need training...
    18. +
    19. C-c should exit insert mode
    20. +
    21. Fix ridiculous html indentation
    22. +
    23. Disable the mouse... try the (disable-mouse) package?
    24. +
    +

    Needs Deeper Research

    +
      +
    1. tabs->spaces
    2. +
    3. looks like highlight and <|> indent by 4 spaces in html extension files... not sure how it varies by file extension
    4. +
    5. we want this to be 2 spaces by default and 4 spaces in the .py file extension
    6. +
    7. +

      indentation with the tab also does not always work, it seems to try to force a style from somewhere, tab does not always have an effect

      +
    8. +
    9. +

      html specific

      +
        +
      • tab seems to add spaces when it allows input... this should not follow complex rules, tab should just put 2 spaces in regardless
      • +
      • in html when exiting insert mode, it seems to do some postprocessing on my editing, visual mode gets weird
      • +
      • things in html mode are generally not working, especially with regards to and similar
      • +
      +
    10. +
    11. +

      Esc (1/2 second pause or less) followed by a key is a meta-key leader... need it to be dead key from now on

      +
    12. +
    13. this is related: https://github.com/syl20bnr/spacemacs/issues/2756
    14. +
    15. this seems to have abated, i think i toggled a mode
    16. +
    17. i do not know why it would have abated but i did restart my computer
    18. +
    19. +

      still reloading emacs settings should be enough, mysterious

      +
    20. +
    21. +

      How do I drill down to my packages? How do I learn about my evil mode configuration and contribute to the evil mode emacs plugin?

      +
    22. +
    23. +

      i have been reading the elisp in the .spacemacs.d layers

      +
    24. +
    25. +

      How do I manage undo branches?

      +
    26. +
    +

    Done

    +
      +
    1. line numbers on startup, line number toggle?
    2. +
    3. note taken - How do i search for tabs, e.g. \t
    4. +
    5. scroll-margin set to 5
    6. +
    7. C-l should redraw the screen - redraw does not clear search highlighting in emacs...
    8. +
    9. Clear a search with SPC s c
    10. +
    11. Turn off auto add closing quotes, braces, brackets, tildes, etc.
    12. +
    13. in init.el: put smartparens in dotspacemacs-excluded-packages
    14. +
    +

    Optional

    +
      +
    1. redraw screen with some key combo? - https://www.gnu.org/software/emacs/manual/html_node/elisp/Refresh-Screen.html
    2. +
    3. May already be in spacemacs, check around
    4. +
    +
    +

    Greg's elisp notes

    +

    I'm starting by reading An Introduction to Programming in Emacs Lisp.

    +

    To get to this, open emacs with no arguments, hit ctrl-h i .

    +

    C-h is for help. +i is for the info reader, which lets you browse manuals.

    +

    Then you're presented with a long menu.

    +

    Hit m for menu, then type Emacs Lisp Intro into the mini buffer. Then +hit enter.

    +

    That gets you to the elisp intro.

    +

    Lisp stands for LISt Processing.

    +

    A list:

    +
    '(rose
    +  violet
    +  daisy
    +  buttercup)
    +
    + +

    Awesome and beautiful quote from the book: +"The elements of this list are the names of the four different flowers, +separated from each other by whitespace and surrounded by parentheses, +like flowers in a field with a stone wall around them."

    +

    Text between double quotation marks is also an atom.

    +

    If there is no apostraphe before a preceding list then the first item +of the list is a function. If there is an apostophe then the list is just +taken as is.

    +

    Why I switched to Spacemacs

    +

    I wrote these out for someone. I prefer to see spacemacs as a vim featureset expansion.

    +
      +
    1. Vimscript sucks and vim isn't really great wrt extendability, extensions are all over the place.
    2. +
    3. I like scheme/lisp and am writing a lot of C this year, emacs seems much better suited for working in both.
    4. +
    5. Spacemacs provides most common keys in vim (but not all!).
        +
      • For example C-a in vim is SPC n + in spacemacs. It drops chording, a net positive.
      • +
      +
    6. +
    7. Vim promises leader keys but you effectively chord enough of your actions that it's a fake claim. Spacemacs uses a space leader for most things.
    8. +
    9. Vim feels stagnant, even if it isn't.
    10. +
    11. The core featureset of vim doesn't really need vim the application anymore
    12. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/spelunking_sqlite3/index.html b/docs/references/spelunking_sqlite3/index.html new file mode 100644 index 00000000..6d6f5804 --- /dev/null +++ b/docs/references/spelunking_sqlite3/index.html @@ -0,0 +1,3146 @@ + + + + + + + + + + + + + + + + Spelunking Sqlite3 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Spelunking Sqlite3

    + +

    Spelunking - Reading the SQLite3 Source

    +

    Tracking the fossil repository

    +

    Fossil is a source control tool.

    +
      +
    1. About the source
    2. +
    3. 3 ways to get the source
        +
      1. Download current snapshot
      2. +
      3. Download tarball of source+fossil history
      4. +
      5. Cloning the complete development history
      6. +
      +
    4. +
    +

    References

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/stardart_spacedomination/index.html b/docs/references/stardart_spacedomination/index.html new file mode 100644 index 00000000..486dbb9a --- /dev/null +++ b/docs/references/stardart_spacedomination/index.html @@ -0,0 +1,3880 @@ + + + + + + + + + + + + + + + + Stardart Spacedomination - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Space Domination AKA Stardart

    +

    One of my favorite games from the 90s.

    +

    Space Domination: A modern release of stardart: http://www.spacedomination.org/index.php/play/

    +

    Build Ticks

    +

    Build ticks are 10 seconds, measured with a stopwatch.

    +

    Races

    +

    It depends on if you need to maximize your acceleration into the game, your fleet power, your total build capacity, or your fleet retention. Raw score bonuses are the best long term, but fleet combat can make or break the game, heavily favoring Avarians.

    +
      +
    • Human gets a bonus stardart, can help you win
    • +
    • Master24: They can double score darts if it lands on their phenomenon or stellurae
    • +
    • +
      +

      Bonus, 1/3 chance of scoring extra dart on owned phenomenon and stellurae.

      +
      +
    • +
    • Avarian get to bring station in fleet, very OP for combat and max fleet size
    • +
    • Zorestians get -20% decay, I think it means they start at world decay? Solid but can be supplemented by worlds instead.
    • +
    • Makluvians - best merchant world build, best build speed, if you need to max that, probably best acceleration in the game.
    • +
    +

    Quick Facts

    +

    From manual: https://www.spacedomination.org/index.php/the-galaxy/

    +

    World Population

    +

    The population regulates what and how many global facilities you can build as well as how fast building goes.

    +

    Industry used to be 4x population. Is it still true?

    +

    Home Worlds

    +

    According to player "sunny" humans are sector 0, i think every game. North Northeast of OE. I am in sector 5, west of OE. Clockwise from OE increases sector

    +
    +

    Home World – Rich Planets supporting high industry

    +

    Technical: 150 population (2250 industry max) Starting with Refinery, 3 of all minerals. If the home world is from your own race you will get a declaration of planets/phenomenon from the owner. This declaration can be seen on the Settings page of the Login Screen, as it can change depending on galaxy size.

    +
    +

    World Moods

    +

    Worlds can revolt if happiness goes below some threshold, destroying industry. I assume this reduces pollution increasing happiness, so it will equilibrate naturally.

    +
      +
    • Angry: None
    • +
    • Annoyed: Merchant
    • +
    • Content: Merchant and Beacon
    • +
    • Happy: Merchant, Beacon, and Blaster
    • +
    • Ecstatic: No limitations (Stardock)
    • +
    +

    World Colors

    +
      +
    • Blue with Orange Border - Old Earth
    • +
    +
    +

    Old Earth Technical: 200 population (3000 industry max) Starting with refinery, 3 of all minerals. Old Earth will start with Star Darts based on the number of worlds in the game. If taken you will get a percentage of planets/phenomenon from the owner of the planet. You can see the current set ratio on the Settings page of the login screen.

    +
    +
      +
    • BrightOrange - Core, rich worlds around Old Earth
    • +
    +
    +

    Core Worlds Technical: 100 population (1500 industry max) Starting with Refinery, 3 of all minerals.

    +
    +
      +
    • Purple - Merchant - population/30 + 1 merchants
    • +
    • Maroon - Beacon - population/8 + 1 beacons
    • +
    • Orange - Stardock - population/40 + 1 stardocks
    • +
    • +

      Red - Blaster - population/50 + 1 blasters

      +
    • +
    • +

      Orange-red - Rich, 50% more build points

      +
    • +
    • Magenta - Poor, 50% less build points
    • +
    • White - Normal, standard
    • +
    • Orange Textured - Large - +20% Population, +1 all minerals
    • +
    • Blue-Purple - Small - -20% Population
    • +
    • +

      Grey Smooth - Toxic - -60% Population, low industry

      +
    • +
    • +

      Grey Textured - 2x faster industry build

      +
    • +
    • Blue - Sloops - 3 Pladesium
    • +
    • Khaki - Frigates - 3 Frelenium
    • +
    • Aqua - Corsairs - 3 Calastium
    • +
    • Green - Stations - 3 Stenterium
    • +
    • Red with Orange Stripe - Ranger - 3 S
    • +
    +

    World Minerals

    +

    Generation seems random with bonuses or guarantees for special worlds.

    +
      +
    • 1 == 0.5x
    • +
    • 2 == 1.0x
    • +
    • 3 == 1.5x
    • +
    +
    +

    chiisana (player) says: 1 = 1/2 speed; 2 = full speed; 3 = twice(?) as fast +Master24: 1.5x

    +
    +

    The world minerals start with the same letter as their ship except slooP and Pladesium.

    +
    +

    If you have none of a given mineral, you cannot build the corresponding ship, and if you have 3 of it you can build that ship at a quicker rate.

    +
    +

    Do the high mineral worlds correspond to the colored worlds above? What is a normal world's minerals? Rich world? Large world?

    +

    Notes: +- this Large world has 2 of all minerals and 3 of 2 minerals... which? +- this merchant world has 3 revidium/ranger and holds 4 merchants max +- merchant world with 1 revidium, 2 pladesium, 3 merchant max

    +
      +
    • Pladesium: Sloops
    • +
    • Calastium: Corsairs
    • +
    • Frelenium: Frigates
    • +
    • Stenterium: Stations
    • +
    • Revidium: Rangers
    • +
    +

    World Industry * Happiness

    +
    +

    ] Mightymo: Happiness will increase over time, And it works by percent

    +
    +
      +
    • Industry influences pollution as a % of total industry.
    • +
    • Happiness increases over time
    • +
    • Planets in home sector will be happier, home sector is the same sector as your race's homeworld.
    • +
    +

    +

    Anomalies

    +
      +
    • Blue = slower
    • +
    • Green = faster
    • +
    +

    Early Strategy

    +

    Fleet

    +

    Fleet ECM is an important factor, so emphasize rangers.

    +

    Fleets have a max size, but you won't hit it until you are harvesting worlds for fleets.

    +

    Worlds

    +

    Cannot afford much early on, so really need to pump fleet build up! Stardock is a goal. So is stellurae, but not yet attainable.

    +

    Rangers are highly preferred thanks to their attack speed and ECM.

    +

    To build stations? It is relevant once you hit max world fleet. You need the ecm for defense against other players as well. I think it's definitely worth it.

    +

    Modern Strategy

    +

    Blaster worlds seem very highly powered, assuming they are a fleet multiplier. If the fleet limit is normal, then blaster is the endgame. Blaster is also useful at all stages since it augments fleet power at peak non/attrition, increasing conquest speed. However, every non-merchant world will increase fleet harvesting times.

    +

    Riffing on the classic strategy, we want to avoid pollution, so avoid building industry. It won't matter compared to merchants and stardocks.

    +

    I think early stardocks are very useful to half the fleet attrition with a cost of only 10 global facilities.

    +

    I also think that a template build based on fleet composition is the best option, stick to the long game.

    +
    Questions
    +
      +
    • Can I have 1 of each facility available on each planet? That is fantastic.
    • +
    • What is sector? Can I use it to get to richer worlds? How is it better than distance from Old Earth?
    • +
    • The population regulates what and how many global facilities you can build as well as how fast building goes.
    • +
    • How much industry per pollution, how does pollution impact happiness?
    • +
    • Is the max fleet size still present?
    • +
    • Is industry with refinery worth it? It is a local facility.
    • +
    • Note the tradeoff is that stellurae is now a local facility. Since Stellurae doesn't interfere with Merchant/Stardock strategy it may actually be worth it instead of industry+refinery.
    • +
    +

    Classic Strategy

    +

    focus on building tons of merchants so you can harvest your worlds. Ignore everything else. Fleet build balance is based exclusively on max fleet size.

    +

    Eventually your fleet attrition will be high, then start balancing in Stardocks.

    +

    Build some beacons early as you want to reap the benefits of fast travel early. Sometimes you need to remove beacons to avoid navigation problems.

    +

    Avoid stardarts.

    +

    Global Facilities

    +
      +
    1. Classic: focus on building tons of merchants so you can harvest your worlds. Ignore everything else.
    2. +
    +

    Merchants

    +
    +

    thedudeabides: Currently getting 7.77/37 increase +- Master24: Yup, some races have added / decreased per merchant

    +
    +
      +
    • `(7.98*.95)/38 == 0.2% world build increase per Merchant, that's subtracting the human bonus and allowing for floating points...
    • +
    +

    Factory

    +

    [9:08 PM] thedudeabides: what are the technicals for factory? +[9:11 PM] Master24: 50% extra build points for the industry built

    +

    Blasters

    +

    Blasters are a fleet bonus.

    +

    Blaster cutoffs:

    +
    [7:19 PM] thedudeabides: how many blasters to get above level 0
    +7:25 PM] Master24: Blasters:
    +Level 0 100%
    +10-24 1 105%
    +25-49 2 110%
    +50-74 3 115%
    +75-99 4 120%
    +100-149 5 125%
    +150-199 6 130%
    +200-249 7 135%
    +250-299 8 140%
    +300-399 9 145%
    +400-499 10 150%
    +500-624 11 155%
    +625-749 12 160%
    +750-874 13 165%
    +875-999 14 170%
    +1000-1199 15 175%
    +1200-1399 16 180%
    +1400-1599 17 185%
    +1600-1799 18 190%
    +1800-1999 19 195%
    +2000+ 20 200%
    +
    + +

    World Setup Ideas

    +

    Early Merchant Growth

    +

    Early Fleet Building

    +

    Should I build a short string of 10 factory core with full industry for fleets? I think so! Will have to manage it when it revolts. It is +50% industry, so move in a bit before investing.

    +

    Strafing worlds

    +

    What's the easiest way to get 10k guns? Probably 10 worlds with 50% industry.

    +

    Note that with 500 industry or 500 build, the worlds can easily finish merchant in about 2 minutes, so I think it is more efficient to set industry, then set merchant and leave. Industry takes 100 industry, so it might be good to kick start. Does population count towards build points? With 100 population, 1 industry per tick, so 500/6== 83 minutes to 500 industry.

    +

    Target 90+ population worlds with a fleet about 8k-15k. The cutoff is to get 4 merchants.

    +
      +
    • 50 industry
    • +
    • all merchants
    • +
    • up to 50% industry - dont wait on it to complete...
    • +
    • build ships for 3 resource, then 2 build if no 3, 1 build if no 2 or 3...
        +
      • repeat, prioritize rangers solo early
      • +
      +
    • +
    • NO beacons early, 10 gave me like 1% increase in speed.
    • +
    • Can get them once a few hundred merchants make building them 1-2 ticks.
    • +
    +

    Note: 74 pop blaster world gave 12 blasters...absolutely huge. chiisana says try to get over 25 blasters at the beginning with 1-2 blaster worlds and some normal worlds.

    +

    Notes & Anecdata

    +
      +
    • chiisana: I personally like to do 30% industry, amenity, fly away and come back to it much later
    • +
    • Storage attrition rollover tells you your build poins basically. Once you get to the storage of required - build points, you will complete the build next pulse with 0 attrition. Not fully validated.
    • +
    • Sunny or someone says: 80k guns for a core world to be safe, 20k guns for a dart, you can roll over homeworlds with 120k guns
    • +
    • Had a beacon world at 6000w-OE with 2 merchant, 4 beacon 34 pop
    • +
    • Industry seems to be 10x population. Not sure how pollution is calculated from industry...
    • +
    • A merchant world with 20 popl, 200 industry, severe pollution, ecstatic population, 3 revidium, no local facility, and 4 merchant facilities just gave me 800 guns of rangers
    • +
    • 6180 seems to be the limit around my local... the old game used to increase the universe size if there were more players in the previous game.
    • +
    • I found a beacon world around 5000 out from Old Earth and it had only 1 beacon. I guess it is +1 to +3 or something and this one natively had 0?
    • +
    • I just found a normal planet with 2 merchants allowed. I don't know why.
        +
      • It also has 30 pop, 300 industry
      • +
      +
    • +
    • An early large world that I added full industry+factory to is Happy and producing several hundred guns after a wait. Even though pollution is severe, happiness is only very slowly going down, making it worth it for early harvest.
        +
      • TAKEAWAY: focus on large worlds early
      • +
      +
    • +
    • Worlds used to become more populated as approaching Old Earth, still true? If so focus on going that direction, as population affects global facilities on special worlds.
    • +
    • Large world with max industry and a factory is losing happiness to pollution, but at the beginning I can't build enough "storage" build for a refinery to reduce pollution so I will try an amenity facility to keep them happy... but I can't seem to get to 8000 either, I may abandon the world and try some without industry to get fleet build up.
    • +
    • Looks like merchants increase world build by a percentage, is it flat per merchant? That makes it kind of interesting rather than a flat value, since world build can be quite low without industry or factories. So this incentivizes me to build industry and factories.
    • +
    +

    Scores

    +
      +
    • "cap" - my cap - when your score accumulates to its full potential.
    • +
    • The required score to win goes down 1% every 4 hours.
    • +
    • Homeworlds are a good way to boost scores.
    • +
    • Getting a homeworld is about 2.95% of total points when capped.
    • +
    +

    Strategies

    +

    Attacking Others

    +
      +
    1. You can reduce their global garrison power by ganking mech and stardock worlds where industry == 10x population. Spiral out from OE and follow a route that is working.
    2. +
    3. It's easy to gank someone's merch if they are all in a row, but hard to collect guns if they are not. I think it might be better to have a guns place near OE then merch hunting via gates.
    4. +
    +

    Player Strategies & Alliances

    +
      +
    • chiisani and waffle are brothers and ganged up on Sunny.
    • +
    • Gawdawful seems to target merchants very heavily
    • +
    • if people keep grudges, change names
    • +
    +

    Misc Strategy Notes

    +
      +
    • What about scumming/traveling for good worlds? Then the enemies cant follow your line and you have a facilities multiplier. Especially effective if you have a low attrition fleet... like stardarts, but then combat is slow... This 80 pop merch world has 16 merchant capacity. Wild.
    • +
    • I can build merchants without command at 500 build. Base build is pop+ind. What is the minimum threshold build to build a merchant? 830/2+83 aka 83 pop planet is 498 build which is fine... how about 60 pop? 60+600/2 == 360 is that enough for merchant?
    • +
    • +

      A 90 population stardock world yields 15 stardocks. But have to get happiness up... I will try amenity on Icelu at 1859 north of OE

      +
    • +
    • +

      Move into the 90 pop worlds early and build 4 merchants per world and optimize the queue, build 50% industry.

      +
    • +
    • Once you can build refinery, about 1500 gross build (incl factories), do 100% industry. Basically the tradeoff is pop vs command build if you build full industry.
        +
      • You could build factory to build refinery with only 66% otherwise required population.... but it's too slow
      • +
      +
    • +
    • Somehow Sunny has 147 merch with 48 worlds... must be cherry picking in the inner system. Chiisana says worlds x 4 == merch worlds early on is reasonable.
    • +
    • The gates are a single large circuit predetermined. The size scales with galaxy size. The loop is apparently often about 30 gates.
    • +
    • Gates can be used to get to a home sector, get closer to OE for better worlds, or scum a certain kind of world, but those worlds are also more discoverable by playeers.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/treehouse-svg-notes-03.24.16.txt b/docs/references/treehouse-svg-notes-03.24.16.txt new file mode 100644 index 00000000..6a11af52 --- /dev/null +++ b/docs/references/treehouse-svg-notes-03.24.16.txt @@ -0,0 +1,49 @@ + + +A list of some (all?) CSS animation types: +CSS Transitions, Transforms, Keyframe Animations + +A rundown of smil vs css vs js (svg animation library): +http://www.creativebloq.com/javascript/css-js-smil-animations-21514229 + +Microsoft does not use SMIL and won't. +Chrome is planning to phase out SMIL. + +snap.js, velocity.js, gsap.js javascript animation libraries. + +two.js - another drawing library, this one can use canvas + +adobe "state of svg animation": http://blogs.adobe.com/dreamweaver/2015/06/the-state-of-svg-animation.html + +(css properties that can be animated are found on w3.org) + +SVG WordPress like a boss: +https://discourse.roots.io/t/best-practice-svg-wordpress-like-a-boss/6280 + + +We can only animate inline svg with css. + +CSS Transform Property: rotate, scale, skew, translate +The transition is then applied onto the transform for the class of the elements affected. + +Give the SVG elements CSS classes and style those. + +... element is a container for grouping SVG elements together. Add a CSS class to the element to change all components as a group. + +XML always has closing tags. + +CSS transforms around 50% 50% (center) +SVG transforms around 0 0 (top left) +Use `transform-origin: 50% 50%;` to transform around the center. + + +Firefox "transform-origin bug": +=============================== +Firefox does not honor percentage based origins for SVG +Firefox doesn't recognize keyword based origins (right bottom or center center) +cx and cy in the circle SVG element have the circle center in 'pixels' +This is kinda weird since SVG doesn't have pixels, but the length is apparently relative to the whole SVG. +transform-origin: 200px 50px; + + + diff --git a/docs/references/uart_isp_ftdi_etc_programming/index.html b/docs/references/uart_isp_ftdi_etc_programming/index.html new file mode 100644 index 00000000..b0c1dd43 --- /dev/null +++ b/docs/references/uart_isp_ftdi_etc_programming/index.html @@ -0,0 +1,3569 @@ + + + + + + + + + + + + + + + + Uart Isp Ftdi Etc Programming - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    FTDI v ISP/ICSP v UART/USART v SPI

    +

    These terms cause a bunch of confusion.

    +

    Programming

    +

    You probably program these things with avrdude. See man avrdude.

    +

    Bootloaders

    +

    It is popular to put a bootloader on your chip. This takes up some space but allows the chip to "reprogram" itself by writing to its own flash.

    +

    Some systems have a separate ISP/ICSP or UART chip on board and you can use that to reprogram the chip without a bootloader.

    +

    The purpose of both of these systems is that you can reprogram the chip while it is on-board.

    +

    Disambiguation

    +

    FTDI is one implementation of UART.

    +

    ISP/ICSP is a set of similar protocols created by different companies, AVR ISP is used with AVR chips and is common/popular.

    +

    UART is common. USART is uncommon. Many devices support UART and not USART. USART is similar to SPI.

    +

    Definitions

    +
      +
    • asynchronous - uses no clock
    • +
    • synchronous - uses a clock
    • +
    +

    Synchronous

    +
      +
    • USART
    • +
    • SPI
    • +
    • ISP/ICSP
    • +
    +

    Asynchronous

    +
      +
    • UART (therefore FTDI)
    • +
    +

    References

    +
      +
    1. Thread on USART v SPI
    2. +
    3. Wikipedia +
    4. +
    +

    SPI - Serial Peripheral Interface

    +

    Direction: Simplex

    +

    Channels: 1

    +

    I used SPI via Raspberry Pi (original) GPIO pins to program a flash chip that I soldered onto my lenovo x220 mainboard to install coreboot.

    +

    ISP/ICSP - In-system Programming or In Circuit Serial Programming.

    +

    Direction:

    +

    Channels:

    +

    This allows you to program on-chip. There are multiple incompatible ISP technologies.

    +

    AVR ISP is very popular right now.

    +

    Wikipedia states: "A ISP USB cable must typically be shorter than 180cm"

    +

    UART - Universal Asynchronous Receiver/Transmitter

    +

    Direction: Simplex, Half Duplex, Full Duplex

    +

    Channels: 1+ (typically 1 channel)

    +

    The foundation of UART is the shift register and clock.

    +

    Raspberry Pi <-> Arduino via UART

    +

    Note that in the demo, a voltage divider is used to talk from the arduino to the raspberry pi. The raspberry pi uses 3v3 on the UART tx/rx pins. The arduino pin 11 (MOSI) gets the voltage divider to the Raspberry Pi GPIO 16 RxD UART.

    + +

    What about Raspberry Pi -> ESP8266EX?

    +
      +
    • Maybe the Raspberry Pi would be a good way to program the ESP8266EX?
    • +
    +

    FTDI is UART

    +

    Direction:

    +

    A common chip in 2017 is FT232RL which goes USB to UART.

    +

    The ESP8266EX AiLight uses the [BoyaMicro 25Q32ASSIG Chip] as an ISP.

    +

    Future Technology Devices International is a company that apparently makes people sad sometimes.

    +

    To use FTDI you need a 512 byte bootloader.

    +

    A number of FTDI programmers exist but do not always seem branded as such.

    +

    Arduino: FTDI or ISP?

    +

    Arduinos used to have an FTDI chip but it was too expensive so they moved to a second chip that can do USB ISP on the primary chip.

    +

    UART (FTDI) Programmers

    +
      +
    1. +

      Sparkfun FT232RL Breakout: 3v3 5v

      +
        +
      • These are called 'USB to serial IC' boards
      • +
      • These use miniUSB, there is a different offering for microUSB
      • +
      • Offers DTR pin but not RTS; DTR resets your arduino; other models offer RTS
      • +
      +
    2. +
    3. +

      Adafruit FTDI Friend FT232RL Breakout: 3v3 and 5v

      +
        +
      • Offers RTS pin and DTR as a pad DTR guide
      • +
      • Offers 3v3 and 5v - signal is 3v3 (5v compatible), power is 5v... make sure you know what you are doing
      • +
      +
    4. +
    +

    Other brands

    +
      +
    1. The ESP8266 AiThinker Light Bulb needs an UART programmer
        +
      • recommended by the developer: AiLight Jig
      • +
      • He got some boards from china, I have asked him for a link to the seller
      • +
      +
    2. +
    +

    Hardware

    +
      +
    1. JTAG Programmers - Apparently the industry standard. Can we make these for fun?
    2. +
    3. AVR ISP Programmers
    4. +
    5. Standard issue microcomputers
        +
      • Raspberry Pi
      • +
      • Arduino Uno
      • +
      • BusPirate
      • +
      +
    6. +
    +

    The CP210x USB to UART from Silicon Labs exists

    +

    It is cheaper than the FTDI FT232RL.

    +

    Adafruit offers a low-cost breakout board of this chip and it is also in other popular USB->UART devices.

    +

    Raspberry Pi

    +

    How does this fit into the picture? I have used it with flashrom as a flash programmer for a lenovo x220 with a test clip, how is this related to everything else?

    +

    BusPirate

    +

    Apparently the BUS Pirate can do all of this, but requires configuration.

    +

    Arduino Uno

    +

    Careful! Transmits at 5V which will fry the Raspberry Pi and esp8266.

    +

    Software

    +
      +
    1. flashrom
    2. +
    3. avrdude
    4. +
    5. Arduino IDE
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/references/vim_tricks/index.html b/docs/references/vim_tricks/index.html new file mode 100644 index 00000000..4ddc769b --- /dev/null +++ b/docs/references/vim_tricks/index.html @@ -0,0 +1,3128 @@ + + + + + + + + + + + + + + + + Vim Tricks - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Vim Tricks

    + +

    A collection of vim tricks. For .vimrc, see .dotfiles

    +

    Vim tricks are added here in order of need. A trick not often referenced should be at the bottom.

    +

    Buffers

    +
      +
    • :tabnew - open a new empty buffer
    • +
    • :edit <filename> - open in a new buffer
    • +
    • :buffers, :ls - show open buffers
    • +
    • :buffer 1, :bu 1 - go to buffer 1
    • +
    • :buffer <substring> - go to buffer that matches substring (press tab to complete)
    • +
    • :bd 1 - close buffer
    • +
    • :w - write buffer
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/AirflowCreatorTalkBigData_20180117/index.html b/docs/talks/AirflowCreatorTalkBigData_20180117/index.html new file mode 100644 index 00000000..bd96cb47 --- /dev/null +++ b/docs/talks/AirflowCreatorTalkBigData_20180117/index.html @@ -0,0 +1,3644 @@ + + + + + + + + + + + + + + + + Airflowcreatortalkbigdata 20180117 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Advanced DATA ENGINEERING PATTERNS with Airflow

    +

    Speaker: Max Beauchim, Creator of Airflow and Superset

    +
      +
    • currently @ Lyft (was at Airbnb)
    • +
    • prev. Data Engineer at Facebook, inspiration!
    • +
    +

    He is wearing an Airflow shirt... how do I get an Airflow shirt?

    +

    Check out his medium account, there are a few interesting blog posts on there.

    +

    Teespring is an airflow user. He will do a batch and send a link over the next few days.

    +

    There are a bunch of frameworks for running jobs every 5 minutes or every minute.

    +

    Qbiz data consulting firm guy says during questions:

    +
      +
    • 3/4 of our customers use AutoDAG.
    • +
    +

    Answer:

    +
      +
    • With superset, it is not a scheduler. It could expose an endpoint where airflow could call an endpoint where the queries run and write a pipeline out of it.
    • +
    +

    What is Data Engineering?

    +

    In charge of building data models and data pipelines that organize information in a way that it can power the processes of the people in the company.

    +

    He wrote a blog post The Downfall of the Data Engineer discussing challenges today.

    +

    Another post Functional Data Engineering about data engineering design patterns.

    +

    Apache Airflow

    +

    A batch workflow orchestrator. Especially for large data pipelines.

    +

    The tasks really accumulate and orchestrating really become a challenge... denormalize, something, something else....

    +

    What is Airflow - 5 min

    +
      +
    • An open source platform to author, schedule, and monitor batch processes.
    • +
    • It's the glue that binds your data ecosystem together.
    • +
    • It orchestrates tasks in a complex network of job dependencies.
    • +
    • It's Python all the way down.
    • +
    • It's popular and has a thriving open source community.
    • +
    • It's expressive and dynamic, workflows are defined in code.
    • +
    +

    Airflow is configuration as code and pipelines as code.

    +

    We are going to get into why configuration as code is such a powerful concept.

    +

    DAG is a fancy acronym that also just means workflow in this context (and Directed Acyclic Graph).

    +

    Hive and Spark operators with a DAG to define topology of workflow.

    +

    Data Engineering Patterns - Foundational Pattern for all examples

    +

    Concept: building data pipelines dynamically

    +

    A classic data warehouse is pretty static. Dimension tables, fact tables. Processes roughly for every table.

    +

    Airflow is dynamic, breaks out of this pattern. Pipelines dynamically built that read configuration.

    +

    Configuration as code

    +

    Why use code instead of drag-and-drop data pipelines? Because it naturally gets source control and design patterns are easier to pull and collaborate on.

    +

    Configuration as code is more powerful than good ole configuration files.

    +
      +
    • Code is more expressive, powerful, and compact
    • +
    • Resuable components (functions, classes, object factories) come naturally in code.
    • +
    • An API has a clear specification with defaults, input validation, and useful methods.
    • +
    • Allow users to hook logic to configuration as callbacks.
    • +
    • SEE IMAGE IN PHONE FOR REST.
    • +
    • +
    +

    Conceptual Model

    +
      +
    • SEE PHOTO
    • +
    +
    Example 1: AB Testing Example
    +

    Lets change a Lyft button to be a brighter shade of pink. Airflow script to read configuration of all these experiments and metrics and weave a workflow of dependency based on the input of the user.

    +

    As the workflow executes, it waits on source data, processes metrics and experiments. Comes out with P-value, confidence interval, other computations. These become exposed in the UI.

    +

    Computation Frameworks

    +
      +
    • AutoDAG at AirBnB - lots of people run sql and they just want to schedule it to run every day. Might not want to set up a pipeline.
        +
      • Built a simple UI as an airflow plugin, AutoDAG, they paste what they run and give it a target table, finds dependencies, creates waitfor operator, hivepartitionsensors, lints code and gives advice, and schedules the workflow and alerts on failure.
      • +
      • Simplest implementation of this pattern
      • +
      • Source code for autodag is extremely simple, couple dozen lines of code.
      • +
      +
    • +
    +
    Example 2: Engagement & Growth Metrics - web companies and most industries, aka "Growth Accounting Metrics"
    +

    DAU, WAU, MAU / new, churn, resurrected, stale and active users

    +

    Wrote this for all of facebook then replicated for different verticals: photos, messaging, photo uploads - anything you can think of we wanted a flavor of this pipeline.

    +

    Count distinct metrics are ... slide is gone... (try to get the slides)

    +

    Framework reads the config file and builds a very complex framework on your behalf.

    +
    Behind the scene / at Facebook
    +

    There's a photo that has a bunch of bullets for how this configuration works (he said 'behind the Python')

    +
      +
    • Runs optimized logic
        +
      • If building the same pipeline over and over, some older ones won't be optimized. Why not improve the old whenever you improve the new?
      • +
      +
    • +
    • Cut the long tail of high cardinality dimension as specified
        +
      • Give parameters instead of tons of parameters and the framework does it automagically for you.
      • +
      • In theory crafts a dashboard on your behalf.
      • +
      +
    • +
    +

    Experimentation

    +

    Based largely on how it's done using Airflow at AirBnB.

    +

    Their complex dags are MASSIVE at airbnb. Nested in a complicated way. This looks to be a couple hundred root tasks.

    +
      +
    1. Wait for source data
    2. +
    3. Load source data into metric repository
        +
      • He could do a talk on what a metric repository might be.
      • +
      • A skinny table with a lot of rows... joins to experimental assignments and experimental stats
      • +
      +
    4. +
    5. ... (slide moved on)
    6. +
    7. ... (slide moved on)
    8. +
    9. ... (slide moved on)
    10. +
    +

    No photo for the above 5 points, get the slides?

    +
    More Complexity
    +
      +
    • Cookie->userid mapping
    • +
    • event level attributes, dimensional breakdowns
    • +
    • different types of subjects (host, guests, listing, cookie, ...)
    • +
    • different types of experimentation (web, mobile, emails, tickets...)
    • +
    • ... (slide moved on, see photo)
    • +
    • statistics beyond pvalue and confidence intervals, preventing bias, global impact, time-boxing
    • +
    +

    Need for ML Feature Repository

    +

    Where you put all your entity centric methods that are useful to train your machine learning models.

    +

    Instead of reinventing the wheel for each model you are training.

    +
      +
    • Entity-centric methods used to train ML models
    • +
    • centralized & reusable across models
    • +
    • consistent reproducible.
    • +
    • smart and efficient around time-windowing
        +
      • life-to-date metrics
      • +
      • how many times over the last 7- or 28-days that a user performed a certain action
      • +
      • use a YAML file to define what might be interesting
      • +
      +
    • +
    • hooks for training and scoring
        +
      • hooks are out of the metrics repository
      • +
      +
    • +
    +

    Stats Daemon

    +
      +
    • This is not open source. It seems like there is a lack of followthrough. He thought people would start open sourcing high leve.
    • +
    • Running a sql express engine against the partition.
    • +
    +
    How to make a Stats Daemon
    +

    Model metastore, ask metastore for schema of table, ask rule engine to build sql automatically. Use presto and pivot the result, attach to partition in a skinny table.

    +

    He verbally said the following:

    +
      +
    • A stats daemon is the idea of computing database stats on top of your data warehouse.
    • +
    • People who know about classic RDBMS, mysql, oracle, postgres, etc. These stats are stored in the schema for the query optimizer to plan.-
    • +
    • Hive etc. do not compute these stats but people can leverage these stats too, beyond the query optimizer.-
    • +
    • Every time we see something changes in hive or hive metadata we compute a bunch more metadata.-
    • +
    +

    (See photo for this slide and copy the text below... )

    +

    -

    +

    -

    +
      +
    • +
    +

    More!

    +
      +
    • Anomoly Detection
    • +
    • Production MySQL exports
    • +
    • AirOlap: Loads data into druid.io
        +
      • druid.io - in-memory column store that's really fast
      • +
      +
    • +
    • Email targeting rule engine
        +
      • Complex rules to determine who gets what email - no marketing email in 3 days and no lyft ride in 7 days... do the right thing
      • +
      +
    • +
    • Cohort analysis and user segmentation (prototype)
    • +
    • [Insert your common pattern here]
        +
      • Knowing you can write dynamic python you can find your own place to apply this pattern.
      • +
      +
    • +
    +

    Conclusion

    +

    METADATA ENGINEERING!

    +
      +
    • Airflow allows you to take data enginering to a whole new level.
    • +
    • Data engineering should find common patterns in their work and build frameworks and services
    • +
    • Building pipelines can be repetitive and inefficient. Data engineers should build machines that build pipelines.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/HettingerHolidaySF2017.pdf b/docs/talks/HettingerHolidaySF2017.pdf new file mode 100644 index 00000000..3b41c6f9 Binary files /dev/null and b/docs/talks/HettingerHolidaySF2017.pdf differ diff --git a/docs/talks/ReactSFMeetup_20160923_PublishYourComponents/index.html b/docs/talks/ReactSFMeetup_20160923_PublishYourComponents/index.html new file mode 100644 index 00000000..920ae210 --- /dev/null +++ b/docs/talks/ReactSFMeetup_20160923_PublishYourComponents/index.html @@ -0,0 +1,3184 @@ + + + + + + + + + + + + + + + + Reactsfmeetup 20160923 Publishyourcomponents - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Reactsfmeetup 20160923 Publishyourcomponents

    + +

    Publish your own react component

    +

    Speaker: Mark Muskardin

    +

    Presentation: http://hackingbeauty.com/reactbook/

    +

    About Mark: Mark is building single page blazing fast apps in react/redux for startups.

    +

    Outline

    +
      +
    1. +

      "No Install" apps are desirable

      +
        +
      • Future: People want offline 'native feeling' web apps
      • +
      +
    2. +
    3. +

      NPM is (opinion) where all dependencies should go, no longer bower

      +
    4. +
    5. +

      Companies are managing apps facing all the different facets of their business

      +
        +
      • e.g. facing both customers and sellers
      • +
      +
    6. +
    7. +

      Reusability is key... so develop in Components!

      +
        +
      • Publish your React Components on NPM.
      • +
      • npm publish "and you're done"
      • +
      +
    8. +
    9. +

      Case Study: Material-UI - Google Material React Components

      +
    10. +
    11. +

      Case II: Mark's component - material-ui-youtube-autocomplete

      +
    12. +
    13. +

      Write good documentation!

      +
        +
      • How to install
      • +
      • How to use
      • +
      • A great example using github pages
      • +
      • A solid github readme
      • +
      +
    14. +
    15. +

      Use nwb to create your component

      +
        +
      • "Tooling in a single devDependency for developing, testing, building:
          +
        1. React Apps
        2. +
        3. React Components and Libraries
        4. +
        5. npm Modules for the Web
        6. +
        +
      • +
      • nwb builds your demo page for you
      • +
      +
    16. +
    17. +

      Nota Bene: You can deliver js and css together through npm in separate files

      +
    18. +
    +

    References:

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/ReactSFMeetup_20161013_Animation/index.html b/docs/talks/ReactSFMeetup_20161013_Animation/index.html new file mode 100644 index 00000000..61ccbd81 --- /dev/null +++ b/docs/talks/ReactSFMeetup_20161013_Animation/index.html @@ -0,0 +1,3245 @@ + + + + + + + + + + + + + + + + Reactsfmeetup 20161013 Animation - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Reactsfmeetup 20161013 Animation

    + +

    React Animation

    +
      +
    • +

      Speaker:

      +
    • +
    • +

      About Speaker: Comes from game development industry

      +
    • +
    +

    Game Animation

    +
      +
    • 30 FPS doesn't really work out, you need to get to 60 fps
    • +
    • Debugging is very challenging
    • +
    +

    Webapps

    +
      +
    • Sad about the animation quality (gives a number of really terrible animation examples.
    • +
    • +

      CSS3 animations

      +
        +
      • better performance
      • +
      • fairly easy to use
      • +
      • no programmatic control - trigger and forget
      • +
      • cross browser support (it's better now)
      • +
      +
    • +
    • +

      DOM

      +
        +
      • Incredibly slow
      • +
      • Inconsistent API with bad cross-browser support
      • +
      • never meant to support complex single page apps
      • +
      +
    • +
    • +

      Single page apps

      +
        +
      • Code and state management is near impossible in a jQuery App
      • +
      • State management is bad in backbone
      • +
      +
    • +
    • +

      But - react + redux

      +
        +
      • fast rendering
      • +
      • fast state management
      • +
      +
    • +
    +

    So with react+redux can we do the cool stuff from the game dev industry?

    +
      +
    • We don't have the years of experience and code patterns...
    • +
    • (get the example from the presentation)
        +
      • sets css3 opacity from reducer based on scroll
      • +
      • getOpacityFromScroll(action.yScroll)
      • +
      • use connect to make sure react component can listen to and get state of the redux store
      • +
      • connect is a library that works between react and redux. quite popular?
      • +
      • one way data flow, set and forget
      • +
      • very performant, fluid
          +
        • did not use time control but redux has it
        • +
        • in redux you can go frame by frame with time control to debug weird animation frames
        • +
        +
      • +
      +
    • +
    • can we make the demo better?
        +
      • maybe make middleware
      • +
      • perhaps write a general animation library based on the concept
          +
        • wraps the whole thing (jquery but in react/redux)
        • +
        +
      • +
      +
    • +
    +

    Questions

    +
      +
    • Have you tried particle systems based on this demo?
        +
      • not yet but i want to
      • +
      +
    • +
    • "Sara Drasner" or something that sounds similar is an authority on doing this sort of particle based animation
    • +
    • question person: shoutout to "greenstuff" or something similar, GSAP animation library?
    • +
    • Are you using react native at instacart?
        +
      • no we are in native and we are moving code to swift, we are trying to get all our code to swift
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/ReactSFMeetup_20161013_ReactAsync/index.html b/docs/talks/ReactSFMeetup_20161013_ReactAsync/index.html new file mode 100644 index 00000000..1d848764 --- /dev/null +++ b/docs/talks/ReactSFMeetup_20161013_ReactAsync/index.html @@ -0,0 +1,3341 @@ + + + + + + + + + + + + + + + + Reactsfmeetup 20161013 Reactasync - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Reactsfmeetup 20161013 Reactasync

    + +

    React Async

    +
      +
    • Speaker:
    • +
    • Works at: HelloSign
    • +
    +

    Plans to give 60 free seats at reactuniversity.com.

    +

    High level summary

    +
      +
    • +

      React has won on the UI side.

      +
        +
      • Angular 2 similar to react
      • +
      • Ember moved to component approach
      • +
      +
    • +
    • +

      Stuff missing in redux with async

      +
        +
      • There is middleware redux-saga for async
      • +
      +
    • +
    • +

      New frontier in javascript is async

      +
    • +
    +

    JavaScript Revolution

    +
      +
    • JQuery, Backbone, Knockout, Angular, Angular2, etc.
        +
      • Now we are seeing the patterns emerge and react has 'won'
      • +
      • But react is just one part of the architecture
          +
        • Should only handle view layer
        • +
        +
      • +
      +
    • +
    • State management: redux has simplified it
        +
      • "redux is a great step forwards"
      • +
      +
    • +
    • Redux:
        +
      • Manage state through pure functions and unidirectional data flow
      • +
      • Your UI becomes a state machine
      • +
      • hen your redux store state changes your react views respond with new data
      • +
      • HelloSign has 5 single page apps. Some started implementing redux
          +
        • Result: moved business logic out of react components which is the goal
        • +
        +
      • +
      +
    • +
    +

    Redux is a workflow - NOT a "complete architecture"

    +
      +
    • We need an architecture on top of redux
        +
      • Approach to this: redux middleware
          +
        • think of middleware as a third party extension - django analogy
        • +
        +
      • +
      • uses currying to dispatch... (see slides)
      • +
      +
    • +
    • Lets look at some code examples
    • +
    • Promises: only three states
        +
      • pending
      • +
      • ??
      • +
      • rejected
      • +
      +
    • +
    • However, async we also need to be able to cancel async processes
    • +
    • Redux documentation says redux-thunk but the author says - this is wrong
        +
      • redux-thunk is a function that wraps an expression to delay its evaluation
      • +
      +
    • +
    • Wrap whatever function into another function and have the middleware (redux-thunk) run it later
        +
      • speaker has an example of redux-thunk wrapping in the presentation
      • +
      +
    • +
    • redux-thunk evaluation:
        +
      • Great for small projects
      • +
      • super simple
      • +
      • fast to run
      • +
      • easy to test in node
      • +
      • dependency injection is hard to do...
          +
        • recently redux allows passing an extra value in the thunk
        • +
        • but you always have to pass your dependencies in here which adds a lot of code
        • +
        +
      • +
      • fsa - flux standard action
          +
        • a set of standards describing what an action should look like
        • +
        +
      • +
      • redux thunk is not fsa compliant
      • +
      • doesn't scale well
          +
        • tons of action creators dispatching functions, hard to track down
        • +
        +
      • +
      • "too easy to forget error handling and pending state"
          +
        • forgetting to do the cache
        • +
        • forgetting to set a spinner when loading
        • +
        +
      • +
      • no way to cancel a thunk - ouch
      • +
      +
    • +
    • rxjs: Reactive eXtensions for JavaScript
        +
      • functional reactive programming
          +
        • need to have a masters or phd to understand functional js
        • +
        +
      • +
      • If Functional Reactive Programming (FRP) is your thing this is for you
      • +
      • netflix uses it a ton
      • +
      • does a lot of stuff redux already does, it's probably not a good thing to use WITH redux.
      • +
      • rxjs is really robust already
      • +
      +
    • +
    • redux-saga: saga pattern in redux
        +
      • author uses a ton at HelloSign
      • +
      • based on generators
          +
        • author considers generators a better strategy than async await in many cases
        • +
        +
      • +
      • "turns your async code into a pillar of your architecture"
      • +
      • instead of dispatching thunks, you create sagas to gather all your Side Effects logic in a central place
      • +
      • saga pattern: ... (look it up, there's a technical paper about it)
      • +
      +
    • +
    +

    Wrapup

    +
      +
    • Redux is great for managing state but incomplete; missing:
        +
      • `
      • +
      +
    • +
    +

    He just skipped this slide... get the slides

    +

    Questions

    +
      +
    • Generators is a learning curve with redux saga "The 80/20 of Generators" - book
        +
      • create your own babel and something or other
      • +
      • Title is probably: "The 80/20 of ES2015 Generators" by Valeri Karpov
      • +
      +
    • +
    • guy comments: angular 2 observables can be used in the same way as redux-saga
    • +
    • guy question: are observables the future?
        +
      • speaker: observables got pushed back and there has been actual pushback against it
          +
        • netflix is pushing hard for something or other with observables, maybe 'falcor'
        • +
        +
      • +
      +
    • +
    • react, redux etc support ie8 i guess, or maybe just hellosign?
    • +
    • Highlight of promise to saga is cancelable. If that is async how is it really cancelable?
        +
      • My undestanding is that it stops calling .next on it, maybe...
      • +
      • or just drops the result as a cancel maybe?
      • +
      • try... catch has finally which may be responsible for canceling
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_HolidayParty_LightningTalks_20171207/index.html b/docs/talks/SFPython_HolidayParty_LightningTalks_20171207/index.html new file mode 100644 index 00000000..fc325acf --- /dev/null +++ b/docs/talks/SFPython_HolidayParty_LightningTalks_20171207/index.html @@ -0,0 +1,3151 @@ + + + + + + + + + + + + + + + + Sfpython Holidayparty Lightningtalks 20171207 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Lightning Talks

    +

    Really messy!

    +

    1. Linting

    +

    Originally a C program by Stephen Johnson, 1978 paper.

    +

    AST, checks against rules.

    +

    Checks code more strictly than a compiler for syntax, consistency, style

    +

    Linters are lint-like programs for many languages.

    +

    Purpose

    +

    Less Debugging, Looking for logic loopholes, Carving out dead code, Reduce runtime errors, For big teams: Consistency, Interpreted languages - no compile time

    +

    Uses

    +

    Unused variables, functions, dead code, undeclared/unset vars, enforcefunction argument/parameter checking... etc.

    +

    Style Checking

    +

    Code looks fine but is inconsistent. You know the stuff, PEP8. Consistency.

    +

    Python

    +

    Flake8, PyLint, PyFlakes, Pep8

    +

    For editors

    +

    vim - flake8

    +

    emacs - ?

    +

    Custom lint rules

    +

    You can write a plugin that examines whatever can be checked by AST, etc.

    +

    Also you can write little rulesets that "lint" your code by rules

    +

    2. Zebras and Lasers - Jonas Neubert - Zymergen

    +

    Talk about barcode readers.

    +

    Writes software stuck in a box for factories.

    +

    The laser takes samples over time, so you have to do image processing.

    +

    You thing opencv = image processing. I think LIST COMPREHENSIONS.

    +

    kernel = lambda a,b,c: a if a==c!=b else b

    +

    smooth = ''.join([(a,b,c) for a,b,c in zip(data[0:], data[1:], data[2:])])

    +

    [str(round(len(list(v))/4.0)) for k,v in itertools.groupby(smooth)][1:-1]

    +

    Look up what you got on the wikipedia table of barcodes

    +

    3. 2FA, OTP, WTF - Making technical concepts accessible - Kelly

    +

    Who here works on a website where people sign up or login? Congrats you are a security engineer.

    +

    Get your family using password managers and 2FA.

    +

    Factors: Something you know, something you have, something you are

    +

    Use this stuff.

    +

    4. Gert, Scientist @ Nasa working on Kepler satellite

    +

    Kepler looks at the brightness of stars and if you look long enough the brightness dims for 6 hours once a year.

    +

    You can find a planet using 7-8 lines of python.

    +

    I am going to find a planet around a distant star live on stage.

    +

    python3, numpy, scipy.signal, matplotlib working in a jupyter notebook

    +

    Use a low pass filter to remove long term trend in star brightness data, this normalizes the year.

    +

    Next, a lomb-scargle periodogram or something is used to find periodic signal in the data.

    +

    The planet has a 0.84 day orbit, so the data was aggregated daily.

    +

    Python package: PyKE - come talk to us if you want to be a developer or intern at nasa.

    +

    5. Bot Cars! - John Ellis

    +

    Race course out in oakland once a month, the cars look like RC type cars.

    +

    Were are these events? Huge warehouse in oakland!!

    +

    Behavior cloning is what we do.

    +
      +
    • Other techniques: You can do line following, something else...
    • +
    • Data labeling is tough in machine learning. Having a data labeler system expidites that.
    • +
    +

    Toolchain

    +
      +
    • Camera input device
    • +
    • OpenCV, B4L2 capture, python3
    • +
    • Adafruit BNO005 gyroscope, dualshock4+ds4drv controller, usb2 camera v4l2capture
    • +
    • nvidia jetson tx2 + orbitty carrier
    • +
    • pololu micromaester + libusb
    • +
    • Cycloid: Traxxas Chassis
    • +
    • Donkeycar: raspberry pi, 3dprinted superstruture, ~$200
    • +
    • Derp Learning: Nvidia TX1, Traxxas Slash, ~$800
        +
      • put a gpu on your car so you have no delay and can learn on board
      • +
      +
    • +
    • Virtual test environment - use a graphics engine in unity
        +
      • you can use numpy+scikit image but it has its limits, he did it
      • +
      +
    • +
    +

    6. Quilt - Docker, but for Data - Anish

    +

    akarve/pydatabook - an example

    +

    Why?

    +
      +
    • Code has reusable building blocks, github, PyPI, DockerHub
    • +
    • Data is missing reusable building blocks - stuff like s3, github, everywhere online
    • +
    • Data packages: metadata and serialized
    • +
    +

    Package Lifecycle - 3-4 primitives that matter

    +
    - build, , install, import
    +- `quilt build` - shred them into a dataframe, hash, stick into a hash tree, serialize columnar data, indexing
    +
    + +

    Why track in a hash tree? - Need to be able to send all the deltas

    +

    If you just change a readme, just want to download that on a version update

    +

    Catalog is like PyPI but for data

    +

    his book on quiltdata.com

    +

    from quilt.data.akarve import pydata_book as pb - pb.getdata.train() (or something) and you get a dataframe out.

    +

    Working on react+Tensorflow, R, Spark, going to get stuff into Jupyter.

    +

    7. Datasette - Simon @ Eventbrite - journalist stuff @ guardian

    +

    datasette

    +

    Make an instant, read-only JSON API for any SQLite database. It also provides tools for packaging the database as a docker container and deploying to hosting providers.

    +

    Arbitrary SQL is pretty fine, you can't really modify the data, read only. Chrome history example.

    +

    San Francisco open data portal, data.sfgov.org - download csv of trees from the city

    +

    Wrote [csvs2sqlite] which just turns the CSV to a sqlite3 database. Can refactor csv to something a bit more relational. Extract some columns... He list about 12 columns he wants into separate tables. Also he uses -x to make the columns searchable in sqlite, indexing or whatever?

    +

    $ datasette tree.db

    +

    $ datasette publish now sf-trees.db - gives you a URL, hyperlinks.

    +

    Just like that you have a browseable, searchable json API

    +

    he built https://sf-tree-search.now.sh because he thought "why not?" - search sf by tree

    +

    8. How to build community - Simeon

    +

    Pacman rule - Eric Holscher - don't stand in a circle, people can't get in. Everyone should meet more people.

    +

    Bring a friend, bring a female coworker.

    +

    BayPiggies, SF Django Meetup, Pyninsula, PyLadies, East Bay Python, North Bay Python

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/index.html b/docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/index.html new file mode 100644 index 00000000..c0dc57d1 --- /dev/null +++ b/docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/index.html @@ -0,0 +1,3360 @@ + + + + + + + + + + + + + + + + Sfpython Holidayparty Raymondhettinger 20171207 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Raymond Hettinger Holiday Party Talk 2017

    +

    Raymond says: I will tweet out a link to this presentation later. It is in sphinx. +Notes are in this folder, /outlines/talks, as HettingerHolidaySF2017.pdf.

    +
      +
    • Mission: Train thousands of Python Developers
    • +
    • Mutable Minds, Inc.
    • +
    • raymond.hettinger@gmail.com
    • +
    • Training Videos: Free to users of Safari Online: "Modern Python: Big Ideas, Little Code"
        +
      • Raymond says about a $100 on-ramp to using Safari Online
      • +
      +
    • +
    • @raymondh on twitter
    • +
    +

    I use sphinx to prepare my talks / slide decks. Never intend to go back to Powerpoint.

    +

    I am a manufacturer of Python Programmers. I take someone good at something and make them good at something plus Python programming.

    +

    Questions from the end of the talk

    +

    I didn't really record them all.

    +
      +
    • (Mentions offhand he has an OCaml background)
    • +
    • Q: Why can't I use a value use_slots = True instead of manually adding slots
        +
      • Raymond: I expect some discussion this week on python-dev about that. Solution is probably that the class decorator will return a new class with the slots in it. It's a little late to turn it on and off with true/false. The present design doesn't preclude that feature. We need to avoid making it impossible. Also because no one who reviewed the pep and no one thought of it, or eric wanted to do it that way.
      • +
      +
    • +
    +

    Python 3.7

    +
      +
    • How to hold these 3 numbers: 33, 1.00, 0.5 (HSL Colors)
    • +
    +

    Class Generators: dataclasses and namedtuples

    +

    Problems to be Solved

    +

    I want to pass around a bunch of instances of colors: HSL system.

    +

    Dark Orange: 33 degrees on the color wheel at 100% saturation and 50% lightness.

    +
    from bunch import Bunch
    +from types import SimpleNamespace
    +? import record # for recordtype
    +? import dataclass
    +
    +# tuple
    +dark_orange = (33, 1.00, 0.5)
    +print(dark_orange)
    +
    +# dict
    +dark_orange = {'hue': 33, 'saturation': 1.0, 'lightness': 0.5}
    +print(dark_orange)
    +
    +# simple class
    +class Color:
    +    ''' there are 6 basic dunder methods, __init__, __hash__, something else, __lt__ etc, 
    +    '''
    +    def __init__(self, hue, saturation, lightness=0.5):
    +        self.hue = hue
    +        self.saturation = saturation
    +        self.lightness = lightness
    +
    +dark_orange = Color(33, 1.00, 0.5)
    +print(dark_orange)
    +
    +
    +# bunch recipe ########### Bunch can be written in three lines (not in std library)
    +dark_orange = Bunch(hue=33, saturation=1.00, lightness=0.5)
    +print(dark_orange)
    +
    +# simple namespace ######### Bunch, but in the standard library, written in c
    +# good, because it's in the standard library... ha but it's just bunch
    +# this way is pretty good, repr but can't compare it, can't sort, can't hash...
    +# takes a bunch of space... has an object with a reference to a dictionary, 300 bytes
    +dark_orange = SimpleNamespace(hue=33, saturation=1.00, lightness=0.5)
    +
    +
    +# named tuples ######### i stole it, i'm an aggregator... i found it reinvented dozens of times
    +# i brought them all together in a massive chart, took the best ideas from each, aggregated
    +# published the recipe, got lots of people to use it, took it to python dev, we put it in
    +# internally same name tuple as before, but now written in a class format... before what?
    +class Color(NamedTuple):
    +    ''' 
    +    benefits from before
    +    one from each line
    +    see the datatype, use default
    +    '''
    +    hue: int
    +    saturation: floor
    +    lightness: float = 0.5
    +
    +# calling the NamedTuple... 72 bytes, 4 times smaller than SimpleNamespace
    +# make one namedtuple then you can make another one based on it, just change an attribute and clone
    +# named tuples are hashable so they are useable as dictionary keys
    +# immutable! - whaa - you just have to use the replace() method to make another... too hard
    +dark_orange = Color(hue=33, saturation=1.00)
    +print(dark_orange)
    +
    +''' Python 2.7 so it's commented
    +# record by george sakkis ####
    +# python 2.7 recipe and not changed for Python3
    +# we had mutable nametuples for a very long time, 8 years, no typing, needs typing
    +# but it didn't have a cool name#127.0.0.1 dev.hackersinresidence.c so no one knew!
    +Color = record.recordtype('Color', ['hue', 'saturation', 'lightness'])
    +# mutability is fun!
    +# 64 bytes, smaller than a tuple... tuples store the length, instances don't unless you add the field
    +# so this can't tell you its length... but it's smaller
    +dark_orange = Color(hue=, saturation=1.00, lightness=0.5)
    +'''
    +
    +# dataclass ##################
    +# half the people see it as a data container, half the people see it as a class
    +# rorscach test
    +# you can start using it in Python3.6 with raymonds code, or wait for python3.7
    +# in python2, you can import recordtype as dataclass - ha!
    +# biggest way of all at 296 bytes, bigger than a dict
    +@dataclass
    +class Color:
    +    ''' it writes classes for you and holds data
    +    '''
    +    hue: int
    +    saturation: float
    +    lightness: float = 0.5
    +
    +dark_orange = Color(hue=33, saturation=1.00)
    +print(dark_orange)
    +
    +# dataclass with slots but no defaults ########
    +@dataclass
    +class Color:
    +    ''' 64 bytes but you can't have any default values, or use george's recipe
    +    '''
    +    slots = ['hue', 'saturation', 'lightness']
    +    hue: int
    +    saturation: float
    +    lightness: float
    +
    +dark_orange = Color(hue=33, saturation=1.00, lightness=0.5)
    +print(dark_orange)
    +
    +# you learned the history of how to store 3 numbers
    +# this gives some output
    +
    + +

    Details about each data container option

    +

    Have to see the notes for this... it's really fast

    +

    Bunch and SimpleNamespace

    +

    Recipe

    +
    class Bunch(object):
    +    def __init__(self, **kwds):
    +        self.__dict__.update(kwds)
    +
    + +

    Optimization

    +
    class Bunch(object):
    +    ''' much faster, replace the dict with kwds
    +    dict is guaranteed to be ordered
    +    ''' 
    +    def __init__(self, **kwds):
    +        self.__dict__ = kwds
    +
    + +

    C version built into Python

    +
    from types import SimpleNamespace
    +
    + +

    Named Tuples - same size as regular tuple

    +
      +
    • Replaces tons of stuff with NamedTuples when doing code review
    • +
    • raymond loves fstrings - brought by eric smith
    • +
    • who did dataclass - eric smith
    • +
    • are you going to remember his name?
    • +
    +

    You can let the code generator build it then modify it yourself... how? what? +I think it's written in python so you need to paste it in or something... no idea

    +

    Data Classes - PEP 557 has landed

    +
      +
    • Validates that NamedTuple was doing the right thing but we need mutable. And a cool name.
    • +
    • Immutable if you want (possible to freeze the data)
    • +
    • PEP says - mutable namedtuples with defaults
        +
      • main design goal is to support static type checkers
      • +
      • highly opinionated about typing, no way to use it without typing
      • +
      • static typing was optional, not here... you can put a type of None or any and it will be ignored.
      • +
      • have to explicitly opt out of typing with None or any
      • +
      • raymond is working on a workaround
      • +
      +
    • +
    • boilerplate for class, attribute based dataholder
    • +
    • is it a code generator? is it a data holder? two different ways of looking at it
    • +
    • generates code for you, generates class docstring, init, repr, eq with strong typechecking, rich comparisons, hashing, read-only enforced by setattr, delattr
    • +
    +

    from dataclasses import make_dataclass +- this thing is huge unless there are slots... but with slots you lose defaults +- the language has a built in constraint against slots and defaults at the same time

    +

    Do you always know if something is going to be integer float? No. 12.5 timezones off in india!

    +

    When you import types it actually executes code... so there is debate about whether they will stringify types in make_dataclass

    +
      +
    • +

      if you read python-dev you will get all of the drama

      +
    • +
    • +

      emulate a namedtuple (see slides) with from operator import itemgetter and dataclasses

      +
    • +
    +

    Summary

    +

    I have been studying dataclasses since the first draft of PEP 557.

    +

    I really like the new dataclasses!

    +

    If you need mutable named tuples today, try George Sakkis's Record class or use the attached dataclass code that runs fine on Python3.6 but not prior. (code in raymond's slides)

    +

    See the 4 tuple code generator table: Namedtuple, Record, Dataclasses, Dataclasses w/ slots

    +

    Gains and losses

    +

    (see the slides)

    +

    Some Nice Improvements

    +

    (see the slides)

    +

    Some things that aren't as nice

    +
      +
    • higher complexity and learning curve, 700 ish lines of code, couple hundred lines of tests, lots of specs.
    • +
    • dataclasses is its own miniature ORM for python stuff, declare, fields() function, hashable, etc.
    • +
    +

    (see the slides)

    +

    Inside the sphinx slides this talk is from, you can cut and paste raymond's code and use it now.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_Import_Madness_20170614/index.html b/docs/talks/SFPython_Import_Madness_20170614/index.html new file mode 100644 index 00000000..522330e0 --- /dev/null +++ b/docs/talks/SFPython_Import_Madness_20170614/index.html @@ -0,0 +1,3170 @@ + + + + + + + + + + + + + + + + Sfpython Import Madness 20170614 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Sfpython Import Madness 20170614

    + +

    import madness

    +

    This talk only works in Python 3!!

    +

    This title import madness is executable. If we import it we get an ImportError without that module existing.

    +

    What is a module? A python file.

    +

    What else is a module? An object loaded that represents a python module (as in: Python file)

    +

    Python has a standard module type. __import__ will initialize a module by executing all the source of the module file in main.

    +

    Can you implement a mergesort algorithm using the Python import keyword?

    +

    Merge

    +

    Yes! Should you? Obviously, no.

    +
    +

    Speaker discusses mergesort.

    +

    When you import a module in Python, Python executes the entire source of that module.

    +
    +

    madness is a wrapper module which will import mergesort. It will then create new modules for the left side and right side and continue.

    +

    Solve most import errors with sys.path.

    +

    DANGER!! WARNING!!

    +

    import is dangerous!! Python imports the containing module to find any function you import from that module. Including uploading all your ssh keys to pastebin, encrypting your drive, and deleting the line of code that did that.

    +

    Some of the source

    +

    bit.ly/2s8YmzL

    +
    current_module = sys.modules(__name__)
    +module_source = inspect.getsource(current_module)
    +
    + +
    # buckle up!
    +from merge_sort import sorted_sublist as sorted_list
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_Unit_Testing_With_Mock_20170614/index.html b/docs/talks/SFPython_Unit_Testing_With_Mock_20170614/index.html new file mode 100644 index 00000000..19a5c891 --- /dev/null +++ b/docs/talks/SFPython_Unit_Testing_With_Mock_20170614/index.html @@ -0,0 +1,3352 @@ + + + + + + + + + + + + + + + + Sfpython Unit Testing With Mock 20170614 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Sfpython Unit Testing With Mock 20170614

    + +

    Unit Testing with Mock

    +

    This talk is about unit testing.

    +

    Speaker: Brian Weber, SRE at Twitter

    +

    Lets execute tests in your code safely

    +

    Tests execute your code.

    +

    For example, a command line function that deletes hard drives...

    +

    How do we do it? mock

    +

    What is a mock?

    +

    unitteset.mock is a library for Testing in Python. It allows you to replace parts of your system under test with mock objects... (is this text from the unittest documentation?)

    +

    Why use mock?

    +
      +
    1. Stop the state-changing parts so you can actually run tests.
    2. +
    3. Write better code
    4. +
    5. _____ (missed it!)
    6. +
    +

    Patch decorator

    +

    Mocks are plastic

    +

    Everything the mock does returns another mock

    +
      +
    • spec - flexible but not safe
    • +
    • spec_set - safer, somewhat immutable
    • +
    • autospec - match function signatures of class instances
    • +
    +

    Mocks have a bunch of introspection features

    +
      +
    • called, call_count, call_args, call_args list, method_calls, ... (more)
    • +
    • assert_called, assert_called_once, ... (more)
    • +
    +

    Example: API Requests

    +

    Two options

    +

    Patch locally defined function

    +

    Replace portion of function being tested - side-effect.

    +

    Patch external library

    +

    Which would you pick? USE BOTH! It's really easy to write, don't worry about it and write both.

    +

    Another thing: Mock "Factory"

    +

    Kind of a factory but not really.

    +

    DO NOT mock

    +
      +
    • The filesystem - too many surfaces and edges. Lots of debate but don't do it
    • +
    • use the temp dir module or whatever it is called. Very simple
    • +
    • Acceptance and Integration tests
    • +
    +

    Additional info

    +
      +
    • Write mocks as PyTest fixtures. PyTest and mock go hand-in-hand.
    • +
    • How do you mock a for loop that hits an API a certain number of times?
        +
      • Mock the parent library and setup some sort of a "factory" module
      • +
      • One instantiation setup that mocks all the behavior
      • +
      • For loop means some expected behavior inside for loop and some expected behavior outside for loop.
      • +
      +
    • +
    • Usually you will patch directly in the namespace you are testing.
        +
      • Direct accuracy over what you are replacing.
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_tensorflow-8hr-condensed-20171108/index.html b/docs/talks/SFPython_tensorflow-8hr-condensed-20171108/index.html new file mode 100644 index 00000000..6146ff00 --- /dev/null +++ b/docs/talks/SFPython_tensorflow-8hr-condensed-20171108/index.html @@ -0,0 +1,3702 @@ + + + + + + + + + + + + + + + + Sfpython Tensorflow 8Hr Condensed 20171108 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Installing, Deploying, Using Tensorflow in Python

    +

    Speaker: Chris Fregley, Pipeline.ai (former Netflix, Databricks, kickstarted Spark.)

    +

    https://github.com/PipelineAI/pipeline/

    +

    Zero respect for Python until he found Scientific Python.

    +

    PySpark not his favorite, rather use Scala for Spark, originally a Java guy

    +

    Slides available on meetup: slides

    +

    Great GPU notebooks and examples

    +

    This guy is such a salesman. He used port 6969 because of port colissions. Clever.

    +

    Notes from meetup site

    +

    Main talk (~30 mins + Q&A)

    +

    Optimizing, Profiling, and Deploying High-Performance Spark ML and TensorFlow AI Models in Production with GPUs

    +

    Using the latest advancements from TensorFlow including the Accelerated Linear Algebra (XLA) Framework, JIT/AOT Compiler, and Graph Transform Tool, I’ll demonstrate how to optimize, profile, and deploy TensorFlow Models - and the TensorFlow Runtime - in GPU-based production environment. This talk is 100% demo based on open source tools and completely reproducible through Docker on your own GPU cluster.

    +

    Bio Chris Fregly is Founder and Research Engineer at PipelineAI, a Streaming Machine Learning and Artificial Intelligence Startup based in San Francisco. He is also an Apache Spark Contributor, a Netflix Open Source Committer, founder of the Global Advanced Spark and TensorFlow Meetup, author of the O’Reilly Training and Video Series titled, "High-Performance TensorFlow in Production."

    +

    Previously, Chris was a Distributed Systems Engineer at Netflix, a Data Solutions Engineer at Databricks, and a Founding Member and Principal Engineer at the IBM Spark Technology Center in San Francisco.

    +

    Tensorflow!

    +

    Mostly in C.

    +
      +
    • Neural networks never want to go to production
    • +
    • always want to be retrained
    • +
    • want someone else to do the last 20%
    • +
    +

    Pipeline.ai

    +

    A framework to get your models into solution. Something about data pipelines!

    +

    Today - TensorFlow (TF) - Condensed talk: 8 hour into 30 minutes

    +

    Optimize and Deploy TF models to production.

    +

    Nice to have a working knowledge of TF.

    +

    GPU heavy talk.

    +

    Content Breakdown

    +

    50% training optimizations(GPUs, Training Pipeline, JIT) +50% prediction optimizations (AOT Compile, TF Serving)

    +

    Why heavy focus on 'model prediction' vs 'just training'?

    +

    Training - boring and batch! +Prediction - exciting and real time!

    +

    Agenda - see the slides

    +

    Biggest thing is telling data scientists that they can deploy from their jupyter notebook in a controlled manner. Ability to push it out & roll it back.

    +

    DOCKER - Package model and runtime as one

    +
      +
    • Docker for mac - opened up a ton of use cases!
        +
      • no surprises in production
      • +
      • deploy and tune model + runtime together
      • +
      • same local, dev, production env
      • +
      +
    • +
    +

    Production always a bit different than development before this. A bunch of virtualbox cruft.

    +

    Did he consider vagrant? I think docker just blows vagrant away for developers, removes tons of devops.

    +

    Tune Model + Runtime together! (see slides!)

    +

    Offline models aren't always going to do well online... (see slides)

    +

    Online - real-time metrics. Cost per prediction!

    +

    The prediction profiling and tuning stuff is about bot identification.

    +

    Pipeline AI - Continuous Model Training

    +

    Identify and fix borderline predictions. Hotdog - not hotdog.

    +

    Use crowdflower to label the data - then relabel along the classification's edges.

    +

    Shift traffic to winning model using AI Bandit Algorithms.

    +

    "Once we drain this experiment of its value... we can stop this experiment."

    +

    Shift traffic to minimum "Cloud Cost"

    +

    Google Cloud vs Amazon Web Services

    +

    Shift to amazon when the cloud instances are cheaper. Shift back and forth.

    +

    He made fun of microsoft azure but plugged their kubernetes support.

    +

    NVIDIA GPU Half-Precision Support

    +
      +
    • All about Volta V100 (2017) - AMD - tensor cores / Google TPUs
    • +
    • +

      Pascal P100 (2016)

      +
    • +
    • +

      FP32 = Full Precision

      +
    • +
    • FP16 = Half Precision
    • +
    • Half good for approximate deep learning use cases
    • +
    • Fit two FP16s into FP32 GPU cores for 2x throughput!!
    • +
    • Thunk to 32 bit
    • +
    +

    Nvidia: P100, M40, K40 - all tested for whatever reason

    +

    AMD? - GPU CUDA Programming

    +
      +
    • Barbaric, fun. Must know hardware. Probably hate your life.
    • +
    • Optimized for same instruction, multiple thread.
    • +
    • Do not like if-statement. Like half the cores go unused.
    • +
    • Independent thread scheduling - finally
    • +
    • CUDA Streams
        +
      • Tensorflow uses this heavily
      • +
      • goal is to saturate cpus
      • +
      +
    • +
    +

    Check out Batch Normalization

    +
      +
    • Almost always use batch normalization - except rarely you should never use batch normalization
    • +
    • Technique from 2015
    • +
    • gradient descent
    • +
    • don't want the network to learn the order the data is showing up
    • +
    • first part of pipeline is shuffle
    • +
    • normalize per batch
    • +
    • normalize per layer
    • +
    • each mini batch may have wildly different distributions
    • +
    +

    Dropout

    +
      +
    • sniff connections in your network
    • +
    • prevent overfitting
    • +
    • ensemble different neural architectures
    • +
    • randomly, 50% sniff these things, purposely cripple it
    • +
    • figure out ways to distort things they are trying to block out (spaces, numbers)
    • +
    • more difficult for the network, better the final network was
    • +
    +

    this guy something or other - his friend

    +
      +
    • https://github.com/yaroslavvb/stuff
    • +
    +

    DON'T USE FEED_DICT

    +
      +
    • feed_dict Requires Python<->C++ Serialization
    • +
    • Dataset API
    • +
    • what happened to dataframe? it's gone i guess? tensorflow went right to dataset api
    • +
    +

    Tensorflow Debugger - mouse from a terminal it's crazy, only Google...

    +

    ALWAYS START WITH estimator AND experiment APIs

    +

    These come from Google trying to productionize tensorflow, probably successfully.

    +

    See the slide, has the above title!!!!!!!!

    +
      +
    • Skip all the early demos you see, they are old and crusty.
    • +
    • These simplify model building.
    • +
    • flexible parameter tuning
    • +
    • enable rapid model experiments
    • +
    • +
    +

    Estimator API

    +

    See the slides.

    +
      +
    • Train-to-Serve Design
    • +
    • Create custom or use a canned Estimator
    • +
    • +

      Hides session, graph layers,

      +
    • +
    • +

      Chief:Worker

      +
    • +
    • Supervisor:Worker
    • +
    • getting away from master but not improving their language... just changing it...
    • +
    +

    Canned Estimators

    +

    See the slides, 60% use prebuilt, 40% roll their own estimator

    +
      +
    • Commonly used estimators
    • +
    • Pre tested and pre tuned
    • +
    +

    Multi-headed inference: Single-Objective Estimator vs Multi-Objective Estimator

    +

    Get two answers (objectives out of one estimator or something).

    +

    Hparams - Hyper parameter tuning

    +

    Do a big grid search, a parameter as a range.

    +

    Layers API exists

    +

    Use kubernetes or mesos

    +

    Good cluster organizer for working on this stuff...

    +

    JIT Compiler - and visualizing

    +

    Need to do a Python Context Manager with device as... whatever to use JIT.

    +

    Historically: Spark & Project Tungsten would take your code and create your plan into an optimized one and then to a physical plan.

    +

    Built on XLA - accelerated linear algebra framework.

    +
      +
    • Goals
        +
      • reduce memory Movement
      • +
      • reduce overhead of multiple function calls
      • +
      +
    • +
    +

    AOT Compiler - Standalone, Ahead-Of-Time (AOT) Compiler

    +

    For super tiny devices... pass in your graph.
    +Build up DAGs of operations in spark and tensorflow.

    +
      +
    • tfcompile - point to input for graph and output for graph
    • +
    • built on XLA framework
    • +
    • creates functions with feeds (inputs) and fetches (outputs)
    • +
    • figures out what everything... .so files, what bare minimum is necessary
    • +
    • creates binary down to 600k - this is how we fit in the apple app store or not.
    • +
    • shrink, shrink, tons of slides, freeze for production
    • +
    +

    request batch tuning

    +

    At the end of the day the forward prop. is just matrix multiplies.

    +

    See slides

    +
      +
    • max_batch_size
    • +
    • batc
    • +
    +

    There's like 60 slides left !! Damn, lots of content.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_train-streetfighter-gym-keras-20171108/index.html b/docs/talks/SFPython_train-streetfighter-gym-keras-20171108/index.html new file mode 100644 index 00000000..49db7d4d --- /dev/null +++ b/docs/talks/SFPython_train-streetfighter-gym-keras-20171108/index.html @@ -0,0 +1,3105 @@ + + + + + + + + + + + + + + + + Sfpython Train Streetfighter Gym Keras 20171108 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Gym & Keras @ SFPython

    +

    Speaker: Adam Fletcher - adam@gyroscope.cc

    +

    Using Python To Create SNES STreetFighter II AIs

    +

    Environment (SNES9x) - BizHawk - Environment (Gym) - Agent (Keras-RL)

    +

    Python Libraries: Gym from OpenAI, Keras-RL for training the agent

    +

    Gym

    +

    Gives you an environment for machine learning - what you are operating on.

    +

    Functions: step, reset

    +

    Observation Space

    +

    For Street Fighter is the timer, health, position of character.

    +

    The observation space they chose is based on what a human could see.

    +

    You get to choose how big your observation space would be.

    +

    Stepping

    +

    ??

    +

    Action space - if it gets too big it becomes too hard to do good learning

    +

    I think they just decided you can only press one button and one direction at the same time.

    +

    A human typically does not press right and left at the same time, so it is not part of our action space.

    +

    Rewards Function

    +

    Hardest part of all of this. Tons of naive approaches - did you win?

    +

    Damage received vs damage done.

    +

    Settled on delta in my health vs opponents health, then maximize that gap.

    +

    Agent (Keras-RL)

    +

    Great abstraction for reinforcement learning. Prebuilt agents.

    +

    Random agent - chooses something from the action space and tries it, does not care about observation.

    +

    How do you know if your stuff is working? Compare it against the random one.

    +

    Also has logging and testing for you which is nice.

    +

    Forward

    +

    Pass it an observation and say what should I do?

    +

    Backwards

    +

    It says 'here are the results' - learn from it!

    +

    Controller

    +

    Code wrote to pass all that data back and forth.

    +

    Python3 Socket server with threads - it just worked with the threaded mixin!

    +

    Passed json back and forth over a tcp socket.

    +

    Imagine a state machine that simulated the emulator in your AI code.

    +

    Also with multiple controllers, agents could play each other.

    +

    Python socketserver io 450fps on a cloud server. Lua ip 60fps, lua sqlite io 120fps

    +

    Does it work?

    +

    After 300 games, it worked!

    +

    They ran a final tournament every game.

    +

    M. Bison is OP and the AI always wins. So he got banned.

    +

    Sagat won the 2nd tournament.

    +

    Python in AI/ML

    +

    Python made things super fast!!

    +
      +
    • Gym
    • +
    • Tensorflow
    • +
    • SciPy
    • +
    • Keras
    • +
    +

    One example, when both had very low health, they would back away from each other!!

    +

    So they could not see an advantage from fighting when they could not get a big delta in opponent's health versus theirs.

    +

    The AI is way better than a human

    +
      +
    • millisecond reaction time
    • +
    • way more training can be done, period
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/SFPython_unicode_20170614/index.html b/docs/talks/SFPython_unicode_20170614/index.html new file mode 100644 index 00000000..d51e6086 --- /dev/null +++ b/docs/talks/SFPython_unicode_20170614/index.html @@ -0,0 +1,3372 @@ + + + + + + + + + + + + + + + + Sfpython Unicode 20170614 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Sfpython Unicode 20170614

    + +

    Unicode!

    +

    Python 3!

    +

    Speaker: Lukasz Langa

    +

    Is unicode important?

    +

    Yes! Plane ticket unicode errors can stop you from flying...

    +

    How does Python decode a file when you import a module?

    +

    Python2 imports as ascii by default. Python3 imports as unicode by default.

    +

    Python reads the encoding you give and additionally has a filesystem encoding it uses but he did not cover details of this.

    +

    What is text?

    +

    Words! Communication.

    +

    On bytes and unicode

    +

    Programs that assume you can open a plain text file without encoding are broken.

    +

    A character is not a byte, it is a unicode codepoint. And it can have a long name and you can even use that name in python.

    +

    A codepoint cannot go on a drive. A code point is a platonic ideal, an abstract theoretical concept.

    +

    A code point specifies what character you mean, for example U+0142, in python \u1402.

    +

    In Python 2, the string type tries to be byte too which isn't truly possible. In python 3, bytes is just bytes.

    +

    Text Transmission

    +

    Transmitting text is challenging!

    +

    UTF-16

    +
      +
    • UTF-16 had to prefix the string with a byte order mark. Must be right, must be there... not likely!
    • +
    • Null bytes in the middle of your string! How do we align the bytes in the string?
    • +
    • Not all characters fit in UTF-16
    • +
    +

    UTF-8

    +
      +
    • Tries to be ascii compatible.
    • +
    • First seven bits are ascii, after that we do 2,3,4 bytes.
    • +
    • Simple algorithm: `if this is a special byte, i expect 1-3 continuation bytes after it.
        +
      • This must be how we know where the codepoint ends at variable length...
      • +
      +
    • +
    +
    >>> len(u'frog'.encode("utf-8")
    +??
    +>>> len(u'a'.encode("utf-16")
    +4
    +>>> len(u'4'.encode("utf-16")
    +4
    +
    + +

    Real Purpose for Unicode... emojis??

    +

    Unicode is that thick book with each codepoint. UTF-8 is the encoding!!

    +
      +
    • Unprecedented growth in the standard... We can't fit all the characters in 4 bytes.
    • +
    • Solution: two pseudocode unicode characters to produce one - 8 bytes... good for now.
    • +
    • Basic multilingual plane. 65536 characters. After this we use two pseudocode. Python3 does this for you.
        +
      • Is this for UTF-16 or UTF-8?
      • +
      +
    • +
    • You can encode codepoints in many ways, but codepoints do not have any way to write them into a file.
        +
      • Not all encodings can encode all characters. Code points are stored by encoding into bytes.
      • +
      • UnicodeEncodeError - current encoding doesn't support all the codepoints you are trying to encode to bytes
      • +
      • You can only read unicode back correctly if you know what codepoints was used to encode the bytes
      • +
      +
    • +
    +

    How does Python3 make things better?

    +

    Python2 does not have full unicode support - does not have the full multilingual plane or something.

    +
    >>> len(u'a')
    +1
    +>>> len(u'f')
    +1
    +
    + +
      +
    • A Single Character - Python 2 does (doesn't?) work well with all but the first one.
        +
      • BMP code point (base multilingual plane)
      • +
      • U-Dxxxx surrogate pair
      • +
      • grapheme cluster
      • +
      • sorting element (example dzs in Hungarian)
      • +
      +
    • +
    +

    Grapheme Cluster -- wtf!!

    +

    Use the library unicodedata to combine these grapheme clusters... somehow...

    +
    unicodedata.normalize('NFS', u'\u00c7')
    +unicodedata.normalize('NFS', u'\u00c7').encode('utf8')
    +
    + +

    Tips!

    +
      +
    • Using bytes for text is heading for a bug!
    • +
    • Python3 reused str for unicode text
    • +
    • In Python3 bytes means bytes
    • +
    • When reading data just do b.decode('utf-8')
    • +
    • When writing data back, just do b.encode('utf-8)
    • +
    • Avoid using str() and bytes() without an encoding to convert between types.
    • +
    • In some languages, uppercase and lowercase may not do the same things, so you can't just go back and forth.
        +
      • Python doesn't reliably do this!!
      • +
      +
    • +
    • Python2: narrow build of python - no wide character processing, raise weird inaccurate exceptions...
        +
      • Not common anymore
      • +
      +
    • +
    • Text segmenting, regular expression, right-to-left text
    • +
    • Literary characters: en-dash, em-dash, separators, etc.
    • +
    • Using bytes for text handling is a bug.
    • +
    • Decode Early, Encode Late.
        +
      • Paraphrased: Your data should exist as codepoints for as long as possible
      • +
      +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/airflow-kubernetes-wepay/index.html b/docs/talks/airflow-kubernetes-wepay/index.html new file mode 100644 index 00000000..f8567b89 --- /dev/null +++ b/docs/talks/airflow-kubernetes-wepay/index.html @@ -0,0 +1,3204 @@ + + + + + + + + + + + + + + + + Airflow Kubernetes Wepay - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Airflow on Kubernetes at WePay

    +
      +
    • Speaker: William @ WePay
    • +
    • Where: WePay @ Redwood City
    • +
    • When: 2018.04.11
    • +
    +

    "Tell them what you are going to tell them, tell them, and tell them what you told them."

    +

    "I now refer to dags as dags, but I swore that we should change the culture and call them workflows and now I am calling them dags. But we should call them workflows." - William

    +

    trent: it sounds like they version their dags somehow...

    +

    Question: Are you versioning your DAGs? No we are using git describe so counting up version from a parent.

    +

    Max: Use Apache Arrow to store serialized data, then use xcom_push and pull to send & retrieve the data. Don't store too much serialized data in xcom stuff.

    +

    Max: Backfill is so common, you might consider setting up a whole backflow framework. (Trent: maybe just run a whole scheduler with separate dags that have backfill enabled with a different pool of workers...)

    +

    Max: If you are doing local surgeries or magic on your data, you probably want to keep that in the DAG and use conditionals for what the date is to determine what to do, that way someone running a regular DAG backfill isn't going to blow away your surgery.

    +

    Max: We would build a dag framework for backfilling that would build a custom dag for a particular date range and manage that, then programmatically manage date ranges. Then managing those backfill datasets into production db as atomic operations.

    +

    Initial (non k8s) deployment

    +
      +
    • Airflow under supervisord (scheduler and webserver on same box)
    • +
    • Manually ssh & pip install
    • +
    • Cron job every 2 minutes to git pull and update the dags
        +
      • not a good approach to anything... sorry...
      • +
      • couple layers of review... one person reviews the commit for a few minutes and says "sure (implied ok whatever)"
      • +
      +
    • +
    +

    Issues

    +
      +
    • Everyone running on the same airflow
    • +
    • No isolation (resources, dependencies)
    • +
    • Deploys are monolithic
    • +
    • Scalability
    • +
    • Limited Availability
    • +
    • Cowboy Culture: ssh to box and run commands: We had pets not cattle (snowflakes)
    • +
    +

    Configuration

    +
      +
    • nginx sidecar
    • +
    • airflow scheduler and webser still in the same pod
    • +
    • cloudsql
    • +
    • elk kubernetes
    • +
    • still running under supervisor
    • +
    • no more cron job to git pull DAGs, moved to situation where manually push endpoint on pod to get new dags (pull tarball artifact), not terribly interesting
    • +
    +

    Benefits

    +
      +
    • control deployment
    • +
    • easily deployed: cattle
    • +
    • DAG deployment
    • +
    • isolation / security
    • +
    • scalable (multiple airflows per team)
    • +
    • docker
    • +
    • secrets
    • +
    +

    KubernetesExecutor / KubernetesOperator (K8SOperator)

    +

    Very excited to do this. We use the localexecutor with kubernetes pods so we don't need celery.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/airflow-on-googlecloud/index.html b/docs/talks/airflow-on-googlecloud/index.html new file mode 100644 index 00000000..424e02b8 --- /dev/null +++ b/docs/talks/airflow-on-googlecloud/index.html @@ -0,0 +1,3170 @@ + + + + + + + + + + + + + + + + Airflow On Googlecloud - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Running Airflow inside Google Cloud Platform

    +

    A lot of this was somewhat advertisement for GCP wrapped in Airflow. Could be useful for someone if they are already in this platform and want to hack some. It seems nice.

    +
      +
    • Speaker: Trevor Edwards @ Google
    • +
    • Location: WePay Redwood City
    • +
    • Date: 2018.04.11
    • +
    +

    My notes on this will be sparse and focused on things I don't already know.

    +

    Max chimes in - yes only one airflow scheduler running!

    +

    Questions (at the end)

    +
      +
    • Someone says that Google is planning to release Airflow as a managed service. The speaker would not comment on that.
    • +
    • How much would it cost? Maybe on the order of $100 a month to clone this architecture. Not publicly cloneable yet.
    • +
    +

    Tools

    +
      +
    • KubernetesEngine
    • +
    • Redis for Celery
    • +
    • Airflow Webserver on Google App Engine
    • +
    • Google Cloud Storage for DAGs and logs
    • +
    +

    Securing your Airflow Server

    +

    How to distribute DAGs and Plugins quickly?

    +

    Many people use git workflows, we decided to use Google Cloud Storage.

    +

    Sidecar container rsyncs DAGs/Plugins every 5 seconds. You would need to change how often the scheduler pulls dags to every 1 minute.

    +

    Scaling out Airflow Webserver

    +

    Scaling the scheduler

    +
      +
    • single process: no horizontal scaling
    • +
    • GKE - scale things up
    • +
    +

    Scaling out Airflow Worker

    +

    GKE Node pool with autoscaling can detect a worker at 99% and add another to the pool

    +

    Stackdriver Logging & Monitoring - GKE out of the box...

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/airflow-operating-data-pipeline-with-airflow/index.html b/docs/talks/airflow-operating-data-pipeline-with-airflow/index.html new file mode 100644 index 00000000..cc8ffdeb --- /dev/null +++ b/docs/talks/airflow-operating-data-pipeline-with-airflow/index.html @@ -0,0 +1,3393 @@ + + + + + + + + + + + + + + + + Airflow Operating Data Pipeline With Airflow - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Operating Data Pipeline with Airflow

    +
      +
    • Speaker: Ananth Packkildurai @ Slack (chat app)
    • +
    • Date: 2018.04.11
    • +
    • Location: WePay
    • +
    +

    Notes

    +

    4 Types of Executors - Max freestyles at the end

    +

    Max says - most people should start using KubernetesExecutor when it comes, which is soon.

    +

    Max says - LocalExecutor isn't for production, but it at some point has been deemed OK for production. At some point you will go out and get the biggest machine you will get and it won't work.

    +

    This includes the new KubernetesExecutor.

    +
      +
    1. LocalExecutor - Python MultiProcessing Queue of the size you specify
        +
      • say you want to run 125 slots in your multiprocessing queue
      • +
      • runs as part of the scheduler process
      • +
      • or runs in the process as backfill
      • +
      • if the scheduler fails, it would lose contact with the queue
      • +
      +
    2. +
    3. CeleryExecutor - Simple-ish abstraction for running remote tasks
        +
      • use redis or rabbitmq broker
      • +
      • put the message in the queue that says 'please worker pick up the task locally'
      • +
      • as many workers and queues as you want, workers watch queues and look at messages
      • +
      • workers run messages if they have them
      • +
      • original intent was a yarn executor, but it was hard to do because yarn is a resource negotiator, so it didn't make a lot of sense, hacky not good containerization support for yarn
      • +
      +
    4. +
    5. KubernetesExecutor: Daniel at Bloomberg is contributing this - open PR in the process of being merged, all the code is there
        +
      • They are using it in production at bloomberg
      • +
      • airbnb looking to use it in production
      • +
      • use kubernetes API, no local celery in kubernetes... actually use kubernetes...
      • +
      • scheduler in a pod in or out of kubernetes
      • +
      • airflow containerization was an afterthought but should have been first maybe in hindsight
      • +
      +
    6. +
    7. (heh whoops which one is the third?) Maybe DaskExector...
    8. +
    +

    Slack

    +
      +
    • 10 data engineers
    • +
    • 1000 employees
    • +
    • +

      6M users

      +
    • +
    • +

      1 in 2 per week access data warehouse (trent: what?)

      +
    • +
    • 600,000 events per second at peak
    • +
    • +

      500+ tables

      +
    • +
    • +

      240+ active DAGs

      +
    • +
    • 5400+ tables per day
    • +
    • 68 contributors
    • +
    +

    We have 68 contributors engaging in airflow or building data pipelines despite having 10 data engineers.

    +

    Democratizing data access.

    +

    Agenda

    +
      +
    1. Airflow Infrastructure
    2. +
    3. Scale Airflow Executor
    4. +
    5. Pipeline Operations
    6. +
    7. Alerting and Monitoring
    8. +
    +

    Airflow Infrastructure

    +
      +
    • Local Executor
    • +
    • Tarball code deployment
    • +
    • Continuous deployment with Jenkins
    • +
    • Flake8, yapf & pytest
    • +
    • airflow.sh shell utility to ensure consistent development environment for all the users.
    • +
    +

    Scale Airflow Executor

    +

    Airflwo Multi Retryable Sensors

    +
      +
    • local executor launches new interpreter per task, which takes significant resources.
    • +
    • but we can do multiple external tasks in a single interpreter...
    • +
    • he put the code up but i didn't really get to read all of it, maybe its online
    • +
    +

    Pipeline Operations

    +

    Airflow Fallacies

    +
      +
    • the upstream task success is reliable
    • +
    • the task remain static after the success state
    • +
    • the DAG structure is static
        +
      • people update or delete the dag
      • +
      +
    • +
    • the data quality is not part of a task life cycle
        +
      • definitely a complaint, based on system workflow
      • +
      +
    • +
    +

    MARIO - global dag operator (cli tool)

    +
      +
    • $ ./mario --help
    • +
    • do stuff like clear downstream, export a graphml represenation of downstream
    • +
    • tons of other diagnostic stuff...
    • +
    +

    Data Quality Checker - dqcheck

    +

    Need lots of stuff if you're running 240+ dags, no easy way to visually look and see if some dag's task is in some particular state easily... (trent: lots of ways to do this automatically, they do it automatically)_

    +
      +
    • from slack.airflow.data_quality import DQCheck
    • +
    • do stuff like check if the row count is > 0
    • +
    • Hive partition sensor operator
    • +
    • delete_dag - if a dag is not active in the dagbag, clean up after it (delete all tables related to dag)
    • +
    +

    DAG Policy Validator

    +
      +
    • test_external_tasks - check if external tasks point to valid DAGs and tasks.
    • +
    • test_circular_dependencies - check if tasks have circular dependencies across DAGs.
    • +
    • test_priority_weight - check that production tasks do not depend on lower priority task
    • +
    • test_on_failure - require that highpriority DAGs have an on-failure alert.
        +
      • just basically make sure you get notifications for that set of dags on failure... what's the test just read the dag or import it and check its python attrs?
      • +
      • seems like it would be good to sandbox this too, maybe overwrite the send list after importing it and send it to a different set of people...
      • +
      +
    • +
    • test_sla - require that high-priority DAGs have an SLA
    • +
    • test_sla_timing - SLA timing should make sense. No job should depend on a tas kthat has an equal or longer SLA than it does....
    • +
    • test_has_retry_and_success_callbacks - Require an on-success_callback for tasks with an on_retry_callback.
    • +
    • test_require_dq_for_prod - require sq check for all the high priority tasks.
    • +
    +

    Alerting and Monitoring

    +

    OnCall Alert Callback

    +

    I took a photo of OncallAlertCallback for on call engineers.

    +
      +
    • Alerting should be reliable
    • +
    • Alerts should be actionable
    • +
    • +
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/index.html b/docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/index.html new file mode 100644 index 00000000..74d2b6d9 --- /dev/null +++ b/docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/index.html @@ -0,0 +1,3228 @@ + + + + + + + + + + + + + + + + Design Cost Optimized Architectures - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Design Cost Optimized Architectures

    +
      +
    • +

      How often and how quickly do you need to access your data?

      +
    • +
    • +

      How large is your data set?

      +
    • +
    • +

      How transient is your data?

      +
    • +
    • +

      Clickstream

      +
    • +
    • +

      How much are you prepared to pay to store the data?

      +
    • +
    • +

      Durability: The average, expected annual data loss

      +
    • +
    • S3 Standard, S3 IA (infrequent access), S3 Archive
    • +
    • Does your data require high IOPS?
    • +
    • EBS block storage
    • +
    • Throughput - HDD
    • +
    • +

      IOPS - SSD

      +
        +
      • Remember the "provisioned iops" ssd has much higher IOPS... 32000 iops
      • +
      • cannot be boot volume
      • +
      • probably need to pay monthly or annual instead of by minute/hour
      • +
      +
    • +
    • +

      S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA)

      +
    • +
    • +

      Throughput oriented, lowest cost: Cold HDD (sc1)

      +
    • +
    • +

      Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM.

      +
    • +
    • You will get charged for 2 hours (not 1.5 hours)
    • +
    • Some instances you can pay per second
    • +
    +

    Spot Instances

    +
      +
    • Cheapest option, up to 90% off the price
    • +
    • You place a bid on amazon EC2 instances, you get unused extra capacity.
    • +
    • Instance can get terminated at any time.
    • +
    • You get a 2 minute warning, so there's solutions.
    • +
    • Apparently we can predict this and shut down the application.
    • +
    • Also apparently you don't get kicked off these very often most of the time, but you COULD BE!!
    • +
    +

    Availability Zones are load balanced behind the scenes

    +
      +
    • But instructor says this is changing, so all users will have the same AZ in the future
    • +
    • Users are binned because everyone would use the first one: us-east-1a
    • +
    +

    Reserved Instances - RI

    +
      +
    • Up to 75% discount compared to on-demand instances
    • +
    • Capacity Reservation - 1 to 3 years
    • +
    • AWS particular AZ can run out of capacity on-demand for a particular type of instance
    • +
    • RI Marketplace
    • +
    +

    Lambda

    +
      +
    • acloud.guru is 100% lambda
    • +
    • He says he didn't pay a cent for the first 18 months!
    • +
    • 1 million requests per month free, forever
    • +
    • Developer exam question: what is the max time you can set for lambda?
    • +
    +

    API Gateway

    +
      +
    • Used for lambda, we did not touch on the details very much
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/exam-questions-copied/index.html b/docs/talks/aws.training.solarchitect/exam-questions-copied/index.html new file mode 100644 index 00000000..68c66a9c --- /dev/null +++ b/docs/talks/aws.training.solarchitect/exam-questions-copied/index.html @@ -0,0 +1,3319 @@ + + + + + + + + + + + + + + + + Exam Questions Copied - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Exam Questions

    +

    These are copied from each section of the day-long course

    +

    Resilient Architecture

    +
      +
    • EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK.
    • +
    • EBS is an Independent Lifecycle from EC2 instance
    • +
    • Exam question, we need 12000 iops, so which one do you pick?
    • +
    • You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS
    • +
    • Provisioned is for large database workloads, production environments
    • +
    • st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations
    • +
    • EBS Volume Types: https://aws.amazon.com/iq/
    • +
    • gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone
    • +
    • Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances.
    • +
    • Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible
    • +
    • S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C
    • +
    • C = customer
    • +
    • S3 = ?? probably what you assume
    • +
    • KMS = ?? probably what you assume
    • +
    • S3 has a multi-part upload API
    • +
    • Use this for large files
    • +
    • S3: AWS will never move data to a different region unless you tell us to
    • +
    • Data soverignty laws
    • +
    • EBS: You can move across AZs within a region by creating a snapshot
    • +
    • To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ
    • +
    • EBS: Snapshots go to S3
    • +
    • S3 Replicates across all AZs in a region
    • +
    • except "IA one-zone" which only has 1 zone
    • +
    • S3 Exam question, how to save cost? Set up lifecycle policy!
    • +
    • 30 days: move to IA,
    • +
    • 60 days: move to Glacier
    • +
    • delete after 365 days.
    • +
    • Durability: "Am I going to lose my data, eleven nines."
    • +
    • Availability: "Can I go get my data right now? Ever?"
    • +
    • EFS is block storage, S3 is object storage
    • +
    • CloudFormation Exam Questions
    • +
    • A free service, you only pay for resources it uses
    • +
    • is important to High Availability because you can create and replicate resources easily
    • +
    • What's a template? The JSON or YAML text file
    • +
    • What's a stack? The actual stack of resources created in the account
    • +
    • Storage gateway: know the types and what they are meant for
    • +
    • LOOK IT UP
    • +
    +

    Design Cost Optimized Architectures

    +
      +
    • How often and how quickly do you need to access your data?
    • +
    • How large is your data set?
    • +
    • How transient is your data?
    • +
    • Clickstream
    • +
    • +

      How much are you prepared to pay to store the data?

      +
    • +
    • +

      Durability: The average, expected annual data loss

      +
    • +
    • S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA)
    • +
    • Throughput oriented, lowest cost: Cold HDD (sc1)
    • +
    • Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM.
    • +
    • You will get charged for 2 hours (not 1.5 hours)
    • +
    • Some instances you can pay per second
    • +
    +

    Define Operationally Excellent Architectures

    +

    5.1 Choose design features in solutions that enable operational excellence.

    +
      +
    • metrics: latency, http, 4xx errors, 5xx errors, etc.
    • +
    • cloudwatch can give metrics on ec2 based on what we can measure
    • +
    • can't measure how much data you have stored on ebs volume - no metric
    • +
    • cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms
    • +
    • CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers
    • +
    +

    Performant Architectures

    +
      +
    • Elasticache -
    • +
    • Whenever they say "relational" - use RDS
    • +
    • Whenever they say "nosql" - DynamoDB
    • +
    • Whenever they say "data warehouse" - "Redshift!"
    • +
    • Not going to get tested on relational vs nonrelational
    • +
    • not an exam question, interview question!
    • +
    • 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc)
    • +
    • Not going to get tested on using aurora vs rds choices
    • +
    • Do know what engines are supported
    • +
    • RDS: Which engines does RDS support read replica for?
    • +
    • Question: "offload main database because it's hit hard"
        +
      • Use READ REPLICA
      • +
      +
    • +
    • Question: "You need HA" and then multi AZ deployment
        +
      • Use MULTI AZ DEPLOYMENT
      • +
      +
    • +
    • Bring content closer to viewers and increase performance of website: CloudFront
    • +
    • Can cache dynamic or static content
    • +
    • Your clients are complaining that viewing your videos is really slow
    • +
    • Scale Out: I need better performance, should I increase the size of my instance or add a server?
    • +
    • The answer is ALWAYS add a server: scale out, add instances, use EC2 instance
    • +
    • Exam Question
    • +
    • Exam Anecdote: More exam questions about classic load balancer
    • +
    • Heard from 2 recent exam takers
    • +
    • Exam Question: Load Balancer checks health of ec2 instances behind load balancer
    • +
    • Question: "What happens then?"
        +
      • Load balancer just stops routing requests until the instance is replaced or healthy
      • +
      • Auto scale manages health of the instance (replaces unhealthy instances with healthy instances)
      • +
      +
    • +
    • Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address
    • +
    • EC2 Families: They might ask you what CPU instance type based on your needs
    • +
    +

    Specify Secure Applications

    +

    Security is Job 0 on AWS.

    +
      +
    • big part of exam: how to secure application tiers
    • +
    • how to secure data
    • +
    • networking infrastructure for a single VPC application
    • +
    • +

      acloud.guru vpc training lab (very long)

      +
    • +
    • +

      IAM User: Console access versus programmatic access

      +
    • +
    • Console requires username + password
    • +
    • Guaranteed exam question: Programmatic access just needs access key and secret
        +
      • Not username / password
      • +
      +
    • +
    • IAM Policy: By default users have access to nothing
    • +
    • You must attach an IAM policy (or group with an IAM policy)
    • +
    • IAM Roles: When asked, always pick IAM roles over access keys
    • +
    • Exam questions will try to confuse you: cloudtrail vs. cloudwatch
    • +
    • cloudtrail is a trail - logs
    • +
    • cloudwatch is like watching - metrics
    • +
    • VPC: What is the biggest size and smallest size for VPC CIDR.
    • +
    • Biggest: /16
    • +
    • Smallest: /28
    • +
    • The allowed block size is between a /28 netmask and /16 netmask.
    • +
    • VPC: Only 1 IGW can be attached to 1 VPC
    • +
    • I am not getting enough bandwidth, can I attack an additional internet gateway?
        +
      • NO you can ONLY have 1
      • +
      +
    • +
    +

    Shared Responsibility Model

    +

    Shared between AWS and the customer (me).

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/exam-taking-strategies/index.html b/docs/talks/aws.training.solarchitect/exam-taking-strategies/index.html new file mode 100644 index 00000000..82f309d9 --- /dev/null +++ b/docs/talks/aws.training.solarchitect/exam-taking-strategies/index.html @@ -0,0 +1,3347 @@ + + + + + + + + + + + + + + + + Exam Taking Strategies - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Exam Taking Strategies

    +

    Sleep well, eat well, arrive a few minutes early to the testing center.

    +

    It's a long exam period (2 hours?), the guy next to me was done in an hour.

    +

    Keep track of your time, mark a tough question and go back.

    +

    Remember the relative grading.

    +

    Exams are on a curve

    +
      +
    • You want to aim for above 70%
    • +
    • There's no set passing score
    • +
    • If you get a very low score you could still pass
    • +
    • You get your score
    • +
    +

    Tips

    +
      +
    • Read the question carefully
    • +
    • Seriously
    • +
    • All of it
    • +
    • Read the answers
    • +
    • Use process of elimination
    • +
    • Refer to other questions
    • +
    • you can go back and forth between questions
    • +
    • Time management is critical
    • +
    • When in doubt GUESS
    • +
    +

    Test Axioms

    +
      +
    • "Single AZ": NEVER the right answer
    • +
    • Using AWS managed services should always be preferred
    • +
    • RDS over setting up a database on EC2
    • +
    • Fault Tolerance is DIFFERENT THAN Fault Tolerance
    • +
    • HA == Multiple AZs
    • +
    • Fault Tolerant = What happens when everything everywhere goes down
    • +
    +

    Sample Exam Question 1

    +

    I took a photo of it.

    +

    Strategy: eliminate 2, then focus on the key features of the problem (highlighted in red).

    +

    Sample Exam Question 2: SELECT TWO

    +

    Strategy: Eliminate 2, validate remaining two.

    +

    Watch out for where one is "all of the above" lol

    +

    Sample Exam Question 3: SELECT THREE

    +
      +
    • Which is NOT right?
    • +
    +

    Sample Exam Question 4: SELECT TWO

    +

    Sample Exam Question 5: SELECT TWO

    +
      +
    • Eliminate Single AZ
    • +
    • Since cost is a priority, we use exactly what we need: 4 instances
    • +
    +

    Sample Exam Question 6: Elimination

    +

    Probably not on SA exam, probably on developer

    +

    Need to know a lot: + - What are mappings, parameters in cloudformation, are AMI ids different or the same?

    +

    Sample Question 7: Elimination

    +

    Sample Question 8: Need to know RTO and RPO... how can we deduce...

    +
      +
    • Specific to Disaster Recovery Plan
    • +
    • Recovery Time Objective
    • +
    • +

      Recovery Point Objective

      +
    • +
    • +

      Gotta know this one!

      +
    • +
    +

    Sample Question 9: Eliminate 2

    +

    Remove 2, know what each one is.

    +

    Sample Question 10: know the facts

    +

    Sample question 12: know the facts

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/index.html b/docs/talks/aws.training.solarchitect/index.html new file mode 100644 index 00000000..f17f7762 --- /dev/null +++ b/docs/talks/aws.training.solarchitect/index.html @@ -0,0 +1,3245 @@ + + + + + + + + + + + + + + + + Readme - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    AWS Solutions Architect Daylong Training

    +

    Purpose: Prep for AWS Solutions Architect exam.

    +

    Can you take cloud practitioner exam online?

    +

    acloud.guru videos

    +

    These videos were specifically called out for their VPC lab: https://acloud.guru/learn/aws-certified-solutions-architect-associate`o

    +

    I took an Udemy "Backspace Academy" 10-part VPC lab which I found quite good. I have not done the acloud.guru one to compare.

    +

    Whizlabs Practice Exams

    +

    Solutions Architect Practice Exams are Recommended: https://www.whizlabs.com/aws-solutions-architect-associate/

    +
      +
    • Someone in this class said it's the best bang for the buck.
    • +
    • great details about why the answer is the answer
    • +
    • tons of question for $20
    • +
    • use the discount code on the homepage
    • +
    +

    Test Taking

    +

    There's a markdown file on this

    +
      +
    • Test is on 5 pillars of a "well-architected framework"
    • +
    • see "resources" for whitepaper and pillars
    • +
    • People say that they get practice test questions on their real exam.
    • +
    • SA questions can be really wordy and long. Practice exam is the same.
    • +
    +

    Exam Tips

    +
      +
    • Which service is best for decoupling architecture?
    • +
    • +

      SQS

      +
    • +
    • +

      Determine how to design a Multi-tier

      +
    • +
    +

    Resources

    +
      +
    • AWS Well-Architected Framework Whitepaper
    • +
    • Reliability
    • +
    • Security
    • +
    • Performance
    • +
    • Cost-optimized
    • +
    • Operationally Excellent
    • +
    • These five pillars are on the exam.
    • +
    • +

      There's a file for each of the presentations covering these 5 pillars

      +
    • +
    • +

      AWS IQ will be GA later this year: https://aws.amazon.com/iq/

      +
    • +
    • +

      A way to tap into AWS certified consultants

      +
    • +
    • +

      acloud.guru

      +
    • +
    • 2.5 hour cert prep: acloud.guru/join/awspartners
    • +
    • can get these guys on udemy, they do that to try to get you into their bigger program
    • +
    • Linux Academy Trainings
    • +
    • Linux academy will spin up services for you (and delete them for you) so it's really clean
    • +
    • Cloud Academy Trainings: cloudacademy.com $449/year use "learn-aws-25" at checkout for 25% discount
    • +
    • code is a little old "probably still valid"...
    • +
    • Building it out in cloud academy with labs "is really helpful"
    • +
    • aws.training - "architecting on aws" search terms, try the "architecting on aws" course. There are also 5 others.
    • +
    • Official Study Guide book: "AWS Certified Solutions Architect: Official Study Guide" - $42.63 on amazon.com
    • +
    • The networking version of this is supposed to be excellent
    • +
    • Read whiteppaers: aws.amazon.com/whitepapers - at least the well-architected one
    • +
    • Read FAQ for services we talked about today
    • +
    • Watch old AWS Reinvent Videos
    • +
    • Study Groups: Coworkers taking the cert
    • +
    • Brown bag lunch and learn
    • +
    +

    Wrapup

    +
      +
    • You have to register for the exam, not sure how rescheduling works
    • +
    • Don't take it if you don't feel prepared, you can reschedule for 1 week 1 time or something...
    • +
    • I think you can reschedule longer if you pay more...
    • +
    • Apparently you can take cloud practitioner online?
    • +
    • Look into this.
    • +
    • Bring 2 forms of ID, regular ID plus credit card or other secondary?
    • +
    +

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/operationally-excellent-architectures/index.html b/docs/talks/aws.training.solarchitect/operationally-excellent-architectures/index.html new file mode 100644 index 00000000..fab515e6 --- /dev/null +++ b/docs/talks/aws.training.solarchitect/operationally-excellent-architectures/index.html @@ -0,0 +1,3231 @@ + + + + + + + + + + + + + + + + Operationally Excellent Architectures - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Define Operationally Excellent Architectures

    +

    5.1 Choose design features in solutions that enable operational excellence.

    +
      +
    • metrics: latency, http, 4xx errors, 5xx errors, etc.
    • +
    • cloudwatch can give metrics on ec2 based on what we can measure
    • +
    • can't measure how much data you have stored on ebs volume - no metric
    • +
    • cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms
    • +
    +

    Exam Questions

    +
      +
    • CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers
    • +
    +

    Infrastructure as Code

    +

    CloudFormation

    +
      +
    • Version your infrastructure
    • +
    • +

      Applications can rely on specific changes to infrastructure

      +
    • +
    • +

      Branch your infastructure (e.g. git)

      +
    • +
    • Work on multiple things concurrently
    • +
    • +

      Run version 2 while working on version 3.

      +
    • +
    • +

      Audit changes

      +
    • +
    • Traceability: who and why
    • +
    +

    AWS CodeCommit

    +

    Not on SA Associate - but on developer. Need to know codesuite.

    +
      +
    • Fully managed source control service
    • +
    • HA, durable
    • +
    • Encryption
    • +
    • IAM
    • +
    • No limit on repo size
    • +
    • Does it support LFS? Need to think about what LFS even is...
    • +
    +

    AWS CodeDeploy

    +
      +
    • Fully managed deployment services
    • +
    • Blue/Green Deployments
    • +
    • Deployment Health Tracking
    • +
    • Automatically rollback if failure is detected
    • +
    • Exam Question: Amazon EC2, Fargate, lambda, on-prem servers
    • +
    +

    AWS CodePipeline

    +
      +
    • We skipped over this, don't really need to know about it for this purpose.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/performant-architectures/index.html b/docs/talks/aws.training.solarchitect/performant-architectures/index.html new file mode 100644 index 00000000..ad932cd2 --- /dev/null +++ b/docs/talks/aws.training.solarchitect/performant-architectures/index.html @@ -0,0 +1,3438 @@ + + + + + + + + + + + + + + + + Performant Architectures - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Performant Architectures

    +

    Exam Questions

    +
      +
    • Elasticache -
    • +
    • Whenever they say "relational" - use RDS
    • +
    • Whenever they say "nosql" - DynamoDB
    • +
    • Whenever they say "data warehouse" - "Redshift!"
    • +
    • Not going to get tested on relational vs nonrelational
    • +
    • not an exam question, interview question!
    • +
    • 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc)
    • +
    • Not going to get tested on using aurora vs rds choices
    • +
    • Do know what engines are supported
    • +
    • RDS: Which engines does RDS support read replica for?
    • +
    • Question: "offload main database because it's hit hard"
        +
      • Use READ REPLICA
      • +
      +
    • +
    • Question: "You need HA" and then multi AZ deployment
        +
      • Use MULTI AZ DEPLOYMENT
      • +
      +
    • +
    • Bring content closer to viewers and increase performance of website: CloudFront
    • +
    • Can cache dynamic or static content
    • +
    • Your clients are complaining that viewing your videos is really slow
    • +
    • Scale Out: I need better performance, should I increase the size of my instance or add a server?
    • +
    • The answer is ALWAYS add a server: scale out, add instances, use EC2 instance
    • +
    • Exam Question
    • +
    • Exam Anecdote: More exam questions about classic load balancer
    • +
    • Heard from 2 recent exam takers
    • +
    • Exam Question: Load Balancer checks health of ec2 instances behind load balancer
    • +
    • Question: "What happens then?"
        +
      • Load balancer just stops routing requests until the instance is replaced or healthy
      • +
      • Auto scale manages health of the instance (replaces unhealthy instances with healthy instances)
      • +
      +
    • +
    • Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address
    • +
    • EC2 Families: They might ask you what CPU instance type based on your needs
    • +
    +

    Topics

    +

    RDS

    +
      +
    • You pick a maintenance window and they apply the maintenance
    • +
    • Automated backups
    • +
    • Multi AZ deployments
    • +
    • Encryption at rest and in transit
    • +
    • Scalability: Read Replicas - same AZ or different AZ
    • +
    • Send some read requests there
    • +
    • Exam Question: Which engines does RDS support read replica for? All except oracle?
    • +
    +

    DynamoDB

    +
      +
    • key-value and document database
    • +
    • nosql
    • +
    • single-digit millisecond performance
    • +
    • multi-master available
    • +
    • now also available in aurora
    • +
    • multi-region available (up to you)
    • +
    • durable
    • +
    • RCU: Read Capacity Unit: One strongly consistent read per second OR 2 eventually consistent reads per second
    • +
    • Item up to 4kb in size
    • +
    • Need this for developer, I need so many reads/writes per second
    • +
    • WCU: Write Capacity Unit - item up to 1kb in size
    • +
    • 1 write per second
    • +
    +

    CloudFront

    +
      +
    • Fast CDN service
    • +
    • Dynamic or Static Content
    • +
    • Global Edge Network
    • +
    • Origins: S3, EC2, ELB, HTTP servers
    • +
    • Even if you have an on-prem HTTP server, you can still use cloudfront
    • +
    • Security: AWS Shield, AWS WAF (firewall)
    • +
    • Protect Private Content
    • +
    +

    Elasticache

    +

    memcached and redis - sysops and devops ask you to distinguish

    +

    One of these: memcached, redis

    +

    Scale Up

    +
      +
    • Increase size of hardware
    • +
    • more processing, more storage
    • +
    • Bigger EC2 instances
    • +
    +

    Scale Out

    +
      +
    • Adding more servers
    • +
    • Share the workload
    • +
    • +

      Can be done on the flo

      +
    • +
    • +

      Scale Out: I need better performance, should I increase the size of my instance or add a server?

      +
    • +
    • The answer is ALWAYS add a server: scale out, add instances, use EC2 instance
    • +
    • Trent: This goes into HA as well, instances can fail, we want to have a lot of instances
    • +
    • Trent: Probably save a lot of money scaling out with spot instances because they are so cheap, especially for http workers
    • +
    +

    Load Balancers

    +

    Exam Anecdote: More exam questions about classic load balancer

    +
      +
    • Classic Load Balancer
    • +
    • Layer 4 and Layer 7 (4 = transport layer, 7 = application layer)
    • +
    • Sticky sessions per user
    • +
    • Manages SSL - does all 4 protocols
    • +
    • Exam Question: Load Balancer checks health of ec2 instances behind load balancer
        +
      • Question: "What happens then?"
      • +
      • Load balancer just stops routing requests until the instance is replaced or healthy
      • +
      • Auto scale manages health of the instance
      • +
      +
    • +
    • Application Load Balancer
    • +
    • Layer 7 (application layer)
    • +
    • Route traffic to targets
    • +
    • only HTTP, HTTPS protocols support
    • +
    • Sysops & network certs
    • +
    • native ipv6
    • +
    • Target Groups: cannot assign instances, must make them a member of a target group
        +
      • concept is specific to application load balancer, not done with classic load balancer
      • +
      +
    • +
    • sticky sessions
    • +
    • advanced routing
    • +
    • Network Load Balancer
    • +
    • All about transport (layer 4)
    • +
    • Best performance load balancer
    • +
    • static IP support
        +
      • Exam question: always use DNS name of load balancer, don't point your website at the load balancer IP address
      • +
      +
    • +
    • TLS offloading
    • +
    • Supports SSL now
    • +
    +

    Auto Scaling

    +

    Better fault tolerance, better availability, better cost management

    +
      +
    • Cost Management
    • +
    • Elastic: Adjust number of instances
    • +
    • Health Check: terminate unhealthy instance and start a new one
    • +
    • Cattle vs Pets
    • +
    • Launch systems based on launch configuration
    • +
    • Scaling policy
    • +
    • if cpu > 95 add x instances
    • +
    • any other metric, whatever is good for application
    • +
    +

    EC2 Instance Types

    +
      +
    • Know the family and what they are for.
    • +
    • Exam Question EC2 Families: They might ask you what CPU instance type based on your needs
    • +
    • You don't need to know how many versions for each family, just know the family.
    • +
    +

    Some Handy mnemonics someone made up

    +
      +
    • T Family: general - burstable, good for dynamic workloads
    • +
    • M family: main for application - static, good for consistent workloads
    • +
    • C family: compute - good for small memory footprint and high compute
    • +
    • R family: RAM - high memory to CPU ratio
    • +
    • X family: extreme - high memory for CPU, general in-memory usage
    • +
    • P family: pictures - general graphics
    • +
    • F family: FPGA
    • +
    • G family: graphics intensive applications
    • +
    • H family: HDD backed
    • +
    • I family: SDD
    • +
    • D family: Dense - High disk ratio
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/resilient-architectures/index.html b/docs/talks/aws.training.solarchitect/resilient-architectures/index.html new file mode 100644 index 00000000..fc2dfc8e --- /dev/null +++ b/docs/talks/aws.training.solarchitect/resilient-architectures/index.html @@ -0,0 +1,3443 @@ + + + + + + + + + + + + + + + + Resilient Architectures - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Designing Resilient Architectures

    +

    Overview

    +
      +
    • SQS: Decoupling Mechanism for architecture
    • +
    • Determine how to design a multi-tier architecture
    • +
    • Global Availability Zone - ALWAYS
    • +
    +

    Exam Questions

    +

    It's better to do the labs than read the documentation.

    +

    Anecdotally, the questions are really clear, there's no ambiguity if you really parse each question. There's always something that discounts one of the two best questions.

    +

    Keep the pillars of well-architected systems in mind. The question will always say "high availabity" or "low cost".

    +

    Solutions Architect

    +
      +
    • EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK.
    • +
    • EBS is an Independent Lifecycle from EC2 instance
    • +
    • Exam question, we need 12000 iops, so which one do you pick?
    • +
    • You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS
    • +
    • Provisioned is for large database workloads, production environments
    • +
    • st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations
    • +
    • EBS Volume Types: https://aws.amazon.com/iq/
    • +
    • gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone
    • +
    • Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances.
    • +
    • Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible
    • +
    • S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C
    • +
    • C = customer
    • +
    • S3 = ?? probably what you assume
    • +
    • KMS = ?? probably what you assume
    • +
    • S3 has a multi-part upload API
    • +
    • Use this for large files
    • +
    • S3: AWS will never move data to a different region unless you tell us to
    • +
    • Data soverignty laws
    • +
    • EBS: You can move across AZs within a region by creating a snapshot
    • +
    • To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ
    • +
    • EBS: Snapshots go to S3
    • +
    • S3 Replicates across all AZs in a region
    • +
    • except "IA one-zone" which only has 1 zone
    • +
    • S3 Exam question, how to save cost? Set up lifecycle policy!
    • +
    • 30 days: move to IA,
    • +
    • 60 days: move to Glacier
    • +
    • delete after 365 days.
    • +
    • Durability: "Am I going to lose my data, eleven nines."
    • +
    • Availability: "Can I go get my data right now? Ever?"
    • +
    • EFS is block storage, S3 is object storage
    • +
    • CloudFormation Exam Questions
    • +
    • A free service, you only pay for resources it uses
    • +
    • is important to High Availability because you can create and replicate resources easily
    • +
    • What's a template? The JSON or YAML text file
    • +
    • What's a stack? The actual stack of resources created in the account
    • +
    • Storage gateway: know the types and what they are meant for
    • +
    • LOOK IT UP
    • +
    +

    Sysops (NOT the focus today)

    +

    Associate Developer (NOT the focus today)

    +
      +
    • CloudFormation: what's wrong with a template, what's missing from a template
    • +
    +

    Elastic Block Store

    +

    Whitepaper: AWS Storage Services Overview

    +
      +
    • MiB is Million bytes
    • +
    • not megabytes (GiB is 1000x1000x1000)
    • +
    • Different Volume Types
    • +
    • gp2, io1, st1, sc1
    • +
    • max size you can get of any one is 16 TB
    • +
    • Snapshots
    • +
    • Supports Encryption
    • +
    • +

      Independent Lifecycle than EC2 instance

      +
    • +
    • +

      EBS snapshots are backed up to S3

      +
    • +
    +

    EFS - Know that efs exists

    +
      +
    • Network filesystem, can attach to multiple efs instances
    • +
    • Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible
    • +
    +

    S3

    +
      +
    • Cross-region replication, cross-account replication
    • +
    • 5 terabytes is limit on object size
    • +
    • 11 nines
    • +
    • supports server-side encryption: SSE-S3, SSE-KMS, SSE-C
    • +
    • Supports versioning files as you update but you are paying for new versions
    • +
    • multi-part upload API
    • +
    • cross-region replication
    • +
    • S3 Storage Classes Table = see photo
    • +
    • There is S3-RRS: 4 nines reduced-redundancy
    • +
    • probably NOT on exam: https://aws.amazon.com/s3/reduced-redundancy/
    • +
    • Charged for a minimum of 30 days
    • +
    • S3 Replicates across all AZs in a region
    • +
    • except "IA one-zone" which only has 1 zone
    • +
    • S3 Exam question, how to save cost? Set up lifecycle policy!
    • +
    • 30 days: move to IA,
    • +
    • 60 days: move to Glacier
    • +
    • delete after 365 days.
    • +
    • Durability: "Am I going to lose my data, eleven nines."
    • +
    • Availability: "Can I go get my data right now? Ever?"
    • +
    • Glacier
    • +
    • Retrieval options: expedited, standard, bulk
    • +
    • Deep archive is always a few hours
    • +
    +

    Cloudfront: CDN Service

    +

    It will be on the exam.

    +

    We'll talk about it later.

    +

    One person used it to host a video.

    +

    AWS CloudFormation

    +

    Associate developer certification goes in depth about CloudFormation templates.

    +
      +
    • Free
    • +
    • Infrastructure as code
    • +
    • Model your entire infrastructure as text: YAML or JSON
    • +
    • Uses templates and stacks to provision resources
    • +
    • "stack" - create, update, delete resources as a single unit
    • +
    • What's a template? The JSON or YAML text file
    • +
    • What's a stack? The actual stack of resources created in the account
    • +
    • Declarative - aka idempotent, reapplying won't create a second set... must use tags?
    • +
    +

    Storage Gateway

    +
      +
    • Hybrid environment - move data between on-prem and the cloud
    • +
    • Exam Question: know the types and what they are meant for
    • +
    +

    Availability Zones Diagram

    +
      +
    • AWS contains regions (currently: 22 regions)
    • +
    • Regions contain Availability Zones (AZs)
    • +
    • At least 2 AZs in every region, typically 3
    • +
    • Each AZ can have multiple data centers (typically 3 data centers)
    • +
    +

    High Availability (HA)

    +
      +
    • You need to deploy in at least 2 AZs for HA.
    • +
    +

    Diagram

    +

    AWS contains Regions, Regions each contain their own AZs

    +
      +
    • Regions are NOT connected by lines
    • +
    • AZs are connected by lines
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/aws.training.solarchitect/secure-applications-and-architectures/index.html b/docs/talks/aws.training.solarchitect/secure-applications-and-architectures/index.html new file mode 100644 index 00000000..7bc6b74c --- /dev/null +++ b/docs/talks/aws.training.solarchitect/secure-applications-and-architectures/index.html @@ -0,0 +1,3470 @@ + + + + + + + + + + + + + + + + Secure Applications And Architectures - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Specify Secure Applications

    +

    Security is Job 0 on AWS.

    +
      +
    • big part of exam: how to secure application tiers
    • +
    • how to secure data
    • +
    • networking infrastructure for a single VPC application
    • +
    • cloud guru vpc (I did this last night)
    • +
    +

    Exam Questions

    +
      +
    • IAM User: Console access versus programmatic access
    • +
    • Console requires username + password
    • +
    • Guaranteed exam question: Programmatic access just needs access key and secret
        +
      • Not username / password
      • +
      +
    • +
    • IAM Policy: By default users have access to nothing
    • +
    • You must attach an IAM policy (or group with an IAM policy)
    • +
    • IAM Roles: When asked, always pick IAM roles over access keys
    • +
    • Exam questions will try to confuse you: cloudtrail vs. cloudwatch
    • +
    • cloudtrail is a trail - logs
    • +
    • cloudwatch is like watching - metrics
    • +
    • VPC: What is the biggest size and smallest size for VPC CIDR.
    • +
    • Biggest: /16
    • +
    • Smallest: /28
    • +
    • The allowed block size is between a /28 netmask and /16 netmask.
    • +
    • VPC: Only 1 IGW can be attached to 1 VPC
    • +
    • I am not getting enough bandwidth, can I attack an additional internet gateway?
        +
      • NO you can ONLY have 1
      • +
      +
    • +
    +

    Shared Responsibility Model

    +

    Shared between AWS and the customer (me).

    +

    AAA: Authenticate, Authorize, Audit

    +

    Authenticate

    +
      +
    • IAM Username/Password
    • +
    • Access Key (+ MFA)
    • +
    • Federation
    • +
    +

    Authorize

    +
      +
    • IAM Policies
    • +
    +

    Audit

    +
      +
    • CloudTrail - region specific logging
    • +
    +

    IAM Groups

    +
      +
    • Groups can be nested
    • +
    • Attach IAM Policy to group
    • +
    • You don't want to attach policies to users.
    • +
    • Users can be in multiple groups
    • +
    • There is no default group for all users
    • +
    • Exam Question: By default users have access to nothing
    • +
    • You must attach an IAM policy (or group with an IAM policy)
    • +
    +

    IAM Roles

    +
      +
    • Identity created for specific permissions
    • +
    • Can be assumed by people who need it (and have perms to do so)
    • +
    • Roles can be assumed by users, applications, or assigned to resources/services.
    • +
    • You can only assume one role at a time
    • +
    • When asked, always pick IAM roles over access keys
    • +
    • Best solution for giving access to security in multiple accounts
    • +
    • Cross account ??
    • +
    • Best way to give access to other organizations
    • +
    • Need to use API to enumerate roles for a user, then compare permissions
    • +
    +

    Web Identity Federation

    +
      +
    • AWS Security Token Service (STS)
    • +
    • Temporary credentials for access to resources (e.g. 24 hour max)
    • +
    +

    IAM Policies

    +
      +
    • There is a great simulation tool for testing
    • +
    • Attach permissions
    • +
    • specify type of access
    • +
    • actions that can be performed
    • +
    • resources on which actions can be performed
    • +
    • etc
    • +
    • Principle of least privilege
    • +
    • JSON format
    • +
    +

    Calculating Permissions

    +
      +
    • Everything implicitly denied
    • +
    • Explicit allows override implicit denies
    • +
    • Explicit denies override explicit allows
    • +
    +

    AWS CloudTrail

    +
      +
    • Logging (see page for details)
    • +
    +

    S3 Security

    +
      +
    • Bucket Policy
    • +
    • ACL (Access Control Lists)
    • +
    • Applied to specific objects within the bucket
    • +
    +

    Encryption

    +
      +
    • Encrypt S3 Buckets
    • +
    • Off by default
    • +
    • S3 Versioning
    • +
    • Once turned on, cannot turn off
    • +
    • maybe possible to suspend
    • +
    • Increases storage costs, previous versions are not deleted
    • +
    +

    Security Groups versus ACLs - Whiteboarding

    +

    See the guru 10 part VPC lab course I took last night (udemy) for more VPC details.

    +
      +
    • VPC goes in a region
    • +
    • Security group is a firewall
    • +
    • Security group vs Access Control List (SG vs ACL)
    • +
    • ACL attached to subnet
        +
      • So it applies to all EC2 instances
      • +
      +
    • +
    • Security Group attached to EC2 instance
    • +
    • Exam question: What is the biggest size and smallest size for VPC CIDR.
    • +
    • Biggest: /16
    • +
    • Smallest: /28
    • +
    • The allowed block size is between a /28 netmask and /16 netmask.
    • +
    • Exam Question: Only 1 IGW can be attached to 1 VPC
    • +
    • I am not getting enough bandwidth, can I attack an additional internet gateway?
        +
      • NO you can ONLY have 1
      • +
      +
    • +
    • ACL you can set allow or deny
    • +
    • Security in layers, so we want Firewall, ACL, and Security Group
    • +
    • Security Group is stateful -- ACL is stateless
    • +
    • This matters because ACL will not allow outbound response during a single network action
    • +
    • Security group allows 2-way connection
    • +
    +

    Networking in General

    +

    "Need to know networking to pass the exam."

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/cypherpunks_writecode_20161112/index.html b/docs/talks/cypherpunks_writecode_20161112/index.html new file mode 100644 index 00000000..c94b874d --- /dev/null +++ b/docs/talks/cypherpunks_writecode_20161112/index.html @@ -0,0 +1,3236 @@ + + + + + + + + + + + + + + + + Cypherpunks Writecode 20161112 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Cypherpunks Writecode 20161112

    + +

    Cypherpunks Write Code - Protecting Online Privacy

    +

    Speaker: Steve

    +

    Date: 2016.11.12

    +

    Basis: Cypherpunks Manifesto - Eric Hughes (2003)

    +

    See quote from this about writing software.

    +

    Motivation

    +
      +
    1. Complacency
    2. +
    3. Available Applications
        +
      • Whatsapp owned by facebook, hard to know about tampering
      • +
      • Signal
      • +
      • 2/3 of Tor users have left since 2013 fall
          +
        • 2-3 million out of billions of internet users
        • +
        +
      • +
      +
    4. +
    5. PRISM Partners and what they collect (Apple, Facebook, Google, etc.)
    6. +
    +

    One Possible Solution

    +
      +
    1. Cypherpunks writing code
        +
      • Regular hackathons with ~2 official projects for each
      • +
      +
    2. +
    3. Designers Contributing
        +
      • More useable software (than historic cypherpunk work)
      • +
      +
    4. +
    +

    Project Requirements Idea

    +
      +
    1. Open Source
    2. +
    3. Project must include well defined tasks for us to do
        +
      • Github issues, openness in allowing anyone to contribute to issues
      • +
      +
    4. +
    5. Project representative should be in attendance (virtual or physical)
    6. +
    7. Represenative helps guide efforts and also attend event
    8. +
    9. Represeentative should:
        +
      • motivate why their projec is important
      • +
      • and which features are a priority
      • +
      +
    10. +
    +

    Shout Out: DESIGN == GOOD

    +
      +
    1. Lets appreciate good design!
    2. +
    3. Snowden / Greenwald could barely figure out PGP
        +
      • Project maintainer said 'screw that guy he should have figured it out or gone away'
      • +
      +
    4. +
    +

    Project Discussion: Which projects deserve our attention?

    +
      +
    1. Online Discussion
    2. +
    3. Wiki
    4. +
    5. Dymaxion: Please Stop Writing Messaging Apps
        +
      • Contains 24 other ideas for Cypherpunk apps
      • +
      +
    6. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/defcon25-nfc-tool-from-scratch-20170730/index.html b/docs/talks/defcon25-nfc-tool-from-scratch-20170730/index.html new file mode 100644 index 00000000..a4561d19 --- /dev/null +++ b/docs/talks/defcon25-nfc-tool-from-scratch-20170730/index.html @@ -0,0 +1,3532 @@ + + + + + + + + + + + + + + + + Defcon25 Nfc Tool From Scratch 20170730 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Defcon25 Nfc Tool From Scratch 20170730

    + +

    NFC Tool From Scratch

    +

    Speaker: shanhaoqi@360.cn +Location: Defcon 25 (2017)

    +
      +
    • NFC & ISO14443A
    • +
    • What is UniProxy
    • +
    • Master and Slave
    • +
    +

    Quick Demo I

    +

    Put the credit card in a UniProxy Master +1. Put the

    +
      +
    • 2 UniProxy Hardware
    • +
    • 1 Cellphone
    • +
    • 1 NFC enabled credit card
    • +
    +

    Who we are: Unicorn Team

    +
      +
    • Insternal security research team of Qihoo 360, founded in 2014.
    • +
    • Focus on wireless hardware hacking and defense
    • +
    • Low cost GPS Spoofing Defcon 23
    • +
    • LTE Redirection acttac - Defcon 24
    • +
    • Attack on powerline communication, Blackhat USA 2016
    • +
    • +

      Ghost Telephonist - Defcon 25

      +
    • +
    • +

      Serial hacking tools developed: HackID, HackID Pro, SafeRFID - more I missed

      +
    • +
    +

    NFC and ISO14443A

    +

    We will focus on ISO14443A for the demo.

    +
      +
    • +

      NFC

      +
        +
      • 13.56MHz
      • +
      • low-cost
      • +
      • does not require power
      • +
      • well developed and deployed
      • +
      +
    • +
    • +

      ISO14443A

      +
        +
      • In china: passport, bank card, etc.
      • +
      • more info in slides
      • +
      +
    • +
    +

    Goals

    +
      +
    • ID Card - could be exploited
        +
      • Access forbidden area
      • +
      • Target banking systems
      • +
      +
    • +
    +

    How

    +
      +
    • Targeting Protocols
        +
      • Proxmark III (The best RFID hardware)
          +
        • Supports many protocols, powerful, cannot hack credit cards
        • +
        +
      • +
      • ChameleonMini
      • +
      +
    • +
    • Targeting Data: NFCProxy, NFCGate
    • +
    +

    What is UniProxy

    +

    Can be extended for ISO14443 protocol and 15693 standard.

    +
      +
    • PN7462AU based NFC relay/proxy device
    • +
    • Supports ISO14443A Protocol
        +
      • Can be extended for other protocols that the chipset supports
      • +
      +
    • +
    • Targeting QuickPass, VisaPay, EMV, Unipay credit cards
    • +
    • Reader emulator: Master
    • +
    • card emulator: Slave
    • +
    • ... see photos
    • +
    +

    Why PN7462AU

    +
      +
    • NXP Chip
    • +
    • 20 MHz Cortext-M0 Core
    • +
    +
    24L01 Chip coordinates between the master and slave
    +
    Their company has not open sourced the firmware, they didn't let him
    +

    I think they write some bits on the iblock and a lot of the iblock is boiler plate?

    +

    Lee says the nfc transaction times out easily and this might keep the connection warm?

    +

    If there is an R block the card emulator will process itself

    +

    Speaker says: Principle Described is "VERY SIMPLE"

    +

    Issues

    +

    Tons of issues occurred in development.

    +
      +
    • First byte of UID is in the firmware, will always be "zero eight"??
        +
      • Did not find a way to modify?
      • +
      +
    • +
    • Waiting/Wakeup time
        +
      • Real issue when developing a proxy tool
      • +
      • NFC has no power, uses power from the reader
      • +
      • Gets response from the reader and turns off
      • +
      • Must modify wakeup time - see code (to ensure the NFC is powered?)
      • +
      +
    • +
    • I/S/R - Block data
        +
      • We do not need to transfer all data
      • +
      • Just transfer I block data, need to directly transfer S/R block data
      • +
      • Read the ISO carefully for more info
      • +
      +
    • +
    • Power supply can cause corruption of the chipset
        +
      • Don't to do any tricks = follow the regular procedure
      • +
      • This is very sensitive
      • +
      +
    • +
    +

    The proxy card is used to make the purchase when the master card can be read

    +

    There is a video of the proxy card in action on my phone.

    +

    You should use a GuardBunny sleeve on your NFC cards to block RF...

    +

    Summary

    +
      +
    1. Read Protocol Well
    2. +
    3. Better not develop without official support
    4. +
    +

    Improvements - future

    +
      +
    1. Improve transmission range to 100 meters
        +
      • Currently 50? 15? meters
      • +
      +
    2. +
    3. Target security ID cards, HID iClass, Chinese ID
    4. +
    5. Self-compatibility
        +
      • Currently only ISO14443A
      • +
      • want to adapt to 15693 and let it know which it is using
      • +
      +
    6. +
    7. How?
    8. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/elastic-search-talk-071415.txt b/docs/talks/elastic-search-talk-071415.txt new file mode 100644 index 00000000..80327e97 --- /dev/null +++ b/docs/talks/elastic-search-talk-071415.txt @@ -0,0 +1,55 @@ + + + +OpenDNS - Why use elastic search? 7-14-15 + +Wikipedia uses elastic search for their full text search. +Github uses elastic search for structured searches in a repository. + +You could build a kayak style search in elastic search if you wanted with a single query. +Kibana allows visualization of data by making heavy use of elastic search. + +What is it? Elasticsearch is a distributed, open source search and analytics engine, designed for horizontal scalabilty, reliability, and easy management. + +Elasticsearch wraps Lucine, a Java? library, and makes it available via a REST API. + +Every piece of data by default keeps 2 copies of each datum. Has a REST API. + +Elastic Search itself is open source. Elastic is the company behind elastic search. + +CONCEPTS: + +Concept: "Document" - The unit of data fed into elasticsearch in JSON format. + +{ + "from" : "tony@stark.com", + ... +} + +Concept: "Comparing RDBMS <-> ElasticSearch" +mapping: +database->index +table->type +(2 more) +-> +field-> + + +Now lets translate SQL to ElasticSearch (see presentation) +Get/Select mapped directly + +Update is a little more interesting (just some documents/rows) + + +WHY??? SEARCH for a SINGLE term in a SINGLE field: +SQL: SELECT * FROM emails WHERE body LIKE "% have %"; + +We lose 'stemming', we might also want to match 'having' as well as 'have'. ElasticSearch does this internally, apparently. + + + + + + + + diff --git a/docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/index.html b/docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/index.html new file mode 100644 index 00000000..a29ebb7d --- /dev/null +++ b/docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/index.html @@ -0,0 +1,3555 @@ + + + + + + + + + + + + + + + + Notes Partii Trent - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Notes Partii Trent

    + +

    Part 2 - Scaling Flask for Production.

    +

    Notes from Miguel Grinberg's talk on making a production flask app.

    +

    PyCon 2016 - 20160528 0900 PST

    +

    Presentation URL: Miguel will put a URL in the github readme and tweet the link.

    +

    Scaling Web Servers

    +

    Problem - one request at a time. Not great.

    +

    Multiple Threads

    +

    Limited use of multiple threads because of GIL. Not really great.

    +

    Multiple processes

    +

    Obviously multiple apps sounds nice. Each process has its own set of things.

    +

    What about SQLAlchemy?

    +

    Green threads / coroutines - asyncio, gevent, eventlet.

    +

    Flask doesn't support asyncio.

    +

    Flask does support gevent, eventlet.

    +

    IO and standard library threading functions are incompatible.

    +

    How about manually triggering a switch? - sleep function to take a break and let other threads have a turn.

    +

    Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch.

    +

    Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice.

    +

    Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).

    +

    Using Production Web Servers (tag: v0.12)

    +
    gunicorn
    +

    Limited load balancing - Why limited? I will have to look this up.

    +

    Written in Python - robust but not lightning fast

    +

    Supports multiple processes, and eventlet or gevent green threads.

    +
    uwsgi
    +
    nginx
    +

    Written in C.

    +

    Ideal for serving static files in production. You expose the static file in the nginx config.

    +

    Bottlenecks: I/O Bound and CPU Bound

    +
    I/O Bottlenecks
    +

    Flack example: scraping links included in posts

    +

    Solution: concurrent request handlers through multiple threads, processes, or green threads.

    +

    Make I/O heavy requests asynchronous.

    +
    CPU Bottlenecks
    +

    Flack example: rendering posts from markdown to HTML

    +

    Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.

    +

    Asynchronous HTTP Requests (tag: v0.13)

    +
      +
    1. Request starts background work, gives a status 202.
    2. +
    3. Goes back to listening requests.
    4. +
    5. Location header has a status URL where the client can ask for status for the asynchronous task.
    6. +
    7. Request to status URL returns 202 while the request is still in progress.
    8. +
    9. When complete, (see presentation for details)
    10. +
    +

    There is a decorator for this in flack, migue's app.... @async decorator.

    +

    That's all that is necessary!!! This is almost too easy.

    +

    If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation.

    +

    note that request.environ has environmental information to build a request object.

    +

    This way miguel can build his own request object.

    +

    Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request.

    +

    We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested.

    +

    Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.

    +

    Celery Workers (tag: v0.14)

    +

    There's a wrapper in manage.py. Celery is integrated into the previous async section.

    +

    For quick setup redis works with Celery.

    +

    Celery needs to be available in init.py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.

    +

    Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens.

    +

    This "server-push" websocket model will reduce load, removing all redundant quests.

    +

    The previous version used 2 requests per second per client just to stay up to date.

    +

    Options: +1. Streaming +2. Long-polling +3. WebSocket +4. Socket.IO (long-polling + WebSocket)

    +
    Streaming
    +

    One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask

    +
    Long polling
    +

    client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.

    +
    WebSocket
    +

    HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.

    +
    SocketIO
    +

    written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client.

    +

    Type 1:

    +

    Python client: use socketio.emit class in a push_model method. See slides. +Javascript server: socketio node.js service

    +

    Type 2:

    +

    Python Server: @socketio.on() decorator +Javascript client: socket.emit(). See slides.

    +

    Even more Socket.IO. We can now only use gevent or eventlet.

    +

    See the events.py module git diff v0.14 v0.15, added to manage events.

    +

    I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful.

    +

    This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed.

    +

    Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source.

    +

    Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code.

    +

    manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in.

    +

    Also see tests. socketio has its own test client.

    +

    Finally nginx has requirements for load balancing. Nginx option "sticky sessions"

    +

    Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.

    +

    Flask-SocketIO

    +
      +
    • Miguel's project
    • +
    • Pure python, translation of the Socket.IO node project for flask.
    • +
    +
    Questions / Notes
    +
      +
    • Flask has a Python profiler.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/index.html b/docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/index.html new file mode 100644 index 00000000..1e79d9cb --- /dev/null +++ b/docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/index.html @@ -0,0 +1,3814 @@ + + + + + + + + + + + + + + + + Notes Parti Trent - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Notes Parti Trent

    + +

    Production Ready Flask App - Part I

    +

    Notes from Miguel Grinberg's talk on making a production flask app.

    +

    PyCon 2016 - 20160528 0900 PST

    +

    Presentation URL: Miguel will put a URL in the github readme and tweet the link.

    +

    1. Move utility functions to utils.py (tag: v0.2)

    +

    url_for, timestamp functions.

    +

    2. Refactor database models. (tag: v0.3)

    +

    Avoid cyclic dependency of importing db from controller then importing model from models.py

    +

    Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded "from flack import db".

    +

    3. Create an Application Package (tag: v0.4) - Use Flask-Script

    +

    A newer option exists over Flask-Script but is not yet production ready.

    +

    Flask-Script is available now: +https://flask-script.readthedocs.io/en/latest/

    +

    See git diff v0.3 v0.4 between these two tags to understand necessary changes.

    +

    4. Refactoring API Authentication (tag: v0.5) -

    +

    Moved auth stuff to auth.py. There were three auth functions finally imported.

    +

    Again see git diff v0.4 v0.5 for details.

    +

    5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure.

    +

    To get the overview, checkout this tag and manage.py. Look at file structure.

    +

    Now we are in a django style construction. tests folder exists alongside flack folder.

    +

    6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py.

    +

    Add a config.py. This is pretty hairy even in django.

    +

    People solve configuration in different ways.

    +

    I have a pretty good django dev.cfg/prod.cfg pattern that I would use here.

    +

    7. Create an API Blueprint - separate the api.

    +

    Create: flack/api.py. Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py.

    +

    8. Create Stats package.

    +

    See git diff v0.8 v0.9

    +

    9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app.

    +
    +
    +
    +

    Sometimes it is desirable to work with more than one application +Best Example: Unit tests that need applications with different configurations.

    +
    +
    +
    +

    SPECIAL NOTE:

    +

    Having app blueprints allows you to have a really elegant test setup and teardown.

    +

    Howto get the Blueprint working (see git diff v0.9 v.10 for exact code)

    +

    We need to get rid of app because it will exist outside the context of the controller.

    +

    Now we can no longer reference app.
    +We must refactor app.config and other references to app. +That means no app.debug.

    +

    To achieve this we can use a Blueprint. +Use the current_app context variable to access application.

    +

    Put application factory function in init.py, see create_app function here.

    +

    To create an app you now call create_app, pass an application name, and get the app.

    +

    SQLAlchemy needs the models in init.py because it introspects on the app. +You can miss this and maybe the models get imported elsewhere but that is sloppy.

    +

    10. Creating an API Package (tag: v0.11) - Turn api.py into a package.

    +

    This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users.

    +

    tokens, messages, users become modules inside of the api package.

    +

    Part 2 - Scaling Flask for Production.

    +

    Notes from Miguel Grinberg's talk on making a production flask app.

    +

    PyCon 2016 - 20160528 0900 PST

    +

    Presentation URL: Miguel will put a URL in the github readme and tweet the link.

    +

    Scaling Web Servers

    +

    Problem - one request at a time. Not great.

    +

    Multiple Threads

    +

    Limited use of multiple threads because of GIL. Not really great.

    +

    Multiple processes

    +

    Obviously multiple apps sounds nice. Each process has its own set of things.

    +

    What about SQLAlchemy?

    +

    Green threads / coroutines - asyncio, gevent, eventlet.

    +

    Flask doesn't support asyncio.

    +

    Flask does support gevent, eventlet.

    +

    IO and standard library threading functions are incompatible.

    +

    How about manually triggering a switch? - sleep function to take a break and let other threads have a turn.

    +

    Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch.

    +

    Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice.

    +

    Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).

    +

    Using Production Web Servers (tag: v0.12)

    +
    gunicorn
    +

    Limited load balancing - Why limited? I will have to look this up.

    +

    Written in Python - robust but not lightning fast

    +

    Supports multiple processes, and eventlet or gevent green threads.

    +
    uwsgi
    +
    nginx
    +

    Written in C.

    +

    Ideal for serving static files in production. You expose the static file in the nginx config.

    +

    Bottlenecks: I/O Bound and CPU Bound

    +
    I/O Bottlenecks
    +

    Flack example: scraping links included in posts

    +

    Solution: concurrent request handlers through multiple threads, processes, or green threads.

    +

    Make I/O heavy requests asynchronous.

    +
    CPU Bottlenecks
    +

    Flack example: rendering posts from markdown to HTML

    +

    Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.

    +

    Asynchronous HTTP Requests (tag: v0.13)

    +
      +
    1. Request starts background work, gives a status 202.
    2. +
    3. Goes back to listening requests.
    4. +
    5. Location header has a status URL where the client can ask for status for the asynchronous task.
    6. +
    7. Request to status URL returns 202 while the request is still in progress.
    8. +
    9. When complete, (see presentation for details)
    10. +
    +

    There is a decorator for this in flack, migue's app.... @async decorator.

    +

    That's all that is necessary!!! This is almost too easy.

    +

    If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation.

    +

    note that request.environ has environmental information to build a request object.

    +

    This way miguel can build his own request object.

    +

    Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request.

    +

    We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested.

    +

    Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.

    +

    Celery Workers (tag: v0.14)

    +

    There's a wrapper in manage.py. Celery is integrated into the previous async section.

    +

    For quick setup redis works with Celery.

    +

    Celery needs to be available in init.py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.

    +

    Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens.

    +

    This "server-push" websocket model will reduce load, removing all redundant quests.

    +

    The previous version used 2 requests per second per client just to stay up to date.

    +

    Options: +1. Streaming +2. Long-polling +3. WebSocket +4. Socket.IO (long-polling + WebSocket)

    +
    Streaming
    +

    One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask

    +
    Long polling
    +

    client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.

    +
    WebSocket
    +

    HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.

    +
    SocketIO
    +

    written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client.

    +

    Type 1:

    +

    Python client: use socketio.emit class in a push_model method. See slides. +Javascript server: socketio node.js service

    +

    Type 2:

    +

    Python Server: @socketio.on() decorator +Javascript client: socket.emit(). See slides.

    +

    Even more Socket.IO. We can now only use gevent or eventlet.

    +

    See the events.py module git diff v0.14 v0.15, added to manage events.

    +

    I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful.

    +

    This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed.

    +

    Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source.

    +

    Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code.

    +

    manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in.

    +

    Also see tests. socketio has its own test client.

    +

    Finally nginx has requirements for load balancing. Nginx option "sticky sessions"

    +

    Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.

    +

    Flask-SocketIO

    +
      +
    • Miguel's project
    • +
    • Pure python, translation of the Socket.IO node project for flask.
    • +
    +
    Questions / Notes
    +
      +
    • Flask has a Python profiler.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/flack_miguel_grinberg/NOTES_preclass.txt b/docs/talks/flack_miguel_grinberg/NOTES_preclass.txt new file mode 100644 index 00000000..21548f0f --- /dev/null +++ b/docs/talks/flack_miguel_grinberg/NOTES_preclass.txt @@ -0,0 +1,53 @@ +SATURDAY 9 A.M.–12:20 P.M. + +FLASK AT SCALE +MIGUEL GRINBERG + +Course Repo: +git@github.com:miguelgrinberg/flack.git + +My Fork (with these notes): +git@github.com:robbintt/flack.git + +Audience level: +Intermediate +Category: +Web Frameworks +DESCRIPTION +Do you think that because Flask is a micro-framework, it must only be good for small, toy-like web applications? Well, not at all! In this tutorial I am going to show you a few patterns and best practices that can take your Flask application to the next level. +ABSTRACT +Can Flask scale? For many, that is the million dollar question. Unfortunately even the Flask official documentation is ambiguous about this topic. Flask is a small, unobtrusive framework that simplifies the interface between your application and the web server. Outside of that, it mostly stays out of your way, so if you need to write an application that can scale, Flask is not going to prevent it, and in fact, it will allow you to freely choose the components of your stack and not impose choices on you like big frameworks tend to do. + +In this tutorial session, I will walk you through a list of typical patterns for medium and large applications written in Flask, specifically chosen to highlight scalability patterns and best practices that you will be able to transfer to your own projects. The class will be divided in two main sections, dedicated to scalability of the code (i.e. how to write large applications with Flask) and scalability of the deployed application (i.e. how to handle large numbers of clients). + +STUDENT HANDOUT +No handouts have been provided yet for this tutorial + +QUESTIONS ABOUT THIS TUTORIAL + Leave class note +Class notes are visible to both instructor(s) and attendees + +Miguel Grinberg 2 weeks, 2 days ago +Hello! + +I'm looking forward to meeting all of you on the 28th! + +In the mean time, I thought I would share some code that we will be using during class, so that you get a chance to install it and familiarize yourself with it. I've created a GitHub repository for this class at: https://github.com/miguelgrinberg/flack. At this point I uploaded an example application that will be the starting point of the class. + +What I would like you to do between now and the 28th is to clone the repository, try the initial version of the application and ask me about anything you don't understand about it. The project is a REST API written in a single-module Flask application and a JavaScript client that uses it. We will obviously concentrate on the server side, but I am happy to address questions regarding any part of the code. If you are all more or less familiar with the Flask portion of application ahead of time we will save some time at class, time that we can use to cover the fun stuff. + +To clone the repository and get the code please use the following commands: + +git clone https://github.com/miguelgrinberg/flack +cd flack +git checkout v0.1 +The v0.1 tag ensures you are synced with the the starting point of this application. In the days before the class I will be pushing additional versions of the application that make up the material I will cover in class, always building upon this first version I'm sharing with you today. + +The README.md file will give you some information on how to set up and run the code. + +Feel free to contact me with any questions you may have. Not sure if you are allowed to post here. If that does not work, you can write to me at miguel.grinberg@gmail.com. + +See you at PyCon! + +Miguel + diff --git a/docs/talks/littlefish_ian_gotts_20170210/index.html b/docs/talks/littlefish_ian_gotts_20170210/index.html new file mode 100644 index 00000000..efe8c7a4 --- /dev/null +++ b/docs/talks/littlefish_ian_gotts_20170210/index.html @@ -0,0 +1,3572 @@ + + + + + + + + + + + + + + + + Littlefish Ian Gotts 20170210 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Littlefish Ian Gotts 20170210

    + +

    Little Fish Meetup - Ian Gotts

    +

    Speaker: Ian Gotts +Talk: The Business of Consulting

    +

    Note: Ian wrote about 10 books and his first one still gets him business today.

    +
      +
    1. Three R's of Ian's talk:
    2. +
    3. R
    4. +
    5. Remember
    6. +
    7. Reveal
    8. +
    +

    Winning Work

    +

    As a consultant you are winning work or performing work and it's hard to balance.

    +
    Winning Rewarding, Profitable Work
    +

    Rewarding - The work takes you where you want to go

    +

    Profitable - You can do it

    +
    Credibility
    +
      +
    • Starts with not having a gmail account
    • +
    • Starts with a real business card
    • +
    • Starts with a decent name
    • +
    • Example: xenogonyx
        +
      • Most of your work comes from word of mouth
      • +
      • If your client's can't remember, they can't tell anyone about you
      • +
      +
    • +
    • Example: IG Partners
        +
      • Says you are consulting and your clients can remember it
      • +
      +
    • +
    +
    Ian's first impression is:
    +
      +
    1. Linkedin
    2. +
    3. 3-5 page website
        +
      • home, services, about, contact us, resources
      • +
      +
    4. +
    5. +

      Some orgs put aol.com, hotmail.com, yahoo.com accounts right in the bin

      +
        +
      • People that have no technical competency?
      • +
      +
    6. +
    7. +

      AOL still makes 917 million a year on dialup accounts, residual income

      +
    8. +
    +
    Build a brand
    +

    Acronym: "Every Consultant Is Awesome"

    +

    These are in order. 1, most important.... 4. least important

    +
      +
    1. Expectation
    2. +
    3. Commonality
    4. +
    5. Intent
    6. +
    7. +

      Ability

      +
    8. +
    9. +

      Expectation - Most important. Are you the consultant they expected?

      +
        +
      • Are you wearing a suit if that is expected
      • +
      • Dress and behave for your audience
      • +
      • Business card like they would expect
      • +
      • "It's about Clues, not Views"
          +
        • You are 'disappointed about the superbowl' but they won... oops
        • +
        • Political views, technology views
        • +
        • let them explain how it all works
        • +
        +
      • +
      +
    10. +
    11. Commonality - Do you have anything in common with them?
        +
      • Kids the same age, musical instrument interest, anything
      • +
      +
    12. +
    13. Intent - Are you there to help them get it done?
        +
      • Are you just there for the day rate
      • +
      • Are you there to make it work
      • +
      • If you can't help them, don't go!!
      • +
      +
    14. +
    15. Ability - Can you do the job?
        +
      • Clearly it's important, but it's below the other three
      • +
      +
    16. +
    +
    Differentiation
    +

    Price is the main difference between two consultants that can do the work. How do you differentiate your work? Why is one person worth $1000 a day and another $1200 a day.

    +

    Anecdote, he worked with a client and they did a perfect job on a $150MM job and all the client could remember a year later was day rate.

    +
      +
    1. Intent: What are you passionate about? What are you good at? Skills?
    2. +
    3. Web Designer: There are so many of those.
        +
      • Align yourself with a product.
          +
        • Example: Be a salesforce consultant, or something.
        • +
        +
      • +
      • You don't know when a client wants to start
          +
        • You don't know when they want to make a business change
        • +
        +
      • +
      • Need to spend time getting up to speed on a product
          +
        • It's like the trains are going by and you gotta jump on the one
        • +
        +
      • +
      +
    4. +
    5. +

      It's great to do something you love, but is it profitable?

      +
        +
      • Is money your primary measure? If so, you have to adapt.
      • +
      • Are you going to build a 40-person business marketing to startups?
      • +
      • Salesforce's limiting factor for growth is business consultants
          +
        • Probably true for microsoft azure, google cloud, aws, rackspace
        • +
        +
      • +
      +
    6. +
    7. +

      How do you make your project URGENT?

      +
        +
      • "You cannot make a consulting project start by sheer will"
      • +
      • Tying yourself to a product
      • +
      • coaching based on their business pipeline
      • +
      • Compliance is another fantastic URGENT incentive.
          +
        • "If we don't do this by december, the FDA fines us 100MM dollars"
        • +
        • We have to start now, just write the check.
        • +
        +
      • +
      +
    8. +
    9. +

      What about IP to differentiate yourself?

      +
        +
      • A business methodology - for example Accenture's 'Lightning' Method
      • +
      • I have methodologies out there right now
      • +
      • Methodology used in your "sales cycle"
          +
        • Way you perform the business cycle with your client
        • +
        +
      • +
      • Example: lawyer -
      • +
      • Methodology can be used to convince a client
          +
        • "Trust me we have the metrics and here are our standard templates"
        • +
        +
      • +
      • How much does your methodology increase your day rate and win rate?
      • +
      +
    10. +
    +
    Profitability
    +

    Make enough to spend your life the way you want to spend it

    +

    A sold consulting firm in silicon valley makes 1 to 1.5 times revenue +An investor wants to make 5x revenue on that form

    +
    The three things discussed below:
    +
      +
    1. Fix bigger problems
    2. +
    3. Project Management
    4. +
    5. Minimize Bench Time
    6. +
    7. +

      Annuity Revenue Streams

      +
    8. +
    9. +

      Sorry, but it's REALLY HARD to build a consultancy to the second stage.

      +
        +
      • Up to 5 is pretty good.
      • +
      • The next stopping point after 3-4 people is twenty.
      • +
      • The bit between 5-20 is REALLY HARD.
      • +
      • Consulting business with 30+ starts to get momentum: marketing, salespeople
      • +
      +
    10. +
    11. +

      Your consultants need something to do between assignments, they aren't just going to develop the business, it isn't what they do.

      +
    12. +
    13. +

      First way is to charge more. How?

      +
        +
      • FIRST THING: Fix bigger problems
      • +
      • Application developers - awesome - ukraine
      • +
      • Configure systems - above applications
      • +
      • Management consultants - above configure (doing business and development)
      • +
      • Run big projects - above management (12 weeks, name the day rate)
          +
        • 3500 a day, 12 weeks, bring in the team, i pay you on top of the team
        • +
        • Ian: i
        • +
        • ROI for that client was 95,000 a day
        • +
        • Ian's biggest project, never got that again
        • +
        • Running workshops, business consulting
        • +
        +
      • +
      • Run big programs - above projects
      • +
      +
    14. +
    15. +

      Writing books - MARKETING GOLD DUST

      +
        +
      • "Common Approach, Common Results" - gets them business today, it was his first one
      • +
      • You can't throw a book away, you can give it away but never get rid of it
      • +
      • Way better than white papers, they've got a spine!
          +
        • jogging vs marathon
        • +
        +
      • +
      • Secret is 80 pages - then you have a spine, and it's a book.
      • +
      • people love books
      • +
      • How do you turn those blogs into something?
      • +
      +
    16. +
    17. +

      Project Management - best way to increase your day rate

      +
        +
      • Scope is the intersection of: time, cost, quality
      • +
      • If you don't have it down at the beginning you've lost the project
          +
        • If you can't get the scope agreed, leave the project!!
        • +
        • This is a real lesson he learned in accenture.
        • +
        +
      • +
      • Scope, timeframe, skillset => all comes back to scope
      • +
      • "What's the case study going to be like when we get you up on stage?"
          +
        • Get them focused on how they deliver the project, so you can focus on how they deliver the project
        • +
        +
      • +
      +
    18. +
    19. +

      Minimize Bench Time

      +
        +
      • Get people around you so you can work together and rely on each other and make sure no one has any bench time
      • +
      • Work for clients who don't screw you over all the time
          +
        • ShipClients - glassdoor for clients, was renamed to "RateClient"
        • +
        • For independent consultants to rate clients on 3 things
            +
          • Too long to get project started
          • +
          • Scope creep
          • +
          • Pay you correctly and on time
          • +
          +
        • +
        • http://clientsfromhell.net
        • +
        +
      • +
      +
    20. +
    21. +

      Annuity Revenue Streams

      +
    22. +
    +

    Writing books isn't it! You don't make any money out of books, they up your day rate. Books also cost very little.

    +

    Silicon Valley is all aboute Annuity Revenue Stream.

    +
      +
    • Could you license some IP?
    • +
    • Could other consultants use your metholodogy?
    • +
    • Can you get 20% of a revenue stream?
    • +
    • Could you build a support service?
    • +
    +
    Be the best you can be
    +

    Always be yourself, unless you can be Batman. Then always be batman.

    +

    Always test the boundary of how much you can charge.

    +

    Day rate: $500, $800, $1000, $2000 - always move it up!!

    +
    Notes
    +

    He says technical skills are worthless, amazing eastern european developers cost $20 an hour, so it's all about access to technical skills.

    +

    Innovative websites don't work. It's why all product websites and carts are the same.

    +
    Questions
    +
      +
    1. How do you be awesome if you don't have a resume that says you worked for the big 5?
        +
      • Ian: It may not be who you worked for but who your clients have been in the past.
      • +
      • Example: The best part of the book is the back cover with quotes by people that love them. Everyone reads the back -- this book must be incredible.
      • +
      +
    2. +
    3. How do you get a client to use your name?
        +
      • A bunch of clients will, some people won't put it through their legal people.
      • +
      • Find people who will bat for you.
      • +
      • If it's a book, it can further their career. Find win-wins.
      • +
      +
    4. +
    5. What about partnerships?
        +
      • Equity partnerships - you need to be super careful. Getting a divorce is hard.
      • +
      • Are you both aligned? Are you both putting the same amount of time on it?
      • +
      • "We'll work it out in the end?"
      • +
      • Very difficult to unwind if it goes wrong.
      • +
      +
    6. +
    7. How much do you spend on marketing when do you stop?
        +
      • As a small business, SEO, facebook marketing, etc. are a huge waste.
      • +
      • BEST: Networking events where you can work together to figure out how to get clients.
      • +
      • BEST: Write a book or a paper, they hang around forever!
      • +
      • BEST: Linkedin relationships, article worth reading on linkedin
      • +
      • Make sure to get writing out there.
      • +
      • What are you really good at? Where are they?
          +
        • Salesforce: all on twitter. Why? No one knows!!
        • +
        • 430 salesforce user groups - marin, sf, etc. Every other week.
        • +
        • half consultants and half clients!! there's an ecosystem
        • +
        • remember: salesforce growth blocker is consultants.
        • +
        +
      • +
      +
    8. +
    9. How do I move up a tier on project size?
        +
      • Confidence to bid for bigger projects
      • +
      • Being there already - take a bigger project with a current client.
      • +
      • Who else do you need around? Project management skills?
      • +
      • The people who are winning those projects, how are they doing it?
          +
        • What does their website look like?
        • +
        • How do I get $2000 a day? Answer: put less on your resume
        • +
        • Behave how people are operating at that level behave
        • +
        +
      • +
      +
    10. +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pyclass_vector_packing_20161114/index.html b/docs/talks/pyclass_vector_packing_20161114/index.html new file mode 100644 index 00000000..1f13e705 --- /dev/null +++ b/docs/talks/pyclass_vector_packing_20161114/index.html @@ -0,0 +1,3226 @@ + + + + + + + + + + + + + + + + Pyclass Vector Packing 20161114 - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Pyclass Vector Packing 20161114

    + +

    Vector Packing: An NP-Hard Problem Made Easy

    +

    Speaker: Conor Frailey, https://github.com/conorfrailey +Turnout: 12 people = 10 students, 1 speaker, and 1 of me.

    +

    The Knapsack Problem - playing tetris for a living, sort of.

    +

    Jupyter Notebook Presentation Online

    +

    Technical Details of Problem:

    +

    See instructor notes, the definitions are very detailed.

    +
      +
    1. Knapsacks are each identical in the context of the problem (volume, weight reqs.)
    2. +
    3. Items have a volume and a weight
        +
      • Weight can be described for items as a percentage a knapsack.
      • +
      • In this description, all knapsacks can contain (1,1) which means (100%, 100%)
      • +
      +
    4. +
    5. You want to use as few knapsacks as possible
    6. +
    7. You group items by partition to find the solution
        +
      • cannot just brute force it, factorial combinations means takes TOO long
      • +
      • e.g. 40 boxes means 40! tries which is not possible to brute force
      • +
      +
    8. +
    +

    Notes

    +
      +
    • partition (math) - distinct groups of your set
    • +
    • bin packing is different - uses three linear dimensions
    • +
    • What is NP-Hard
        +
      1. Is P == NP?
      2. +
      3. P means problems solvable in polynomial time
      4. +
      5. If you can solve this in polynomial time you can solve almost anything in polynomial time
      6. +
      +
    • +
    • If you can form a problem into a convex optimization problem, you are super happy
        +
      • space has to be convex
      • +
      • it keeps on curving up, you want to find the minimum
      • +
      • gradient descent is used in high dimensions to find the minimum
      • +
      • pick a point and go towards zero
      • +
      +
    • +
    • if you have mixed integer program you can do a noncontiguous set of point
        +
      • you can't have a continuous number of cases of beef
          +
        • thus you can't use gradient descent on cases of beef
        • +
        +
      • +
      • list of MIP solvers in the notes
      • +
      • MIP programs are super expensive so we can't use it today
      • +
      • we can use online tool: Arc-flow VPSolver
      • +
      +
    • +
    • VPSolver has a docker image available on docker hub
    • +
    • Hypergraph - a collection of distinct objects and a connection between two or more
        +
      • example: customer orders a subset of the products, a "group". Another customer orders a second subset, different group. They might overlap some products, or even be identical but different customer.
      • +
      • solving with a hypergraph. use the first item as a reference, then start optimizing and reducing symmetry. Hit hotspots where employee has to go to more than one (too many) aisles.
      • +
      +
    • +
    +

    Other Examples

    +
    1. Vacationing on a short vacation, want to do as many things as possible
    +    - Each day has finite time
    +    - You can only walk so much a day
    +    - You can only spend so much money per day (per diem)
    +2. Data centers and their virtual machines
    +3. Refrigerated warehouses
    +    - Fixed height rack, movable height shelves inside racks
    +    - All pallets are standard, except height
    +    - Get the pallets onto the shelves
    +
    + +

    References

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pycon2016_django_docdrivendev/index.html b/docs/talks/pycon2016_django_docdrivendev/index.html new file mode 100644 index 00000000..9ba18bba --- /dev/null +++ b/docs/talks/pycon2016_django_docdrivendev/index.html @@ -0,0 +1,3163 @@ + + + + + + + + + + + + + + + + Pycon2016 Django Docdrivendev - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Pycon2016 Django Docdrivendev

    + +

    Documentation Driven Development in the Django Project

    +

    Using the django project as an example for great ddd.

    +

    What's so good? +* structured properly +* clear and consistent within structure +* covers just about everything +* held to a high standard +* ? +* regarded as a process rather than a product

    +

    Results: +* Django is easier to adopt +* Makes people better django programmers +* lowers support burden +* makes people faster

    +

    Main point of his talk:

    +

    Software is not the only thing that develops, grows, improves.

    +

    Communities of programmers also develops, grows, improves.

    +

    What does documentation mean for the development of communities and products?

    +

    Writer keeps riffing on the same stuff. His words have depth but not immediately actionable.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pycon2016_grinberg_flaskprod/index.html b/docs/talks/pycon2016_grinberg_flaskprod/index.html new file mode 100644 index 00000000..86388a01 --- /dev/null +++ b/docs/talks/pycon2016_grinberg_flaskprod/index.html @@ -0,0 +1,3813 @@ + + + + + + + + + + + + + + + + Pycon2016 Grinberg Flaskprod - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Pycon2016 Grinberg Flaskprod

    + +

    Production Ready Flask App - Part I

    +

    Notes from Miguel Grinberg's talk on making a production flask app.

    +

    Speaker: Miguel Grinberg

    +

    Event: PyCon 2016 - 20160528 0900 PST

    +

    Presentation URL: Miguel will put a URL in the github readme and tweet the link.

    +

    1. Move utility functions to utils.py (tag: v0.2)

    +

    url_for, timestamp functions.

    +

    2. Refactor database models. (tag: v0.3)

    +

    Avoid cyclic dependency of importing db from controller then importing model from models.py

    +

    Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded "from flack import db".

    +

    3. Create an Application Package (tag: v0.4) - Use Flask-Script

    +

    A newer option exists over Flask-Script but is not yet production ready.

    +

    Flask-Script is available now: +https://flask-script.readthedocs.io/en/latest/

    +

    See git diff v0.3 v0.4 between these two tags to understand necessary changes.

    +

    4. Refactoring API Authentication (tag: v0.5) -

    +

    Moved auth stuff to auth.py. There were three auth functions finally imported.

    +

    Again see git diff v0.4 v0.5 for details.

    +

    5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure.

    +

    To get the overview, checkout this tag and manage.py. Look at file structure.

    +

    Now we are in a django style construction. tests folder exists alongside flack folder.

    +

    6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py.

    +

    Add a config.py. This is pretty hairy even in django.

    +

    People solve configuration in different ways.

    +

    I have a pretty good django dev.cfg/prod.cfg pattern that I would use here.

    +

    7. Create an API Blueprint - separate the api.

    +

    Create: flack/api.py. Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py.

    +

    8. Create Stats package.

    +

    See git diff v0.8 v0.9

    +

    9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app.

    +
    +
    +
    +

    Sometimes it is desirable to work with more than one application +Best Example: Unit tests that need applications with different configurations.

    +
    +
    +
    +

    SPECIAL NOTE:

    +

    Having app blueprints allows you to have a really elegant test setup and teardown.

    +

    Howto get the Blueprint working (see git diff v0.9 v.10 for exact code)

    +

    We need to get rid of app because it will exist outside the context of the controller.

    +

    Now we can no longer reference app.
    +We must refactor app.config and other references to app. +That means no app.debug.

    +

    To achieve this we can use a Blueprint. +Use the current_app context variable to access application.

    +

    Put application factory function in init.py, see create_app function here.

    +

    To create an app you now call create_app, pass an application name, and get the app.

    +

    SQLAlchemy needs the models in init.py because it introspects on the app. +You can miss this and maybe the models get imported elsewhere but that is sloppy.

    +

    10. Creating an API Package (tag: v0.11) - Turn api.py into a package.

    +

    This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users.

    +

    tokens, messages, users become modules inside of the api package.

    +

    Part II - Scaling Flask for Production.

    +

    Notes from Miguel Grinberg's talk on making a production flask app.

    +

    PyCon 2016 - 20160528 0900 PST

    +

    Presentation URL: Miguel will put a URL in the github readme and tweet the link.

    +

    Scaling Web Servers

    +

    Problem - one request at a time. Not great.

    +

    Multiple Threads

    +

    Limited use of multiple threads because of GIL. Not really great.

    +

    Multiple processes

    +

    Obviously multiple apps sounds nice. Each process has its own set of things.

    +

    What about SQLAlchemy?

    +

    Green threads / coroutines - asyncio, gevent, eventlet.

    +

    Flask doesn't support asyncio.

    +

    Flask does support gevent, eventlet.

    +

    IO and standard library threading functions are incompatible.

    +

    How about manually triggering a switch? - sleep function to take a break and let other threads have a turn.

    +

    Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch.

    +

    Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice.

    +

    Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).

    +

    Using Production Web Servers (tag: v0.12)

    +
    gunicorn
    +

    Limited load balancing - Why limited? I will have to look this up.

    +

    Written in Python - robust but not lightning fast

    +

    Supports multiple processes, and eventlet or gevent green threads.

    +
    uwsgi
    +
    nginx
    +

    Written in C.

    +

    Ideal for serving static files in production. You expose the static file in the nginx config.

    +

    Bottlenecks: I/O Bound and CPU Bound

    +
    I/O Bottlenecks
    +

    Flack example: scraping links included in posts

    +

    Solution: concurrent request handlers through multiple threads, processes, or green threads.

    +

    Make I/O heavy requests asynchronous.

    +
    CPU Bottlenecks
    +

    Flack example: rendering posts from markdown to HTML

    +

    Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.

    +

    Asynchronous HTTP Requests (tag: v0.13)

    +
      +
    1. Request starts background work, gives a status 202.
    2. +
    3. Goes back to listening requests.
    4. +
    5. Location header has a status URL where the client can ask for status for the asynchronous task.
    6. +
    7. Request to status URL returns 202 while the request is still in progress.
    8. +
    9. When complete, (see presentation for details)
    10. +
    +

    There is a decorator for this in flack, migue's app.... @async decorator.

    +

    That's all that is necessary!!! This is almost too easy.

    +

    If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation.

    +

    note that request.environ has environmental information to build a request object.

    +

    This way miguel can build his own request object.

    +

    Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request.

    +

    We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested.

    +

    Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.

    +

    Celery Workers (tag: v0.14)

    +

    There's a wrapper in manage.py. Celery is integrated into the previous async section.

    +

    For quick setup redis works with Celery.

    +

    Celery needs to be available in init.py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.

    +

    Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens.

    +

    This "server-push" websocket model will reduce load, removing all redundant quests.

    +

    The previous version used 2 requests per second per client just to stay up to date.

    +

    Options: +1. Streaming +2. Long-polling +3. WebSocket +4. Socket.IO (long-polling + WebSocket)

    +
    Streaming
    +

    One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask

    +
    Long polling
    +

    client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.

    +
    WebSocket
    +

    HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.

    +
    SocketIO
    +

    written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client.

    +

    Type 1:

    +

    Python client: use socketio.emit class in a push_model method. See slides. +Javascript server: socketio node.js service

    +

    Type 2:

    +

    Python Server: @socketio.on() decorator +Javascript client: socket.emit(). See slides.

    +

    Even more Socket.IO. We can now only use gevent or eventlet.

    +

    See the events.py module git diff v0.14 v0.15, added to manage events.

    +

    I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful.

    +

    This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed.

    +

    Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source.

    +

    Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code.

    +

    manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in.

    +

    Also see tests. socketio has its own test client.

    +

    Finally nginx has requirements for load balancing. Nginx option "sticky sessions"

    +

    Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.

    +

    Flask-SocketIO

    +
      +
    • Miguel's project
    • +
    • Pure python, translation of the Socket.IO node project for flask.
    • +
    +
    Questions / Notes
    +
      +
    • Flask has a Python profiler.
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pycon2016_lasercutter_3dprinter_python/index.html b/docs/talks/pycon2016_lasercutter_3dprinter_python/index.html new file mode 100644 index 00000000..930b27cf --- /dev/null +++ b/docs/talks/pycon2016_lasercutter_3dprinter_python/index.html @@ -0,0 +1,3344 @@ + + + + + + + + + + + + + + + + Pycon2016 Lasercutter 3Dprinter Python - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Pycon2016 Lasercutter 3Dprinter Python

    + +

    Laser Cutters and 3D Printers

    +

    How to use Python to build stuff to be laser cut or 3d printed. +Talk: https://github.com/vishnubob/pycon2016 +Speaker: Giles Hall

    +
    Additional Resources:
    +
      +
    • https://github.com/vishnubob/pyscad
    • +
    • https://github.com/vishnubob/rockit
    • +
    • https://github.com/vishnubob/snowflake
    • +
    +

    Laser Cutters

    +
    Process
    +
      +
    1. Select material (wood, plastic, etc.)
    2. +
    3. Size
    4. +
    5. Build design (vector graphics allows scaling without losing fidelity eg svg)
        +
      • Determine which lines are cut
      • +
      • Determine which lines are etched
      • +
      +
    6. +
    7. Lay out material on laser bed
    8. +
    9. Upload your design and begin to cut.
    10. +
    +

    The individual processes above are defined by the particular laser cutter and its software.

    +

    Can use PDF, EPS, etc. But preferred is SVG:

    +

    Path is a great way to specify a zigzaggy line in your SVG.

    +
    So how do we use Python to generate our SVG for our laser cut image?
    +

    We'll cut 2D shapes and assemble them into a 3D shape.

    +

    His cube is a really great sample of using one huge single cut to make six interlocking pieces.

    +

    This cube was cut with wood and you can see the burns on the edges of the wood from the laser.

    +

    I could easily modify this to build the cups I want to make for tea.

    +

    Really just need to know the guts of the SVG path specification, the N commands and L commands that let you specify a complex set of line segments.

    +

    Then we get more complex by etching onto the sides of the teacups. He uses fermat's spiral, but I could do anything or free draw something, or get a raster/pixelart off the web and convert to svg circles.

    +

    Maybe skyrim mug

    +

    3D Printers

    +

    Most common are fuse deposition models.

    +

    Cut 3d object into 2d slices and build a model up.

    +

    Extruders extrude plastic to do this. Uses XY plane for each layer, Z advances to the next 2D slice.

    +

    Generate STL file +Produce GCODE

    +

    STL is very hard to generate by hand. Not great way to think about 3d designs (mesh of triangles).

    +
    There must be a better way to design!!
    +

    Most 3D modelling tools are expensive, difficult, or run in windows or all three.

    +

    OpenSCAD -> +* open source, +* uses constructive solid geomoetry.

    +

    Drinking glass can be constructed with two cylinders. +1. Describe outside surface. +2. Describe negative space inside, slightly smaller radius, slightly offset from bottom.

    +
    # very easy to build a drinking glass, nested cylinders
    +difference()
    +{
    +  cylinder(r=20, h=80);
    +  translate([0,0,1]])
    +  {
    +    cylinder(r=18, h=90);
    +  }
    +}
    +
    + +
    We can very easily generate OpenSCAD from Python using PythonSCAD!
    +

    How about a Flower Pot?

    +

    It's a cone but we call that a cylinder in scad with 2 different radiuses on each end.

    +

    Lip at the top.

    +

    A few different Python Libraries: PythonSCAD written by the Speaker.

    +

    You can accomplish with the other alternative libraries but we use his here.

    +
    """
    +PythonSCAD Sample of a flowerpot.
    +"""
    +class FlowerPot(SCAD_Object):
    +    radius_ratio = 0.6 # from flowerpots in his house
    +    collar_height_raidus = 0.2
    +    height = inch2mm(2.5)
    +    thickness
    +    # ...
    +    # theres more but he moved on
    +
    +
    +def scad(self):
    +    outer_pot = Cylinder(r1=self.bottom_radius, r2=self.top_radius)
    +    # ...
    +    # theres more but he moved on
    +
    +
    +# this is all the code!
    +
    + +
    Other things to check out in PythonSCAD
    +

    Translate math from "Modeling a Snow Flake...." research document into Python.

    +

    They used this to make snowflakes 3D printed.

    +

    The math used a complex automata and was computationally expensive - done in the cloud. +The program provides a raster of the automata cells and then is converted to SVG. +Two SVGs are merged, one of the densest bands of automata another of the outline. +Then sent to the 3D printer (laser cutter?).

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pycon2016_sqlite_tricks/index.html b/docs/talks/pycon2016_sqlite_tricks/index.html new file mode 100644 index 00000000..4ce047f7 --- /dev/null +++ b/docs/talks/pycon2016_sqlite_tricks/index.html @@ -0,0 +1,3224 @@ + + + + + + + + + + + + + + + + Pycon2016 Sqlite Tricks - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Why SQLite?

    +

    Speaker: Dave Sawyer +Talk: Pycon 2016 Monday May 30 - SQLite gotchas and gimmes. +Talk URL:

    +
      +
    • Search/Sort Efficiently
    • +
    • transactions with rollback
    • +
    • safe format
    • +
    • handle large datasets. 32/64 bit agnostic
    • +
    • little/big endian agnostic
    • +
    • concurrency.
    • +
    +

    Gotchas!

    +
      +
    • Remember to commit your db changes (duh) => try/finally
    • +
    • SQLite autocommits by default. Probably want to turn this off to control your commits.
    • +
    • Close your cursor because writers have to wait for readers etc.
    • +
    +

    Gimmees!

    +
      +
    • +

      SQLite has a built in context manager! Use with statement! + python + with connection: + connection.execute(MY_SQLITE_STATEMENT, (data,))

      +

      ``` python

      +

      even better, generate the cursor in the with context.

      +

      with closing(self.connection.cursor()) as cursor: + cursor.execute(MY_SQLITE_STATEMENT, (data,)) +```

      +
    • +
    • +

      See the code from the talk for his class. It's very compact and general.

      +
    • +
    • WAL mode - SQLite 3.7. Write Ahead Logging. Lets you read and write at the same time. It's like a delta and the writers write then the readers use the delta to read.
    • +
    • sqlite3.version = python module version
    • +
    • sqlite3.sqlite_version = gives sqlite installation version
    • +
    • sqlite3 :memory: -- in-memory model and very fast obviously. No writes to disk.
    • +
    +
    SQLite isolation levels: deferred, immediate, exclusive.
    +

    Lets just implement deferred. The other two are easy and not totally necessary.

    +
    Questions:
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/pycon2016_typeannotations/index.html b/docs/talks/pycon2016_typeannotations/index.html new file mode 100644 index 00000000..230e52ff --- /dev/null +++ b/docs/talks/pycon2016_typeannotations/index.html @@ -0,0 +1,3349 @@ + + + + + + + + + + + + + + + + Pycon2016 Typeannotations - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + + + + + +
    +
    + + + + + + + + + +

    Pycon2016 Typeannotations

    + +

    Why use static typing? (Dropbox talk)

    +

    Date: 2016-05-29 +Talk: PyCon 2016 +Who: Guido van Rossum et al, Dropbox Inc. +Spreadsheet URL:

    +

    At dropbox, 40% of time was used on reading/understanding code (2015 survey)

    +

    Static typing helps understanding of code.

    +

    Problem:

    +

    Finding a type of an input can be impossible. Worst case: recursively hunt backwards in the codebase until you enumerate everything constructing your input. Massive search tree required.

    +

    More complex problem: type can even vary, maybe a method is overloaded (eek). Computer science says this is undecidable.

    +

    Another problem:

    +

    Over time, expectations for the code change and comments that were true become lies.

    +

    Now we have to go back to the original problem.

    +

    "Explicit is better than implicit." -> "Checked is better than unchecked."

    +

    Lets make our types explicit have a computer check our types.

    +

    New Strategy: Make types explicit and checked.

    +
      +
    1. Write types at def and where not obvious.
    2. +
    3. Run mypy to check types, routinely like your tests
    4. +
    5. Read code, learning types i easy.
    6. +
    +

    A definition for "static typing"

    +

    Static Typing - The expectation the author had for the piece of code when they were writing it.

    +
    Using Type Hints in Python 2 (Static Typing)
    +

    Simply use a comment.

    +
    def function(a, b):
    +    # a: int, b: int => int
    +
    + +

    Using Type Hints in Python 3 (Static Typing)

    +

    Use mypy as a checker for type hints in python 3.

    +

    History of static typing (Guido)

    +

    Guido has been considering this over a decade. The technology really has come around in the last six months.

    +
    2004-2005 - Artima blog posts:
    +
      +
    1. https://www.artima.com/weblogs/viewpost.jsp?thread=85551
    2. +
    3. +
    +
    2006 - PEP 3107 Compromise, 'function annotations'
    +
      +
    1. https://www.python.org/dev/peps/pep-3107/
    2. +
    3. Type annotations do nothing but are introspectable.
    4. +
    +
    2012 - Jukka also started working with this, stsarted mypy as an "experimental python variant" - statically typed python.
    +

    Used angular brackets because other languages do it in this way.

    +

    Guido convinced him to use pep3107 and square brackets so mypy is completely compatible with Python

    +
    2014 - Bob Ippolito - EuroPython Talk (see youtube) - "What Can Python Learn from Haskell"
    +

    His 3rd idea was to use mypy b/c static typing.

    +

    https://www.youtube.com/watch?v=pJOmlFf5Je4

    +

    Discussion about PEP484 started right after PyCon 2014. +https://www.python.org/dev/peps/pep-0484/

    +

    PyCharm and Google's pytype project started adopting this standard.

    +
    Everything is optional and gradual.
    +

    You can have annotations in one place and none elsewhere.

    +

    Python ignores annotations. Except when you set annotations

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/trigger-point-massage/index.html b/docs/talks/trigger-point-massage/index.html new file mode 100644 index 00000000..0c1da51e --- /dev/null +++ b/docs/talks/trigger-point-massage/index.html @@ -0,0 +1,3241 @@ + + + + + + + + + + + + + + + + Trigger Point Massage - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    + +
    +
    + + + +
    +
    + + + + + + + + + +

    Lacrosse Ball Myofascial Release

    +

    Speaker: ? +Date: 2019-09-10

    +
      +
    • typically 40-60 seconds for any body part
    • +
    • 2 rounds if you have time
    • +
    • quads, hamstrings, glutes, back, everything
    • +
    • the second round you really rolling pin it around
    • +
    • do this type of stuff before a workout to open up your fascia and allow muscles to work through greater range of motion and minimize injury
    • +
    • relax as much as you can, if you tighten it up the ball is tougher to get in there
    • +
    • do every single part of the muscle
    • +
    • this is different than stretching, surrounding every muscle is fascia, also attaches muscle to skin and other muscles
    • +
    • ball breaks things up in there, if you are cringing a lot drink a lot of water - "releasing a bunch of toxins and broken up stagnant toxins into your bloodstream"
    • +
    • never have any alcohol before/after a massage
    • +
    • we tend to do the same movements over and over, sitting, walking, whatever... lots of stagnant tissue
    • +
    • use straight up PVC pipe as a foam roller. Foam rollers get soft over time and won't work
    • +
    • try not to use the muscles you are releasing to apply force
    • +
    • what's the best exercise? foam rolling, decreases sore timing, keeps you from getting injured
    • +
    • whenever i fly i bring a lacrosse ball and do it in the airport
    • +
    +

    Sit on the ball on the ground - butt muscles

    +
      +
    • get as close to the bone without being on the bone, that will hurt
    • +
    • hip is a ball and socket joint, sit on the ball and trace the socket
    • +
    +

    Sit on the ball on the chair

    +
      +
    • put under hamstring
    • +
    +

    against the wall - spine-shoulderblade, lats

    +
      +
    • do sort of a wall sit
    • +
    • put ball between shoulderblade and spine against the wall, lean into it
    • +
    • explore around your back
    • +
    • lats tend to get really tight, definitely try these
    • +
    +

    extensors

    +
      +
    • trace from your elbow out to your wrist
    • +
    • outside of arm against wall while standing
    • +
    • use inside of arm on the table, push it down with other arm
    • +
    +

    Feet

    +
      +
    • stand and apply force against bottom of foot... i guess just try everywhere... from right in front of your heel
    • +
    • pull your toes back and roll forward on the foot towards the toes
    • +
    • "reconnect the neuromuscular connections"
    • +
    • do you notice crunchies in your feet? "fascia starts to calcify... on a cellular level" - lol wtf sure why not
    • +
    +

    Calf

    +
      +
    • ball on the floor, calf on the ball
    • +
    • most people don't realize how tight they are until they do it
    • +
    • pick your hips up a bit to float over, good to use a block to raise the hips on this one
    • +
    • relax your ankle as you roll into it, don't flex it
    • +
    +

    Foam Rollers Abbreviated Version

    +
      +
    • For IT band definitely use this instead of the ball
    • +
    • "t something" like a rolling pin, about 2 inches diameter, good for calves and easier to get in there
    • +
    • some tool i missed for something something
    • +
    • try softball instead of lacrosse ball, it's bigger, maybe a bit more manageable - good for hips, calves
    • +
    • i don't really like the knobs on the foam roller (trent: i think tons of knobs like a texture). idea is that they're for pressure points, but it is hard to pinpoint pressure points. consistently firm foam roller is better
    • +
    +

    Scalenes are some of the tightest muscles

    +
      +
    • do it yourself with your fingers, push down and do normal 40-60 sec, 2 sessions
    • +
    • i find right on the inside of my collarbone, then tilt my head back
    • +
    • so pin it then stretch back (tilt head back)
    • +
    • might feel ticklish, neck, nausea, address it carefully
    • +
    • scalenes go in a lot of different directions, so feel those out
    • +
    • text neck is horrible (looking down)
    • +
    +

    Cheek muscles, also use your fingers

    +
      +
    • relax your face before you start
    • +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/docs/talks/vim-meetup-020416.txt b/docs/talks/vim-meetup-020416.txt new file mode 100644 index 00000000..956afbdd --- /dev/null +++ b/docs/talks/vim-meetup-020416.txt @@ -0,0 +1,19 @@ + +## We are reviewing: https://github.com/faun/dotfiles/blob/master/vimrc + +faun (do this?): +set nocompatible "makes vim not stupid" + + +faun's favorite thing in vimrc: + runs tests, deeply linked to tmux. + +faun's vimrc +Look at how he maps his f3 key to remove trailing whitespace in the whole file + + +vim modeline +modelines allow you to set variables specific to a file. By default, the first and last five lines are read by vim for variable settings. For example, if you put the following in the last line of a C program, you would get a textwidth of 60 chars when editing that file: +/* vim: tw=60 ts=2: */ +The modelines variable sets the number of lines (at the beginning and end of each file) vim checks for initializations. +check out in spf13 diff --git a/index.html b/index.html new file mode 100644 index 00000000..ac1f7622 --- /dev/null +++ b/index.html @@ -0,0 +1,3164 @@ + + + + + + + + + + + + + + + + outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Outlines

    +

    This project collects detailed notes as aggregate outlines.

    +

    Please send pull requests if you notice errors.

    +

    Purpose

    +
      +
    1. Store information in a way that can be easily referenced or updated.
    2. +
    3. Have a destination for information curated during deep projects, especially after they end.
    4. +
    +

    Locations

    +
      +
    1. praxes - praxis/process oriented information
    2. +
    3. reference - primarly aggregated from another source
    4. +
    5. monographs - my original, observations from data and experiences
    6. +
    7. talks - notes from speakers and events
    8. +
    9. digests - for longer works, if it is worth reading, it is worth taking notes on
    10. +
    11. external - copies of external outlines worth keeping handy
    12. +
    13. logs - freeform summaries, syntheses, etc
    14. +
    +

    Github Pages

    +
      +
    • Portray is configured in pyproject.toml
    • +
    • requiring the project to have a docs directory for now (maybe there is some hack to get rid of the docs/ top level directory.
    • +
    +

    Rebuilding

    +
      +
    • Rebuild github pages in the ~/code/outlines project root using virtualenv: ~/virtualenvs/portray.
    • +
    • publish with the command: portray on_github_pages
    • +
    • Rebuild the portray virtualenv by simply installing portray and mkdocs-awesome-pages-plugin.
    • +
    +

    The github pages are rendered with portray and mkdocs-awesome-pages-plugin

    + + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/api/index.html b/reference/portray/api/index.html new file mode 100644 index 00000000..fd34bbeb --- /dev/null +++ b/reference/portray/api/index.html @@ -0,0 +1,3954 @@ + + + + + + + + + + + + + + + + API - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.api

    +

    This module defines the programmatic API that can be used to interact with portray

    +

    to generate and view documentation.

    +

    If you want to extend portray or use it directly from within Python - this is the place +to start.

    +
    +View Source +
    """This module defines the programmatic API that can be used to interact with `portray`
    +
    +   to generate and view documentation.
    +
    +   If you want to extend `portray` or use it directly from within Python - this is the place
    +
    +   to start.
    +
    +"""
    +
    +import os
    +
    +import webbrowser
    +
    +from typing import Dict, Union
    +
    +import mkdocs.commands.gh_deploy
    +
    +from livereload import Server
    +
    +from portray import config, logo, render
    +
    +def as_html(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    output_dir: str = "site",
    +
    +    overwrite: bool = False,
    +
    +    modules: list = None,  # type: ignore
    +
    +) -> None:
    +
    +    """Produces HTML documentation for a Python project placing it into output_dir.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml)
    +
    +      formatted config file you wish to use.
    +
    +    - *output_dir*: The directory to place the generated HTML into.
    +
    +    - *overwrite*: If set to `True` any existing documentation output will be removed
    +
    +      before generating new documentation. Otherwise, if documentation exists in the
    +
    +      specified `output_dir` the command will fail with a `DocumentationAlreadyExists`
    +
    +      exception.
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    render.documentation(
    +
    +        project_configuration(directory, config_file, modules=modules, output_dir=output_dir),
    +
    +        overwrite=overwrite,
    +
    +    )
    +
    +    print(logo.ascii_art)
    +
    +    print(f"Documentation successfully generated into `{os.path.abspath(output_dir)}` !")
    +
    +def in_browser(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    port: int = None,  # type: ignore
    +
    +    host: str = None,  # type: ignore
    +
    +    modules: list = None,  # type: ignore
    +
    +    reload: bool = False,
    +
    +) -> None:
    +
    +    """Opens your default webbrowser pointing to a locally started development webserver enabling
    +
    +    you to browse documentation locally
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *port*: The port to expose your documentation on (defaults to: `8000`)
    +
    +    - *host*: The host to expose your documentation on (defaults to `"127.0.0.1"`)
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    - *reload*: If true the server will live load any changes
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    server(
    +
    +        directory=directory,
    +
    +        config_file=config_file,
    +
    +        open_browser=True,
    +
    +        port=port,
    +
    +        host=host,
    +
    +        modules=modules,
    +
    +        reload=reload,
    +
    +    )
    +
    +def server(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    open_browser: bool = False,
    +
    +    port: int = None,  # type: ignore
    +
    +    host: str = None,  # type: ignore
    +
    +    modules: list = None,  # type: ignore
    +
    +    reload: bool = False,
    +
    +) -> None:
    +
    +    """Runs a development webserver enabling you to browse documentation locally.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *open_browser*: If true a browser will be opened pointing at the documentation server
    +
    +    - *port*: The port to expose your documentation on (defaults to: `8000`)
    +
    +    - *host*: The host to expose your documentation on (defaults to `"127.0.0.1"`)
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    - *reload*: If true the server will live load any changes
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    project_config = project_configuration(directory, config_file, modules=modules)
    +
    +    host = host or project_config["host"]
    +
    +    port = port or project_config["port"]
    +
    +    with render.documentation_in_temp_folder(project_config) as (sources_folder, docs_folder):
    +
    +        print(logo.ascii_art)
    +
    +        live_server = Server()
    +
    +        if reload:
    +
    +            def reloader():  # pragma: no cover
    +
    +                sources_old = sources_folder + ".old"
    +
    +                docs_old = docs_folder + ".old"
    +
    +                with render.documentation_in_temp_folder(project_config) as (sources_new, docs_new):
    +
    +                    # cause as little churn as possible to the server watchers
    +
    +                    os.rename(sources_folder, sources_old)
    +
    +                    os.rename(sources_new, sources_folder)
    +
    +                    os.rename(sources_old, sources_new)
    +
    +                    os.rename(docs_folder, docs_old)
    +
    +                    os.rename(docs_new, docs_folder)
    +
    +                    os.rename(docs_old, docs_new)
    +
    +            # all directories that feed documentation_in_temp_folder
    +
    +            watch_dirs = set(
    +
    +                (
    +
    +                    project_config["directory"],
    +
    +                    project_config["docs_dir"],
    +
    +                    *project_config["extra_dirs"],
    +
    +                )
    +
    +            )
    +
    +            if "docs_dir" in project_config["mkdocs"]:
    +
    +                watch_dirs.add(project_config["mkdocs"]["docs_dir"])
    +
    +            if "site_dir" in project_config["mkdocs"]:
    +
    +                watch_dirs.add(project_config["mkdocs"]["site_dir"])
    +
    +            for watch_dir in watch_dirs.difference(set((sources_folder, docs_folder))):
    +
    +                live_server.watch(watch_dir, reloader)
    +
    +        if open_browser:
    +
    +            webbrowser.open_new(f"http://{host}:{port}")
    +
    +        live_server.serve(root=docs_folder, host=host, port=port, restart_delay=0)
    +
    +def project_configuration(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    modules: list = None,  # type: ignore
    +
    +    output_dir: str = None,  # type: ignore
    +
    +) -> dict:
    +
    +    """Returns the configuration associated with a project.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *modules*: One or more modules to include in the configuration for reference rendering
    +
    +    """
    +
    +    overrides: Dict[str, Union[str, list]] = {}
    +
    +    if modules:
    +
    +        overrides["modules"] = modules
    +
    +    if output_dir:
    +
    +        overrides["output_dir"] = output_dir
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    return config.project(directory=directory, config_file=config_file, **overrides)
    +
    +def on_github_pages(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    message: str = None,  # type: ignore
    +
    +    force: bool = False,
    +
    +    ignore_version: bool = False,
    +
    +    modules: list = None,  # type: ignore
    +
    +) -> None:
    +
    +    """Regenerates and deploys the documentation to GitHub pages.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *message*: The commit message to use when uploading your documentation.
    +
    +    - *force*: Force the push to the repository.
    +
    +    - *ignore_version*: Ignore check that build is not being deployed with an old version.
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    project_config = project_configuration(directory, config_file, modules)
    +
    +    with render.documentation_in_temp_folder(project_config) as (_, site_dir):
    +
    +        project_config["mkdocs"]["site_dir"] = site_dir
    +
    +        conf = render._mkdocs_config(project_config["mkdocs"])
    +
    +        conf.config_file_path = directory
    +
    +        mkdocs.commands.gh_deploy.gh_deploy(
    +
    +            conf, message=message, force=force, ignore_version=ignore_version
    +
    +        )
    +
    +        print(logo.ascii_art)
    +
    +        print("Documentation successfully generated and pushed!")
    +
    + +
    +

    Functions

    +

    as_html

    +
    def as_html(
    +    directory: str = '',
    +    config_file: str = 'pyproject.toml',
    +    output_dir: str = 'site',
    +    overwrite: bool = False,
    +    modules: list = None
    +) -> None
    +
    + +

    Produces HTML documentation for a Python project placing it into output_dir.

    +
      +
    • directory: The root folder of your project.
    • +
    • config_file: The TOML + formatted config file you wish to use.
    • +
    • output_dir: The directory to place the generated HTML into.
    • +
    • overwrite: If set to True any existing documentation output will be removed + before generating new documentation. Otherwise, if documentation exists in the + specified output_dir the command will fail with a DocumentationAlreadyExists + exception.
    • +
    • modules: One or more modules to render reference documentation for
    • +
    +
    +View Source +
    def as_html(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    output_dir: str = "site",
    +
    +    overwrite: bool = False,
    +
    +    modules: list = None,  # type: ignore
    +
    +) -> None:
    +
    +    """Produces HTML documentation for a Python project placing it into output_dir.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml)
    +
    +      formatted config file you wish to use.
    +
    +    - *output_dir*: The directory to place the generated HTML into.
    +
    +    - *overwrite*: If set to `True` any existing documentation output will be removed
    +
    +      before generating new documentation. Otherwise, if documentation exists in the
    +
    +      specified `output_dir` the command will fail with a `DocumentationAlreadyExists`
    +
    +      exception.
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    render.documentation(
    +
    +        project_configuration(directory, config_file, modules=modules, output_dir=output_dir),
    +
    +        overwrite=overwrite,
    +
    +    )
    +
    +    print(logo.ascii_art)
    +
    +    print(f"Documentation successfully generated into `{os.path.abspath(output_dir)}` !")
    +
    + +
    +

    in_browser

    +
    def in_browser(
    +    directory: str = '',
    +    config_file: str = 'pyproject.toml',
    +    port: int = None,
    +    host: str = None,
    +    modules: list = None,
    +    reload: bool = False
    +) -> None
    +
    + +

    Opens your default webbrowser pointing to a locally started development webserver enabling

    +

    you to browse documentation locally

    +
      +
    • directory: The root folder of your project.
    • +
    • config_file: The TOML formatted + config file you wish to use.
    • +
    • port: The port to expose your documentation on (defaults to: 8000)
    • +
    • host: The host to expose your documentation on (defaults to "127.0.0.1")
    • +
    • modules: One or more modules to render reference documentation for
    • +
    • reload: If true the server will live load any changes
    • +
    +
    +View Source +
    def in_browser(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    port: int = None,  # type: ignore
    +
    +    host: str = None,  # type: ignore
    +
    +    modules: list = None,  # type: ignore
    +
    +    reload: bool = False,
    +
    +) -> None:
    +
    +    """Opens your default webbrowser pointing to a locally started development webserver enabling
    +
    +    you to browse documentation locally
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *port*: The port to expose your documentation on (defaults to: `8000`)
    +
    +    - *host*: The host to expose your documentation on (defaults to `"127.0.0.1"`)
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    - *reload*: If true the server will live load any changes
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    server(
    +
    +        directory=directory,
    +
    +        config_file=config_file,
    +
    +        open_browser=True,
    +
    +        port=port,
    +
    +        host=host,
    +
    +        modules=modules,
    +
    +        reload=reload,
    +
    +    )
    +
    + +
    +

    on_github_pages

    +
    def on_github_pages(
    +    directory: str = '',
    +    config_file: str = 'pyproject.toml',
    +    message: str = None,
    +    force: bool = False,
    +    ignore_version: bool = False,
    +    modules: list = None
    +) -> None
    +
    + +

    Regenerates and deploys the documentation to GitHub pages.

    +
      +
    • directory: The root folder of your project.
    • +
    • config_file: The TOML formatted + config file you wish to use.
    • +
    • message: The commit message to use when uploading your documentation.
    • +
    • force: Force the push to the repository.
    • +
    • ignore_version: Ignore check that build is not being deployed with an old version.
    • +
    • modules: One or more modules to render reference documentation for
    • +
    +
    +View Source +
    def on_github_pages(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    message: str = None,  # type: ignore
    +
    +    force: bool = False,
    +
    +    ignore_version: bool = False,
    +
    +    modules: list = None,  # type: ignore
    +
    +) -> None:
    +
    +    """Regenerates and deploys the documentation to GitHub pages.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *message*: The commit message to use when uploading your documentation.
    +
    +    - *force*: Force the push to the repository.
    +
    +    - *ignore_version*: Ignore check that build is not being deployed with an old version.
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    project_config = project_configuration(directory, config_file, modules)
    +
    +    with render.documentation_in_temp_folder(project_config) as (_, site_dir):
    +
    +        project_config["mkdocs"]["site_dir"] = site_dir
    +
    +        conf = render._mkdocs_config(project_config["mkdocs"])
    +
    +        conf.config_file_path = directory
    +
    +        mkdocs.commands.gh_deploy.gh_deploy(
    +
    +            conf, message=message, force=force, ignore_version=ignore_version
    +
    +        )
    +
    +        print(logo.ascii_art)
    +
    +        print("Documentation successfully generated and pushed!")
    +
    + +
    +

    project_configuration

    +
    def project_configuration(
    +    directory: str = '',
    +    config_file: str = 'pyproject.toml',
    +    modules: list = None,
    +    output_dir: str = None
    +) -> dict
    +
    + +

    Returns the configuration associated with a project.

    +
      +
    • directory: The root folder of your project.
    • +
    • config_file: The TOML formatted + config file you wish to use.
    • +
    • modules: One or more modules to include in the configuration for reference rendering
    • +
    +
    +View Source +
    def project_configuration(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    modules: list = None,  # type: ignore
    +
    +    output_dir: str = None,  # type: ignore
    +
    +) -> dict:
    +
    +    """Returns the configuration associated with a project.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *modules*: One or more modules to include in the configuration for reference rendering
    +
    +    """
    +
    +    overrides: Dict[str, Union[str, list]] = {}
    +
    +    if modules:
    +
    +        overrides["modules"] = modules
    +
    +    if output_dir:
    +
    +        overrides["output_dir"] = output_dir
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    return config.project(directory=directory, config_file=config_file, **overrides)
    +
    + +
    +

    server

    +
    def server(
    +    directory: str = '',
    +    config_file: str = 'pyproject.toml',
    +    open_browser: bool = False,
    +    port: int = None,
    +    host: str = None,
    +    modules: list = None,
    +    reload: bool = False
    +) -> None
    +
    + +

    Runs a development webserver enabling you to browse documentation locally.

    +
      +
    • directory: The root folder of your project.
    • +
    • config_file: The TOML formatted + config file you wish to use.
    • +
    • open_browser: If true a browser will be opened pointing at the documentation server
    • +
    • port: The port to expose your documentation on (defaults to: 8000)
    • +
    • host: The host to expose your documentation on (defaults to "127.0.0.1")
    • +
    • modules: One or more modules to render reference documentation for
    • +
    • reload: If true the server will live load any changes
    • +
    +
    +View Source +
    def server(
    +
    +    directory: str = "",
    +
    +    config_file: str = "pyproject.toml",
    +
    +    open_browser: bool = False,
    +
    +    port: int = None,  # type: ignore
    +
    +    host: str = None,  # type: ignore
    +
    +    modules: list = None,  # type: ignore
    +
    +    reload: bool = False,
    +
    +) -> None:
    +
    +    """Runs a development webserver enabling you to browse documentation locally.
    +
    +    - *directory*: The root folder of your project.
    +
    +    - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted
    +
    +      config file you wish to use.
    +
    +    - *open_browser*: If true a browser will be opened pointing at the documentation server
    +
    +    - *port*: The port to expose your documentation on (defaults to: `8000`)
    +
    +    - *host*: The host to expose your documentation on (defaults to `"127.0.0.1"`)
    +
    +    - *modules*: One or more modules to render reference documentation for
    +
    +    - *reload*: If true the server will live load any changes
    +
    +    """
    +
    +    directory = directory if directory else os.getcwd()
    +
    +    project_config = project_configuration(directory, config_file, modules=modules)
    +
    +    host = host or project_config["host"]
    +
    +    port = port or project_config["port"]
    +
    +    with render.documentation_in_temp_folder(project_config) as (sources_folder, docs_folder):
    +
    +        print(logo.ascii_art)
    +
    +        live_server = Server()
    +
    +        if reload:
    +
    +            def reloader():  # pragma: no cover
    +
    +                sources_old = sources_folder + ".old"
    +
    +                docs_old = docs_folder + ".old"
    +
    +                with render.documentation_in_temp_folder(project_config) as (sources_new, docs_new):
    +
    +                    # cause as little churn as possible to the server watchers
    +
    +                    os.rename(sources_folder, sources_old)
    +
    +                    os.rename(sources_new, sources_folder)
    +
    +                    os.rename(sources_old, sources_new)
    +
    +                    os.rename(docs_folder, docs_old)
    +
    +                    os.rename(docs_new, docs_folder)
    +
    +                    os.rename(docs_old, docs_new)
    +
    +            # all directories that feed documentation_in_temp_folder
    +
    +            watch_dirs = set(
    +
    +                (
    +
    +                    project_config["directory"],
    +
    +                    project_config["docs_dir"],
    +
    +                    *project_config["extra_dirs"],
    +
    +                )
    +
    +            )
    +
    +            if "docs_dir" in project_config["mkdocs"]:
    +
    +                watch_dirs.add(project_config["mkdocs"]["docs_dir"])
    +
    +            if "site_dir" in project_config["mkdocs"]:
    +
    +                watch_dirs.add(project_config["mkdocs"]["site_dir"])
    +
    +            for watch_dir in watch_dirs.difference(set((sources_folder, docs_folder))):
    +
    +                live_server.watch(watch_dir, reloader)
    +
    +        if open_browser:
    +
    +            webbrowser.open_new(f"http://{host}:{port}")
    +
    +        live_server.serve(root=docs_folder, host=host, port=port, restart_delay=0)
    +
    + +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/cli/index.html b/reference/portray/cli/index.html new file mode 100644 index 00000000..500c5e07 --- /dev/null +++ b/reference/portray/cli/index.html @@ -0,0 +1,3150 @@ + + + + + + + + + + + + + + + + CLI - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.cli

    +

    This module defines CLI interaction when using portray.

    +

    This is powered by hug which means unless necessary +it should maintain 1:1 compatibility with the programmatic API definition in the +API module

    +
      +
    • portray as_html: Renders the project as HTML into the site or other specified output directory
    • +
    • portray in_browser: Runs a server with the rendered documentation pointing a browser to it
    • +
    • portray server: Starts a local development server (by default at localhost:8000)
    • +
    • portray project_configuration: Returns back the project configuration as determined byportray
    • +
    +
    +View Source +
    """This module defines CLI interaction when using `portray`.
    +
    +This is powered by [hug](https://github.com/hugapi/hug) which means unless necessary
    +
    +it should maintain 1:1 compatibility with the programmatic API definition in the
    +
    +[API module](/reference/portray/api)
    +
    +- `portray as_html`: Renders the project as HTML into the `site` or other specified output directory
    +
    +- `portray in_browser`: Runs a server with the rendered documentation pointing a browser to it
    +
    +- `portray server`: Starts a local development server (by default at localhost:8000)
    +
    +- `portray project_configuration`: Returns back the project configuration as determined by` portray`
    +
    +"""
    +
    +from pprint import pprint
    +
    +import hug
    +
    +from portray import api, logo
    +
    +cli = hug.cli(api=hug.API(__name__, doc=logo.ascii_art))
    +
    +cli(api.as_html)
    +
    +cli.output(pprint)(api.project_configuration)
    +
    +cli(api.server)
    +
    +cli(api.in_browser)
    +
    +cli(api.on_github_pages)
    +
    + +
    +

    Variables

    +
    cli
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/config/index.html b/reference/portray/config/index.html new file mode 100644 index 00000000..5cdd541d --- /dev/null +++ b/reference/portray/config/index.html @@ -0,0 +1,3997 @@ + + + + + + + + + + + + + + + + Config - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.config

    +

    Defines the configuration defaults and load functions used by portray

    +
    +View Source +
    """Defines the configuration defaults and load functions used by `portray`"""
    +
    +import _ast
    +
    +import ast
    +
    +import os
    +
    +import re
    +
    +import warnings
    +
    +from pathlib import Path
    +
    +from typing import Any, Dict, Optional
    +
    +import mkdocs.config as _mkdocs_config  # noqa
    +
    +import mkdocs.exceptions as _mkdocs_exceptions  # noqa
    +
    +from git import Repo
    +
    +from toml import load as toml_load
    +
    +from portray.exceptions import NoProjectFound
    +
    +PORTRAY_DEFAULTS = {
    +
    +    "docs_dir": "docs",
    +
    +    "extra_dirs": ["art", "images", "media"],
    +
    +    "output_dir": "site",
    +
    +    "port": 8000,
    +
    +    "host": "127.0.0.1",
    +
    +    "append_directory_to_python_path": True,
    +
    +    "include_reference_documentation": True,
    +
    +    "labels": {"Cli": "CLI", "Api": "API", "Http": "HTTP", "Pypi": "PyPI"},
    +
    +    "extra_markdown_extensions": [],
    +
    +}
    +
    +MKDOCS_DEFAULTS: Dict[str, Any] = {
    +
    +    "site_name": os.path.basename(os.getcwd()),
    +
    +    "config_file_path": os.getcwd(),
    +
    +    "theme": {
    +
    +        "name": "material",
    +
    +        "palette": {"primary": "green", "accent": "lightgreen"},
    +
    +        "custom_dir": os.path.join(os.path.dirname(__file__), "mkdocs_templates"),
    +
    +    },
    +
    +    "markdown_extensions": [
    +
    +        "admonition",
    +
    +        "codehilite",
    +
    +        "extra",
    +
    +        "pymdownx.details",
    +
    +        "pymdownx.highlight",
    +
    +    ],
    +
    +}
    +
    +PDOCS_DEFAULTS: Dict = {"overwrite": True, "exclude_source": False}
    +
    +def project(directory: str, config_file: str, **overrides) -> dict:
    +
    +    """Returns back the complete configuration - including all sub configuration components
    +
    +    defined below that `portray` was able to determine for the project
    +
    +    """
    +
    +    if not (
    +
    +        os.path.isfile(os.path.join(directory, config_file))
    +
    +        or os.path.isfile(os.path.join(directory, "setup.py"))
    +
    +        or "modules" in overrides
    +
    +    ):
    +
    +        raise NoProjectFound(directory)
    +
    +    project_config: Dict[str, Any] = {**PORTRAY_DEFAULTS, "directory": directory}
    +
    +    if os.path.isfile(os.path.join(directory, "setup.py")):
    +
    +        project_config.update(setup_py(os.path.join(directory, "setup.py")))
    +
    +    project_config.update(toml(os.path.join(directory, config_file)))
    +
    +    project_config.update(overrides)
    +
    +    project_config.setdefault("modules", [os.path.basename(os.getcwd()).replace("-", "_")])
    +
    +    project_config.setdefault("pdocs", {}).setdefault("modules", project_config["modules"])
    +
    +    mkdocs_config = project_config.get("mkdocs", {})
    +
    +    mkdocs_config.setdefault(
    +
    +        "extra_markdown_extensions", project_config.get("extra_markdown_extensions", [])
    +
    +    )
    +
    +    project_config["mkdocs"] = mkdocs(directory, **mkdocs_config)
    +
    +    if "pdoc3" in project_config:
    +
    +        warnings.warn(
    +
    +            "pdoc3 config usage is deprecated in favor of pdocs. "
    +
    +            "pdoc3 section will be ignored. ",
    +
    +            DeprecationWarning,
    +
    +        )
    +
    +    project_config["pdocs"] = pdocs(directory, **project_config.get("pdocs", {}))
    +
    +    return project_config
    +
    +def setup_py(location: str) -> dict:
    +
    +    """Returns back any configuration info we are able to determine from a setup.py file"""
    +
    +    setup_config = {}
    +
    +    try:
    +
    +        with open(location) as setup_py_file:
    +
    +            for node in ast.walk(ast.parse(setup_py_file.read())):
    +
    +                if (
    +
    +                    type(node) == _ast.Call
    +
    +                    and type(getattr(node, "func", None)) == _ast.Name
    +
    +                    and node.func.id == "setup"  # type: ignore
    +
    +                ):
    +
    +                    for keyword in node.keywords:  # type: ignore
    +
    +                        if keyword.arg == "packages":
    +
    +                            setup_config["modules"] = ast.literal_eval(keyword.value)
    +
    +                            break
    +
    +                    break
    +
    +    except Exception as error:
    +
    +        warnings.warn(f"Error ({error}) occurred trying to parse setup.py file: {location}")
    +
    +    return setup_config
    +
    +def toml(location: str) -> dict:
    +
    +    """Returns back the configuration found within the projects
    +
    +    [TOML](https://github.com/toml-lang/toml#toml) config (if there is one).
    +
    +    Generally this is a `pyproject.toml` file at the root of the project
    +
    +    with a `[tool.portray]` section defined.
    +
    +    """
    +
    +    try:
    +
    +        location_exists = os.path.exists(location)
    +
    +        if not location_exists:
    +
    +            warnings.warn(f'\nNo config file found at location: "{location}"')
    +
    +            return {}
    +
    +    except Exception as detection_error:  # pragma: no cover
    +
    +        warnings.warn(f'\nUnable to check config at "{location}" due to error: {detection_error}')
    +
    +    try:
    +
    +        toml_config = toml_load(location)
    +
    +        tools = toml_config.get("tool", {})
    +
    +        config = tools.get("portray", {})
    +
    +        config["file"] = location
    +
    +        if "modules" not in config:
    +
    +            if "poetry" in tools and "name" in tools["poetry"]:
    +
    +                config["modules"] = [tools["poetry"]["name"]]
    +
    +            elif (
    +
    +                "flit" in tools
    +
    +                and "metadata" in tools["flit"]
    +
    +                and "module" in tools["flit"]["metadata"]
    +
    +            ):
    +
    +                config["modules"] = [tools["flit"]["metadata"]["module"]]
    +
    +        return config
    +
    +    except Exception as load_config_error:
    +
    +        warnings.warn(f'\nConfig file at "{location}" has errors: {load_config_error}')
    +
    +    return {}
    +
    +def repository(
    +
    +    directory: str,
    +
    +    repo_url: Optional[str] = None,
    +
    +    repo_name: Optional[str] = None,
    +
    +    edit_uri: Optional[str] = None,
    +
    +    normalize_repo_url: bool = True,
    +
    +    **kwargs,
    +
    +) -> Dict[str, Optional[str]]:
    +
    +    """Returns back any information that can be determined by introspecting the projects git repo
    +
    +    (if there is one).
    +
    +    """
    +
    +    try:
    +
    +        if repo_url is None:
    +
    +            repo_url = Repo(directory).remotes.origin.url
    +
    +        if repo_name is None:
    +
    +            match = re.search(r"(:(//)?)([\w\.@\:/\-~]+)(\.git)?(/)?", repo_url)
    +
    +            if match:
    +
    +                path = match.groups()[2]
    +
    +            else:
    +
    +                path = repo_url
    +
    +            repo_name = path.split("/")[-1]
    +
    +            if repo_name.endswith(".git"):
    +
    +                repo_name = repo_name[: -len(".git")]
    +
    +        if edit_uri is None:
    +
    +            if "github" in repo_url or "gitlab" in repo_url:
    +
    +                edit_uri = "edit/main/"
    +
    +            elif "bitbucket" in repo_url:
    +
    +                edit_uri = "src/default/docs/"
    +
    +        if normalize_repo_url:
    +
    +            if repo_url.startswith("git@") and ":" in repo_url:
    +
    +                tld, path = repo_url[4:].split(":")
    +
    +                repo_url = f"https://{tld}/{path}"
    +
    +            elif repo_url.startswith("https://") and "@" in repo_url:
    +
    +                repo_url = f"https://{repo_url.split('@')[1]}"
    +
    +            if repo_url and "github" in repo_url or "gitlab" in repo_url or "bitbucket" in repo_url:
    +
    +                repo_url = repo_url.replace(".git", "")
    +
    +        return {
    +
    +            key: value
    +
    +            for key, value in {
    +
    +                "repo_url": repo_url,
    +
    +                "repo_name": repo_name,
    +
    +                "edit_uri": edit_uri,
    +
    +            }.items()
    +
    +            if value
    +
    +        }
    +
    +    except Exception:
    +
    +        warnings.warn("Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.")
    +
    +        return {}
    +
    +def mkdocs(directory: str, **overrides) -> dict:
    +
    +    """Returns back the configuration that will be used when running mkdocs"""
    +
    +    mkdocs_config: Dict[str, Any] = {
    +
    +        **MKDOCS_DEFAULTS,
    +
    +        **repository(directory, **overrides),
    +
    +        **overrides,
    +
    +    }
    +
    +    theme = mkdocs_config["theme"]
    +
    +    if theme["name"].lower() == "material":
    +
    +        if "custom_dir" in theme:
    +
    +            theme["custom_dir"] = Path(theme["custom_dir"]).absolute().as_posix()
    +
    +        else:
    +
    +            theme["custom_dir"] = MKDOCS_DEFAULTS["theme"]["custom_dir"]
    +
    +    nav = mkdocs_config.get("nav", None)
    +
    +    if nav and hasattr(nav[0], "copy"):
    +
    +        mkdocs_config["nav"] = [nav_item.copy() for nav_item in nav]
    +
    +    mkdocs_config["markdown_extensions"] = mkdocs_config["markdown_extensions"] + mkdocs_config.pop(
    +
    +        "extra_markdown_extensions", []
    +
    +    )
    +
    +    return mkdocs_config
    +
    +def pdocs(directory: str, **overrides) -> dict:
    +
    +    """Returns back the configuration that will be used when running pdocs"""
    +
    +    defaults = {**PDOCS_DEFAULTS}
    +
    +    defaults.update(overrides)
    +
    +    return defaults
    +
    + +
    +

    Variables

    +
    MKDOCS_DEFAULTS
    +
    + +
    PDOCS_DEFAULTS
    +
    + +
    PORTRAY_DEFAULTS
    +
    + +

    Functions

    +

    mkdocs

    +
    def mkdocs(
    +    directory: str,
    +    **overrides
    +) -> dict
    +
    + +

    Returns back the configuration that will be used when running mkdocs

    +
    +View Source +
    def mkdocs(directory: str, **overrides) -> dict:
    +
    +    """Returns back the configuration that will be used when running mkdocs"""
    +
    +    mkdocs_config: Dict[str, Any] = {
    +
    +        **MKDOCS_DEFAULTS,
    +
    +        **repository(directory, **overrides),
    +
    +        **overrides,
    +
    +    }
    +
    +    theme = mkdocs_config["theme"]
    +
    +    if theme["name"].lower() == "material":
    +
    +        if "custom_dir" in theme:
    +
    +            theme["custom_dir"] = Path(theme["custom_dir"]).absolute().as_posix()
    +
    +        else:
    +
    +            theme["custom_dir"] = MKDOCS_DEFAULTS["theme"]["custom_dir"]
    +
    +    nav = mkdocs_config.get("nav", None)
    +
    +    if nav and hasattr(nav[0], "copy"):
    +
    +        mkdocs_config["nav"] = [nav_item.copy() for nav_item in nav]
    +
    +    mkdocs_config["markdown_extensions"] = mkdocs_config["markdown_extensions"] + mkdocs_config.pop(
    +
    +        "extra_markdown_extensions", []
    +
    +    )
    +
    +    return mkdocs_config
    +
    + +
    +

    pdocs

    +
    def pdocs(
    +    directory: str,
    +    **overrides
    +) -> dict
    +
    + +

    Returns back the configuration that will be used when running pdocs

    +
    +View Source +
    def pdocs(directory: str, **overrides) -> dict:
    +
    +    """Returns back the configuration that will be used when running pdocs"""
    +
    +    defaults = {**PDOCS_DEFAULTS}
    +
    +    defaults.update(overrides)
    +
    +    return defaults
    +
    + +
    +

    project

    +
    def project(
    +    directory: str,
    +    config_file: str,
    +    **overrides
    +) -> dict
    +
    + +

    Returns back the complete configuration - including all sub configuration components

    +

    defined below that portray was able to determine for the project

    +
    +View Source +
    def project(directory: str, config_file: str, **overrides) -> dict:
    +
    +    """Returns back the complete configuration - including all sub configuration components
    +
    +    defined below that `portray` was able to determine for the project
    +
    +    """
    +
    +    if not (
    +
    +        os.path.isfile(os.path.join(directory, config_file))
    +
    +        or os.path.isfile(os.path.join(directory, "setup.py"))
    +
    +        or "modules" in overrides
    +
    +    ):
    +
    +        raise NoProjectFound(directory)
    +
    +    project_config: Dict[str, Any] = {**PORTRAY_DEFAULTS, "directory": directory}
    +
    +    if os.path.isfile(os.path.join(directory, "setup.py")):
    +
    +        project_config.update(setup_py(os.path.join(directory, "setup.py")))
    +
    +    project_config.update(toml(os.path.join(directory, config_file)))
    +
    +    project_config.update(overrides)
    +
    +    project_config.setdefault("modules", [os.path.basename(os.getcwd()).replace("-", "_")])
    +
    +    project_config.setdefault("pdocs", {}).setdefault("modules", project_config["modules"])
    +
    +    mkdocs_config = project_config.get("mkdocs", {})
    +
    +    mkdocs_config.setdefault(
    +
    +        "extra_markdown_extensions", project_config.get("extra_markdown_extensions", [])
    +
    +    )
    +
    +    project_config["mkdocs"] = mkdocs(directory, **mkdocs_config)
    +
    +    if "pdoc3" in project_config:
    +
    +        warnings.warn(
    +
    +            "pdoc3 config usage is deprecated in favor of pdocs. "
    +
    +            "pdoc3 section will be ignored. ",
    +
    +            DeprecationWarning,
    +
    +        )
    +
    +    project_config["pdocs"] = pdocs(directory, **project_config.get("pdocs", {}))
    +
    +    return project_config
    +
    + +
    +

    repository

    +
    def repository(
    +    directory: str,
    +    repo_url: Union[str, NoneType] = None,
    +    repo_name: Union[str, NoneType] = None,
    +    edit_uri: Union[str, NoneType] = None,
    +    normalize_repo_url: bool = True,
    +    **kwargs
    +) -> Dict[str, Union[str, NoneType]]
    +
    + +

    Returns back any information that can be determined by introspecting the projects git repo

    +

    (if there is one).

    +
    +View Source +
    def repository(
    +
    +    directory: str,
    +
    +    repo_url: Optional[str] = None,
    +
    +    repo_name: Optional[str] = None,
    +
    +    edit_uri: Optional[str] = None,
    +
    +    normalize_repo_url: bool = True,
    +
    +    **kwargs,
    +
    +) -> Dict[str, Optional[str]]:
    +
    +    """Returns back any information that can be determined by introspecting the projects git repo
    +
    +    (if there is one).
    +
    +    """
    +
    +    try:
    +
    +        if repo_url is None:
    +
    +            repo_url = Repo(directory).remotes.origin.url
    +
    +        if repo_name is None:
    +
    +            match = re.search(r"(:(//)?)([\w\.@\:/\-~]+)(\.git)?(/)?", repo_url)
    +
    +            if match:
    +
    +                path = match.groups()[2]
    +
    +            else:
    +
    +                path = repo_url
    +
    +            repo_name = path.split("/")[-1]
    +
    +            if repo_name.endswith(".git"):
    +
    +                repo_name = repo_name[: -len(".git")]
    +
    +        if edit_uri is None:
    +
    +            if "github" in repo_url or "gitlab" in repo_url:
    +
    +                edit_uri = "edit/main/"
    +
    +            elif "bitbucket" in repo_url:
    +
    +                edit_uri = "src/default/docs/"
    +
    +        if normalize_repo_url:
    +
    +            if repo_url.startswith("git@") and ":" in repo_url:
    +
    +                tld, path = repo_url[4:].split(":")
    +
    +                repo_url = f"https://{tld}/{path}"
    +
    +            elif repo_url.startswith("https://") and "@" in repo_url:
    +
    +                repo_url = f"https://{repo_url.split('@')[1]}"
    +
    +            if repo_url and "github" in repo_url or "gitlab" in repo_url or "bitbucket" in repo_url:
    +
    +                repo_url = repo_url.replace(".git", "")
    +
    +        return {
    +
    +            key: value
    +
    +            for key, value in {
    +
    +                "repo_url": repo_url,
    +
    +                "repo_name": repo_name,
    +
    +                "edit_uri": edit_uri,
    +
    +            }.items()
    +
    +            if value
    +
    +        }
    +
    +    except Exception:
    +
    +        warnings.warn("Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.")
    +
    +        return {}
    +
    + +
    +

    setup_py

    +
    def setup_py(
    +    location: str
    +) -> dict
    +
    + +

    Returns back any configuration info we are able to determine from a setup.py file

    +
    +View Source +
    def setup_py(location: str) -> dict:
    +
    +    """Returns back any configuration info we are able to determine from a setup.py file"""
    +
    +    setup_config = {}
    +
    +    try:
    +
    +        with open(location) as setup_py_file:
    +
    +            for node in ast.walk(ast.parse(setup_py_file.read())):
    +
    +                if (
    +
    +                    type(node) == _ast.Call
    +
    +                    and type(getattr(node, "func", None)) == _ast.Name
    +
    +                    and node.func.id == "setup"  # type: ignore
    +
    +                ):
    +
    +                    for keyword in node.keywords:  # type: ignore
    +
    +                        if keyword.arg == "packages":
    +
    +                            setup_config["modules"] = ast.literal_eval(keyword.value)
    +
    +                            break
    +
    +                    break
    +
    +    except Exception as error:
    +
    +        warnings.warn(f"Error ({error}) occurred trying to parse setup.py file: {location}")
    +
    +    return setup_config
    +
    + +
    +

    toml

    +
    def toml(
    +    location: str
    +) -> dict
    +
    + +

    Returns back the configuration found within the projects

    +

    TOML config (if there is one).

    +

    Generally this is a pyproject.toml file at the root of the project +with a [tool.portray] section defined.

    +
    +View Source +
    def toml(location: str) -> dict:
    +
    +    """Returns back the configuration found within the projects
    +
    +    [TOML](https://github.com/toml-lang/toml#toml) config (if there is one).
    +
    +    Generally this is a `pyproject.toml` file at the root of the project
    +
    +    with a `[tool.portray]` section defined.
    +
    +    """
    +
    +    try:
    +
    +        location_exists = os.path.exists(location)
    +
    +        if not location_exists:
    +
    +            warnings.warn(f'\nNo config file found at location: "{location}"')
    +
    +            return {}
    +
    +    except Exception as detection_error:  # pragma: no cover
    +
    +        warnings.warn(f'\nUnable to check config at "{location}" due to error: {detection_error}')
    +
    +    try:
    +
    +        toml_config = toml_load(location)
    +
    +        tools = toml_config.get("tool", {})
    +
    +        config = tools.get("portray", {})
    +
    +        config["file"] = location
    +
    +        if "modules" not in config:
    +
    +            if "poetry" in tools and "name" in tools["poetry"]:
    +
    +                config["modules"] = [tools["poetry"]["name"]]
    +
    +            elif (
    +
    +                "flit" in tools
    +
    +                and "metadata" in tools["flit"]
    +
    +                and "module" in tools["flit"]["metadata"]
    +
    +            ):
    +
    +                config["modules"] = [tools["flit"]["metadata"]["module"]]
    +
    +        return config
    +
    +    except Exception as load_config_error:
    +
    +        warnings.warn(f'\nConfig file at "{location}" has errors: {load_config_error}')
    +
    +    return {}
    +
    + +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/exceptions/index.html b/reference/portray/exceptions/index.html new file mode 100644 index 00000000..0c0a449c --- /dev/null +++ b/reference/portray/exceptions/index.html @@ -0,0 +1,3552 @@ + + + + + + + + + + + + + + + + Exceptions - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.exceptions

    +

    All portray specific exception classes should be defined here

    +
    +View Source +
    """All portray specific exception classes should be defined here"""
    +
    +class PortrayError(Exception):
    +
    +    """Base class for all exceptions returned from portray"""
    +
    +    pass
    +
    +class NoProjectFound(PortrayError):
    +
    +    """Thrown when portray is ran in a directory with no Python project"""
    +
    +    def __init__(self, directory: str):
    +
    +        super().__init__(
    +
    +            self,
    +
    +            f"No Python project found in the given directory: '{directory}'"
    +
    +            + " See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound",
    +
    +        )
    +
    +        self.directory = directory
    +
    +class DocumentationAlreadyExists(PortrayError):
    +
    +    """Thrown when portray has been told to output documentation where it already exists"""
    +
    +    def __init__(self, directory: str):
    +
    +        super().__init__(
    +
    +            self, f"Documentation already exists in '{directory}'. Use --overwrite to ignore"
    +
    +        )
    +
    +        self.directory = directory
    +
    + +
    +

    Classes

    +

    DocumentationAlreadyExists

    +
    class DocumentationAlreadyExists(
    +    directory: str
    +)
    +
    + +

    Thrown when portray has been told to output documentation where it already exists

    +
    +View Source +
    class DocumentationAlreadyExists(PortrayError):
    +
    +    """Thrown when portray has been told to output documentation where it already exists"""
    +
    +    def __init__(self, directory: str):
    +
    +        super().__init__(
    +
    +            self, f"Documentation already exists in '{directory}'. Use --overwrite to ignore"
    +
    +        )
    +
    +        self.directory = directory
    +
    + +
    +
    +

    Ancestors (in MRO)

    +
      +
    • portray.exceptions.PortrayError
    • +
    • builtins.Exception
    • +
    • builtins.BaseException
    • +
    +

    Class variables

    +
    args
    +
    + +

    Methods

    +

    with_traceback

    +
    def with_traceback(
    +    ...
    +)
    +
    + +

    Exception.with_traceback(tb) --

    +

    set self.traceback to tb and return self.

    +

    NoProjectFound

    +
    class NoProjectFound(
    +    directory: str
    +)
    +
    + +

    Thrown when portray is ran in a directory with no Python project

    +
    +View Source +
    class NoProjectFound(PortrayError):
    +
    +    """Thrown when portray is ran in a directory with no Python project"""
    +
    +    def __init__(self, directory: str):
    +
    +        super().__init__(
    +
    +            self,
    +
    +            f"No Python project found in the given directory: '{directory}'"
    +
    +            + " See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound",
    +
    +        )
    +
    +        self.directory = directory
    +
    + +
    +
    +

    Ancestors (in MRO)

    +
      +
    • portray.exceptions.PortrayError
    • +
    • builtins.Exception
    • +
    • builtins.BaseException
    • +
    +

    Class variables

    +
    args
    +
    + +

    Methods

    +

    with_traceback

    +
    def with_traceback(
    +    ...
    +)
    +
    + +

    Exception.with_traceback(tb) --

    +

    set self.traceback to tb and return self.

    +

    PortrayError

    +
    class PortrayError(
    +    /,
    +    *args,
    +    **kwargs
    +)
    +
    + +

    Base class for all exceptions returned from portray

    +
    +View Source +
    class PortrayError(Exception):
    +
    +    """Base class for all exceptions returned from portray"""
    +
    +    pass
    +
    + +
    +
    +

    Ancestors (in MRO)

    +
      +
    • builtins.Exception
    • +
    • builtins.BaseException
    • +
    +

    Descendants

    +
      +
    • portray.exceptions.NoProjectFound
    • +
    • portray.exceptions.DocumentationAlreadyExists
    • +
    +

    Class variables

    +
    args
    +
    + +

    Methods

    +

    with_traceback

    +
    def with_traceback(
    +    ...
    +)
    +
    + +

    Exception.with_traceback(tb) --

    +

    set self.traceback to tb and return self.

    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/index.html b/reference/portray/index.html new file mode 100644 index 00000000..34e08a9a --- /dev/null +++ b/reference/portray/index.html @@ -0,0 +1,3106 @@ + + + + + + + + + + + + + + + + Index - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    + +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/logo/index.html b/reference/portray/logo/index.html new file mode 100644 index 00000000..e5dd49a5 --- /dev/null +++ b/reference/portray/logo/index.html @@ -0,0 +1,3159 @@ + + + + + + + + + + + + + + + + Logo - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.logo

    +
    __
    +                     /\ \__
    + _____     ___   _ __\ \ ,_\  _ __    __     __  __
    +/\ '__`\  / __`\/\`'__\ \ \/ /\`'__\/'__`\  /\ \/\ \
    +\ \ \L\ \/\ \L\ \ \ \/ \ \ \_\ \ \//\ \L\.\_\ \ \_\ \
    + \ \ ,__/\ \____/\ \_\  \ \__\\ \_\\ \__/.\_\\/`____ \
    +  \ \ \/  \/___/  \/_/   \/__/ \/_/ \/__/\/_/ `/___/> \
    +   \ \_\                                         /\___/
    +    \/_/                                         \/__/
    +        Your Project with Great Documentation.
    +
    +Version: 1.8.0
    +Copyright Timothy Edmund Crosley 2019 MIT License
    +
    + +
    +View Source +
    from portray._version import __version__
    +
    +ascii_art = rf"""
    +
    +                      __
    +
    +                     /\ \__
    +
    + _____     ___   _ __\ \ ,_\  _ __    __     __  __
    +
    +/\ '__`\  / __`\/\`'__\ \ \/ /\`'__\/'__`\  /\ \/\ \
    +
    +\ \ \L\ \/\ \L\ \ \ \/ \ \ \_\ \ \//\ \L\.\_\ \ \_\ \
    +
    + \ \ ,__/\ \____/\ \_\  \ \__\\ \_\\ \__/.\_\\/`____ \
    +
    +  \ \ \/  \/___/  \/_/   \/__/ \/_/ \/__/\/_/ `/___/> \
    +
    +   \ \_\                                         /\___/
    +
    +    \/_/                                         \/__/
    +
    +        Your Project with Great Documentation.
    +
    +Version: {__version__}
    +
    +Copyright Timothy Edmund Crosley 2019 MIT License
    +
    +"""
    +
    +__doc__ = f"""
    +
    +```python
    +
    +{ascii_art}
    +
    +```
    +
    +"""
    +
    + +
    +

    Variables

    +
    ascii_art
    +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/reference/portray/render/index.html b/reference/portray/render/index.html new file mode 100644 index 00000000..61da2f65 --- /dev/null +++ b/reference/portray/render/index.html @@ -0,0 +1,3818 @@ + + + + + + + + + + + + + + + + Render - outlines + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + +
    + +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    + + + +
    +
    + + + + + + + + + +

    Module portray.render

    +

    Defines how to render the current project and project_config using the

    +

    included documentation generation utilities.

    +
    +View Source +
    """Defines how to render the current project and project_config using the
    +
    +included documentation generation utilities.
    +
    +"""
    +
    +import os
    +
    +import shutil
    +
    +import sys
    +
    +import tempfile
    +
    +from contextlib import contextmanager
    +
    +from glob import glob
    +
    +from typing import Dict, Iterator, Tuple
    +
    +import mkdocs.config as mkdocs_config
    +
    +import mkdocs.exceptions as _mkdocs_exceptions
    +
    +from mkdocs.commands.build import build as mkdocs_build
    +
    +from mkdocs.config.defaults import get_schema as mkdocs_schema
    +
    +from mkdocs.utils import is_markdown_file
    +
    +from pdocs import as_markdown as pdocs_as_markdown
    +
    +from yaspin import yaspin
    +
    +from portray.exceptions import DocumentationAlreadyExists
    +
    +NO_HOME_PAGE = """
    +
    +# Nothing here
    +
    +`portray` uses README.md as your projects home page.
    +
    +It appears you do not yet have a README.md file created.
    +
    +"""
    +
    +def documentation(config: dict, overwrite: bool = False) -> None:
    +
    +    """Renders the entire project given the project config into the config's
    +
    +    specified output directory.
    +
    +    Behind the scenes:
    +
    +    - A temporary directory is created and your code is copy and pasted there
    +
    +    - pdoc is ran over your code with the output sent into the temporary directory
    +
    +        as Markdown documents
    +
    +    - MkDocs is ran over all of your projects Markdown documents including those
    +
    +        generated py pdoc. MkDocs outputs an HTML representation to a new temporary
    +
    +        directory.
    +
    +    - The html temporary directory is copied into your specified output location
    +
    +    - Both temporary directories are deleted.
    +
    +    """
    +
    +    if os.path.exists(config["output_dir"]):
    +
    +        if overwrite:
    +
    +            shutil.rmtree(config["output_dir"])
    +
    +        else:
    +
    +            raise DocumentationAlreadyExists(config["output_dir"])
    +
    +    with documentation_in_temp_folder(config) as (_, documentation_output):
    +
    +        shutil.copytree(documentation_output, config["output_dir"])
    +
    +def pdocs(config: dict) -> None:
    +
    +    """Render this project using the specified pdoc config passed into pdoc.
    +
    +    This rendering is from code definition to Markdown so that
    +
    +    it will be compatible with MkDocs.
    +
    +    """
    +
    +    pdocs_as_markdown(**config)
    +
    +def mkdocs(config: dict):
    +
    +    """Render the project's associated Markdown documentation using the specified
    +
    +    MkDocs config passed into the MkDocs `build` command.
    +
    +    This rendering is from `.md` Markdown documents into HTML
    +
    +    """
    +
    +    config_instance = _mkdocs_config(config)
    +
    +    return mkdocs_build(config_instance)
    +
    +@contextmanager
    +
    +def documentation_in_temp_folder(config: dict) -> Iterator[Tuple[str, str]]:
    +
    +    """Build documentation within a temp folder, returning that folder name before it is deleted."""
    +
    +    if config["append_directory_to_python_path"] and not config["directory"] in sys.path:
    +
    +        sys.path.append(config["directory"])
    +
    +    with tempfile.TemporaryDirectory() as input_dir:
    +
    +        input_dir = os.path.join(input_dir, "input")
    +
    +        os.mkdir(input_dir)
    +
    +        with tempfile.TemporaryDirectory() as temp_output_dir:
    +
    +            with yaspin(
    +
    +                text="Copying source documentation to temporary compilation directory"
    +
    +            ) as spinner:
    +
    +                for root_file in os.listdir(config["directory"]):
    +
    +                    root_file_absolute = os.path.join(config["directory"], root_file)
    +
    +                    if os.path.isfile(root_file_absolute) and is_markdown_file(root_file_absolute):
    +
    +                        shutil.copyfile(root_file_absolute, os.path.join(input_dir, root_file))
    +
    +                for source_directory in [config["docs_dir"]] + config["extra_dirs"]:
    +
    +                    directory_absolute = os.path.join(config["directory"], source_directory)
    +
    +                    if os.path.isdir(directory_absolute):
    +
    +                        shutil.copytree(
    +
    +                            directory_absolute, os.path.join(input_dir, source_directory)
    +
    +                        )
    +
    +                spinner.ok("Done")
    +
    +            if "docs_dir" not in config["mkdocs"]:
    +
    +                config["mkdocs"]["docs_dir"] = input_dir
    +
    +            if "site_dir" not in config["mkdocs"]:
    +
    +                config["mkdocs"]["site_dir"] = temp_output_dir
    +
    +            if "nav" not in config["mkdocs"]:
    +
    +                nav = config["mkdocs"]["nav"] = []
    +
    +                root_docs = sorted(glob(os.path.join(input_dir, "*.md")))
    +
    +                readme_doc = os.path.join(input_dir, "README.md")
    +
    +                if readme_doc in root_docs:
    +
    +                    root_docs.remove(readme_doc)
    +
    +                else:
    +
    +                    with open(readme_doc, "w") as readme_doc_file:
    +
    +                        readme_doc_file.write(NO_HOME_PAGE)
    +
    +                nav.append({"Home": "README.md"})
    +
    +                nav.extend(_doc(doc, input_dir, config) for doc in root_docs)
    +
    +                nav.extend(
    +
    +                    _nested_docs(os.path.join(input_dir, config["docs_dir"]), input_dir, config)
    +
    +                )
    +
    +            else:
    +
    +                nav = config["mkdocs"]["nav"]
    +
    +                if nav:
    +
    +                    index_nav = nav[0]
    +
    +                    index_page: str = ""
    +
    +                    if index_nav and isinstance(index_nav, dict):
    +
    +                        index_page = tuple(index_nav.values())[0]
    +
    +                    elif isinstance(index_nav, str):  # pragma: no cover
    +
    +                        index_page = index_nav
    +
    +                    if index_page:
    +
    +                        destination_index_page = os.path.join(input_dir, "index.md")
    +
    +                        if (
    +
    +                            index_page != "README.md"
    +
    +                            and index_page != "index.md"
    +
    +                            and not os.path.exists(destination_index_page)
    +
    +                        ):
    +
    +                            shutil.copyfile(
    +
    +                                os.path.join(input_dir, index_page), destination_index_page
    +
    +                            )
    +
    +            if config["include_reference_documentation"]:
    +
    +                with yaspin(text="Auto generating reference documentation using pdocs") as spinner:
    +
    +                    if "output_dir" not in config["pdocs"]:
    +
    +                        config["pdocs"]["output_dir"] = os.path.join(input_dir, "reference")
    +
    +                    pdocs(config["pdocs"])
    +
    +                    reference_docs = _nested_docs(config["pdocs"]["output_dir"], input_dir, config)
    +
    +                    nav.append({"Reference": reference_docs})  # type: ignore
    +
    +                    spinner.ok("Done")
    +
    +            with yaspin(text="Rendering complete website from Markdown using MkDocs") as spinner:
    +
    +                mkdocs(config["mkdocs"])
    +
    +                spinner.ok("Done")
    +
    +            # remove any settings pointing to the temp dirs
    +
    +            if config["mkdocs"]["docs_dir"].startswith(input_dir):
    +
    +                del config["mkdocs"]["docs_dir"]
    +
    +            if config["mkdocs"]["site_dir"].startswith(temp_output_dir):
    +
    +                del config["mkdocs"]["site_dir"]
    +
    +            if config["pdocs"]["output_dir"].startswith(input_dir):
    +
    +                del config["pdocs"]["output_dir"]
    +
    +            if config["include_reference_documentation"]:
    +
    +                nav.pop()
    +
    +            yield input_dir, temp_output_dir
    +
    +def _mkdocs_config(config: dict) -> mkdocs_config.Config:
    +
    +    config_instance = mkdocs_config.Config(schema=mkdocs_schema())
    +
    +    config_instance.load_dict(config)
    +
    +    errors, warnings = config_instance.validate()
    +
    +    if errors:
    +
    +        print(errors)
    +
    +        raise _mkdocs_exceptions.ConfigurationError(
    +
    +            f"Aborted with {len(errors)} Configuration Errors!"
    +
    +        )
    +
    +    elif config.get("strict", False) and warnings:  # pragma: no cover
    +
    +        print(warnings)
    +
    +        raise _mkdocs_exceptions.ConfigurationError(
    +
    +            f"Aborted with {len(warnings)} Configuration Warnings in 'strict' mode!"
    +
    +        )
    +
    +    config_instance.config_file_path = config["config_file_path"]
    +
    +    return config_instance
    +
    +def _nested_docs(directory: str, root_directory: str, config: dict) -> list:
    +
    +    nav = [
    +
    +        _doc(doc, root_directory, config) for doc in sorted(glob(os.path.join(directory, "*.md")))
    +
    +    ]
    +
    +    nested_dirs = sorted(glob(os.path.join(directory, "*/")))
    +
    +    for nested_dir in nested_dirs:
    +
    +        if (
    +
    +            len(glob(os.path.join(nested_dir, "*.md")) + glob(os.path.join(nested_dir, "**/*.md")))
    +
    +            > 0
    +
    +        ):
    +
    +            dir_nav = {
    +
    +                _label(nested_dir[:-1], config): _nested_docs(nested_dir, root_directory, config)
    +
    +            }
    +
    +            nav.append(dir_nav)  # type: ignore
    +
    +    return nav
    +
    +def _label(path: str, config: Dict) -> str:
    +
    +    label = os.path.basename(path)
    +
    +    if "." in label:
    +
    +        label = ".".join(label.split(".")[:-1])
    +
    +    label = label.replace("-", " ").replace("_", " ").title()
    +
    +    return config["labels"].get(label, label)
    +
    +def _doc(path: str, root_path: str, config: dict) -> Dict[str, str]:
    +
    +    path = os.path.relpath(path, root_path)
    +
    +    return {_label(path, config): path}
    +
    + +
    +

    Variables

    +
    NO_HOME_PAGE
    +
    + +

    Functions

    +

    documentation

    +
    def documentation(
    +    config: dict,
    +    overwrite: bool = False
    +) -> None
    +
    + +

    Renders the entire project given the project config into the config's

    +

    specified output directory.

    +

    Behind the scenes:

    +
      +
    • A temporary directory is created and your code is copy and pasted there
    • +
    • pdoc is ran over your code with the output sent into the temporary directory + as Markdown documents
    • +
    • MkDocs is ran over all of your projects Markdown documents including those + generated py pdoc. MkDocs outputs an HTML representation to a new temporary + directory.
    • +
    • The html temporary directory is copied into your specified output location
    • +
    • Both temporary directories are deleted.
    • +
    +
    +View Source +
    def documentation(config: dict, overwrite: bool = False) -> None:
    +
    +    """Renders the entire project given the project config into the config's
    +
    +    specified output directory.
    +
    +    Behind the scenes:
    +
    +    - A temporary directory is created and your code is copy and pasted there
    +
    +    - pdoc is ran over your code with the output sent into the temporary directory
    +
    +        as Markdown documents
    +
    +    - MkDocs is ran over all of your projects Markdown documents including those
    +
    +        generated py pdoc. MkDocs outputs an HTML representation to a new temporary
    +
    +        directory.
    +
    +    - The html temporary directory is copied into your specified output location
    +
    +    - Both temporary directories are deleted.
    +
    +    """
    +
    +    if os.path.exists(config["output_dir"]):
    +
    +        if overwrite:
    +
    +            shutil.rmtree(config["output_dir"])
    +
    +        else:
    +
    +            raise DocumentationAlreadyExists(config["output_dir"])
    +
    +    with documentation_in_temp_folder(config) as (_, documentation_output):
    +
    +        shutil.copytree(documentation_output, config["output_dir"])
    +
    + +
    +

    documentation_in_temp_folder

    +
    def documentation_in_temp_folder(
    +    config: dict
    +) -> Iterator[Tuple[str, str]]
    +
    + +

    Build documentation within a temp folder, returning that folder name before it is deleted.

    +
    +View Source +
    @contextmanager
    +
    +def documentation_in_temp_folder(config: dict) -> Iterator[Tuple[str, str]]:
    +
    +    """Build documentation within a temp folder, returning that folder name before it is deleted."""
    +
    +    if config["append_directory_to_python_path"] and not config["directory"] in sys.path:
    +
    +        sys.path.append(config["directory"])
    +
    +    with tempfile.TemporaryDirectory() as input_dir:
    +
    +        input_dir = os.path.join(input_dir, "input")
    +
    +        os.mkdir(input_dir)
    +
    +        with tempfile.TemporaryDirectory() as temp_output_dir:
    +
    +            with yaspin(
    +
    +                text="Copying source documentation to temporary compilation directory"
    +
    +            ) as spinner:
    +
    +                for root_file in os.listdir(config["directory"]):
    +
    +                    root_file_absolute = os.path.join(config["directory"], root_file)
    +
    +                    if os.path.isfile(root_file_absolute) and is_markdown_file(root_file_absolute):
    +
    +                        shutil.copyfile(root_file_absolute, os.path.join(input_dir, root_file))
    +
    +                for source_directory in [config["docs_dir"]] + config["extra_dirs"]:
    +
    +                    directory_absolute = os.path.join(config["directory"], source_directory)
    +
    +                    if os.path.isdir(directory_absolute):
    +
    +                        shutil.copytree(
    +
    +                            directory_absolute, os.path.join(input_dir, source_directory)
    +
    +                        )
    +
    +                spinner.ok("Done")
    +
    +            if "docs_dir" not in config["mkdocs"]:
    +
    +                config["mkdocs"]["docs_dir"] = input_dir
    +
    +            if "site_dir" not in config["mkdocs"]:
    +
    +                config["mkdocs"]["site_dir"] = temp_output_dir
    +
    +            if "nav" not in config["mkdocs"]:
    +
    +                nav = config["mkdocs"]["nav"] = []
    +
    +                root_docs = sorted(glob(os.path.join(input_dir, "*.md")))
    +
    +                readme_doc = os.path.join(input_dir, "README.md")
    +
    +                if readme_doc in root_docs:
    +
    +                    root_docs.remove(readme_doc)
    +
    +                else:
    +
    +                    with open(readme_doc, "w") as readme_doc_file:
    +
    +                        readme_doc_file.write(NO_HOME_PAGE)
    +
    +                nav.append({"Home": "README.md"})
    +
    +                nav.extend(_doc(doc, input_dir, config) for doc in root_docs)
    +
    +                nav.extend(
    +
    +                    _nested_docs(os.path.join(input_dir, config["docs_dir"]), input_dir, config)
    +
    +                )
    +
    +            else:
    +
    +                nav = config["mkdocs"]["nav"]
    +
    +                if nav:
    +
    +                    index_nav = nav[0]
    +
    +                    index_page: str = ""
    +
    +                    if index_nav and isinstance(index_nav, dict):
    +
    +                        index_page = tuple(index_nav.values())[0]
    +
    +                    elif isinstance(index_nav, str):  # pragma: no cover
    +
    +                        index_page = index_nav
    +
    +                    if index_page:
    +
    +                        destination_index_page = os.path.join(input_dir, "index.md")
    +
    +                        if (
    +
    +                            index_page != "README.md"
    +
    +                            and index_page != "index.md"
    +
    +                            and not os.path.exists(destination_index_page)
    +
    +                        ):
    +
    +                            shutil.copyfile(
    +
    +                                os.path.join(input_dir, index_page), destination_index_page
    +
    +                            )
    +
    +            if config["include_reference_documentation"]:
    +
    +                with yaspin(text="Auto generating reference documentation using pdocs") as spinner:
    +
    +                    if "output_dir" not in config["pdocs"]:
    +
    +                        config["pdocs"]["output_dir"] = os.path.join(input_dir, "reference")
    +
    +                    pdocs(config["pdocs"])
    +
    +                    reference_docs = _nested_docs(config["pdocs"]["output_dir"], input_dir, config)
    +
    +                    nav.append({"Reference": reference_docs})  # type: ignore
    +
    +                    spinner.ok("Done")
    +
    +            with yaspin(text="Rendering complete website from Markdown using MkDocs") as spinner:
    +
    +                mkdocs(config["mkdocs"])
    +
    +                spinner.ok("Done")
    +
    +            # remove any settings pointing to the temp dirs
    +
    +            if config["mkdocs"]["docs_dir"].startswith(input_dir):
    +
    +                del config["mkdocs"]["docs_dir"]
    +
    +            if config["mkdocs"]["site_dir"].startswith(temp_output_dir):
    +
    +                del config["mkdocs"]["site_dir"]
    +
    +            if config["pdocs"]["output_dir"].startswith(input_dir):
    +
    +                del config["pdocs"]["output_dir"]
    +
    +            if config["include_reference_documentation"]:
    +
    +                nav.pop()
    +
    +            yield input_dir, temp_output_dir
    +
    + +
    +

    mkdocs

    +
    def mkdocs(
    +    config: dict
    +)
    +
    + +

    Render the project's associated Markdown documentation using the specified

    +

    MkDocs config passed into the MkDocs build command.

    +

    This rendering is from .md Markdown documents into HTML

    +
    +View Source +
    def mkdocs(config: dict):
    +
    +    """Render the project's associated Markdown documentation using the specified
    +
    +    MkDocs config passed into the MkDocs `build` command.
    +
    +    This rendering is from `.md` Markdown documents into HTML
    +
    +    """
    +
    +    config_instance = _mkdocs_config(config)
    +
    +    return mkdocs_build(config_instance)
    +
    + +
    +

    pdocs

    +
    def pdocs(
    +    config: dict
    +) -> None
    +
    + +

    Render this project using the specified pdoc config passed into pdoc.

    +

    This rendering is from code definition to Markdown so that +it will be compatible with MkDocs.

    +
    +View Source +
    def pdocs(config: dict) -> None:
    +
    +    """Render this project using the specified pdoc config passed into pdoc.
    +
    +    This rendering is from code definition to Markdown so that
    +
    +    it will be compatible with MkDocs.
    +
    +    """
    +
    +    pdocs_as_markdown(**config)
    +
    + +
    + + + + + + +
    +
    + + +
    + +
    + + + + +
    +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..1fdfd3cf --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Outlines This project collects detailed notes as aggregate outlines. Please send pull requests if you notice errors. Purpose Store information in a way that can be easily referenced or updated. Have a destination for information curated during deep projects, especially after they end. Locations praxes - praxis/process oriented information reference - primarly aggregated from another source monographs - my original, observations from data and experiences talks - notes from speakers and events digests - for longer works, if it is worth reading, it is worth taking notes on external - copies of external outlines worth keeping handy logs - freeform summaries, syntheses, etc Github Pages Portray is configured in pyproject.toml requiring the project to have a docs directory for now (maybe there is some hack to get rid of the docs/ top level directory. Rebuilding Rebuild github pages in the ~/code/outlines project root using virtualenv: ~/virtualenvs/portray . publish with the command: portray on_github_pages Rebuild the portray virtualenv by simply installing portray and mkdocs-awesome-pages-plugin . The github pages are rendered with portray and mkdocs-awesome-pages-plugin github pages reference","title":"Home"},{"location":"#outlines","text":"This project collects detailed notes as aggregate outlines. Please send pull requests if you notice errors.","title":"Outlines"},{"location":"#purpose","text":"Store information in a way that can be easily referenced or updated. Have a destination for information curated during deep projects, especially after they end.","title":"Purpose"},{"location":"#locations","text":"praxes - praxis/process oriented information reference - primarly aggregated from another source monographs - my original, observations from data and experiences talks - notes from speakers and events digests - for longer works, if it is worth reading, it is worth taking notes on external - copies of external outlines worth keeping handy logs - freeform summaries, syntheses, etc","title":"Locations"},{"location":"#github-pages","text":"Portray is configured in pyproject.toml requiring the project to have a docs directory for now (maybe there is some hack to get rid of the docs/ top level directory.","title":"Github Pages"},{"location":"#rebuilding","text":"Rebuild github pages in the ~/code/outlines project root using virtualenv: ~/virtualenvs/portray . publish with the command: portray on_github_pages Rebuild the portray virtualenv by simply installing portray and mkdocs-awesome-pages-plugin . The github pages are rendered with portray and mkdocs-awesome-pages-plugin github pages reference","title":"Rebuilding"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/","text":"Installing Semantic Mediawiki with Ansible Requirements: Use old mediawiki production database (upgrade?) Manage installation Manage upgrades Open Source (contribute back for other hackerspaces and other wikis) Manage backups Testable processes Automatically upgrade/configure/manage semantic mediawiki extension and other extensions Requirements We want to use our old database. It would be nice to use semantic mediawiki . We should be able to upgrade and add extensions by redeploying the ansible playbook (idempotency retained) We should install all this stuff with composer The Ansible Composer Module is a preview and doesn't guarantee a backwards compatible API. This should be fine. Composer Install Guide: Install Semantic MediaWiki using Composer General Semantic MediaWiki Install Guide Semantic Mediawiki Source Abount Semantic MediaWiki Questions What RDBMS are we using now? What WikiMedia version are we using now? What WikiMedia extensions are we using now? How does the wiki upgrade process work? Special Considerations? Alternatives to our own ansible playbook WikiMedia has an initiative to simplify wiki deployments called CloudVPS . It is OpenStack powered infrastructure. We want to self-host, but might be able to use their images? A Noisebridge Wiki Upgrade Plan Patrick: \"no more snowflakes\" Trent's Plan Use my servers.yml playbook as a base, available here . Add a premade playbook Make significant modifications to accomodate our needs Hunting for a premade role Success? Google Search A google search for \"ansible role semantic mediawiki\" seemed promising and is summarized below. There are probably more results available by trying more searches. EMWCon Spring 2017 Found here: Using Ansible to create and manage a wiki/wiki farm examples . Very Promising Playbooks from phabricator.mediawiki.org author: Cindy.cicalese Not as promising playbooks from meza it's just old, don't ignore it outright... BlueSpice Enterprise This may be helpful to look over. They have used ansible to deploy their enterprise product . A BlueSpice Playbook . Some Random Playbooks/Roles has releases this year: github.com/yongxinL/ansible-mediawiki OLD: https://github.com/quimgil/ansible-playbook derivative: https://github.com/freephile/ansible-playbook Failed: Ansible Galaxy The playbooks I found here were incomplete and outdated, as usual. Extra ToolForge a hosting environment for developers working on services that provide value to the Wikimedia movement. These services allow developers to easily do ad hoc analytics, administer bots, run webservices, and generally create tools to help editors and other volunteers in their work. The environment also includes access to a variety of data services. References wikimedia production environment guidelines","title":"Ansible Semanticmediawiki Install Notes"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#installing-semantic-mediawiki-with-ansible","text":"Requirements: Use old mediawiki production database (upgrade?) Manage installation Manage upgrades Open Source (contribute back for other hackerspaces and other wikis) Manage backups Testable processes Automatically upgrade/configure/manage semantic mediawiki extension and other extensions","title":"Installing Semantic Mediawiki with Ansible"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#requirements","text":"We want to use our old database. It would be nice to use semantic mediawiki . We should be able to upgrade and add extensions by redeploying the ansible playbook (idempotency retained) We should install all this stuff with composer The Ansible Composer Module is a preview and doesn't guarantee a backwards compatible API. This should be fine. Composer Install Guide: Install Semantic MediaWiki using Composer General Semantic MediaWiki Install Guide Semantic Mediawiki Source Abount Semantic MediaWiki","title":"Requirements"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#questions","text":"What RDBMS are we using now? What WikiMedia version are we using now? What WikiMedia extensions are we using now? How does the wiki upgrade process work? Special Considerations?","title":"Questions"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#alternatives-to-our-own-ansible-playbook","text":"WikiMedia has an initiative to simplify wiki deployments called CloudVPS . It is OpenStack powered infrastructure. We want to self-host, but might be able to use their images?","title":"Alternatives to our own ansible playbook"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#a-noisebridge-wiki-upgrade-plan","text":"Patrick: \"no more snowflakes\"","title":"A Noisebridge Wiki Upgrade Plan"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#trents-plan","text":"Use my servers.yml playbook as a base, available here . Add a premade playbook Make significant modifications to accomodate our needs","title":"Trent's Plan"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#hunting-for-a-premade-role","text":"","title":"Hunting for a premade role"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#success-google-search","text":"A google search for \"ansible role semantic mediawiki\" seemed promising and is summarized below. There are probably more results available by trying more searches.","title":"Success? Google Search"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#emwcon-spring-2017","text":"Found here: Using Ansible to create and manage a wiki/wiki farm examples . Very Promising Playbooks from phabricator.mediawiki.org author: Cindy.cicalese Not as promising playbooks from meza it's just old, don't ignore it outright...","title":"EMWCon Spring 2017"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#bluespice-enterprise","text":"This may be helpful to look over. They have used ansible to deploy their enterprise product . A BlueSpice Playbook .","title":"BlueSpice Enterprise"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#some-random-playbooksroles","text":"has releases this year: github.com/yongxinL/ansible-mediawiki OLD: https://github.com/quimgil/ansible-playbook derivative: https://github.com/freephile/ansible-playbook","title":"Some Random Playbooks/Roles"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#failed-ansible-galaxy","text":"The playbooks I found here were incomplete and outdated, as usual.","title":"Failed: Ansible Galaxy"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#extra","text":"ToolForge a hosting environment for developers working on services that provide value to the Wikimedia movement. These services allow developers to easily do ad hoc analytics, administer bots, run webservices, and generally create tools to help editors and other volunteers in their work. The environment also includes access to a variety of data services.","title":"Extra"},{"location":"docs/digests/ansible-semanticmediawiki-install-notes/#references","text":"wikimedia production environment guidelines","title":"References"},{"location":"docs/digests/artofwar13_spies/","text":"Chapter 13: Spies A summary of Sun Tzu Chapter 13. Source: https://suntzusaid.com/book/13 More footnotes: http://www.sacred-texts.com/tao/aow/aow21.htm Also try to find the remarks of Frederick the Great on spies. Also see the Military Memoirs and maxims of Marshal Turenne. Notes The word 'spy' is not an excellent translation for this chapter, te term is broader. Apparently there is some history between the chinese word for \"spy\" and the word for \"a crack in the door between which the moonlight can slip\". So the context of this document must be adjusted. Additionally, there is something about it meaing \"a crack or a chink\", so this is probably related to the modern computer concepts of bugs and cracking an enemy's loyalty strategies and other parts of his personnell substrate not fully under his control. \"Divine Manipulation\" == Control . This definition probably relates to the definitions of control we give to performers rather than coercive power. Another translation recommends that 'doomed' spies are also enemy spies who are fed false information, but this is disputed. Another translation of \"pay spies generously\" is to also \"show them complete trust in their work\" Tu Mu added a warning: \"Just as water, which carries a boat from bank to bank, may also be the means of sinking it, so reliance on spies, while productive of great results, is oft-times the cause of utter destruction.\" Chia Lin added: \"An army without spies is like a man without ears or eyes.\" Summary If your objective has a high ongoing and total cost, don't try to save a fraction of the daily cost in payments, e.g. \"emoluments\" and \"honors\" for information. Foreknowledge of an opponent cannot come from calculation, mystics, or experience. Foreknowledge of an opponent can only come from other people. Five Classes of Spies local: inhabitants of a opponent district inward: officials of the opponent converted: enemy spies turned by bribe carrot or stick doomed: deceive your own spies who are then captured by the enemy and report false information. the enemy will kill this spy when their information is found to be false. surviving: a traditional spy, seek and bring back news from the enemy camp an apparent fool with a will of iron and keen intellect active, robust, strng, courageous accustomed to dirty work, able to endure hunger and cold able to put up with and ignominy The \"divine manipulation of the threads\" is having all five kinds of spies at work at once. Claimed to be \"the soverign's most precious faculty\" as well as \"an undiscoverable secret system\". The relationship with spies is the most intimate in the army. They should be the most well rewarded and should have the highest level of secrecy. Employ spies with wisdom, Manage them with benevolence and straightforwardness as necessary. Without \"subtle ingenuity\" you cannot trust your spies. Use your spies for every kind of business. \"Be subtle! Be Subtle!\" If a spy reveals news before you need it, kill the spy and the recepient of the knowledge. Get the names of: attendants aides-de-camp door-keepers and sentries of the leader The 'converted' spy has information which is the source of 'inward' and 'local' spies. Create 'converted' spies with bribes, housing. Goal: Knowledge of your opponent. The 'converted' spy is the foundation of this knowledge. Therefore, the 'converted' spy is treated with the \"utmost liberality\". Spies are a more important element in water because the army's ability to move depends on them.","title":"Artofwar13 Spies"},{"location":"docs/digests/artofwar13_spies/#chapter-13-spies","text":"A summary of Sun Tzu Chapter 13. Source: https://suntzusaid.com/book/13 More footnotes: http://www.sacred-texts.com/tao/aow/aow21.htm Also try to find the remarks of Frederick the Great on spies. Also see the Military Memoirs and maxims of Marshal Turenne.","title":"Chapter 13: Spies"},{"location":"docs/digests/artofwar13_spies/#notes","text":"The word 'spy' is not an excellent translation for this chapter, te term is broader. Apparently there is some history between the chinese word for \"spy\" and the word for \"a crack in the door between which the moonlight can slip\". So the context of this document must be adjusted. Additionally, there is something about it meaing \"a crack or a chink\", so this is probably related to the modern computer concepts of bugs and cracking an enemy's loyalty strategies and other parts of his personnell substrate not fully under his control. \"Divine Manipulation\" == Control . This definition probably relates to the definitions of control we give to performers rather than coercive power. Another translation recommends that 'doomed' spies are also enemy spies who are fed false information, but this is disputed. Another translation of \"pay spies generously\" is to also \"show them complete trust in their work\" Tu Mu added a warning: \"Just as water, which carries a boat from bank to bank, may also be the means of sinking it, so reliance on spies, while productive of great results, is oft-times the cause of utter destruction.\" Chia Lin added: \"An army without spies is like a man without ears or eyes.\"","title":"Notes"},{"location":"docs/digests/artofwar13_spies/#summary","text":"If your objective has a high ongoing and total cost, don't try to save a fraction of the daily cost in payments, e.g. \"emoluments\" and \"honors\" for information. Foreknowledge of an opponent cannot come from calculation, mystics, or experience. Foreknowledge of an opponent can only come from other people. Five Classes of Spies local: inhabitants of a opponent district inward: officials of the opponent converted: enemy spies turned by bribe carrot or stick doomed: deceive your own spies who are then captured by the enemy and report false information. the enemy will kill this spy when their information is found to be false. surviving: a traditional spy, seek and bring back news from the enemy camp an apparent fool with a will of iron and keen intellect active, robust, strng, courageous accustomed to dirty work, able to endure hunger and cold able to put up with and ignominy The \"divine manipulation of the threads\" is having all five kinds of spies at work at once. Claimed to be \"the soverign's most precious faculty\" as well as \"an undiscoverable secret system\". The relationship with spies is the most intimate in the army. They should be the most well rewarded and should have the highest level of secrecy. Employ spies with wisdom, Manage them with benevolence and straightforwardness as necessary. Without \"subtle ingenuity\" you cannot trust your spies. Use your spies for every kind of business. \"Be subtle! Be Subtle!\" If a spy reveals news before you need it, kill the spy and the recepient of the knowledge. Get the names of: attendants aides-de-camp door-keepers and sentries of the leader The 'converted' spy has information which is the source of 'inward' and 'local' spies. Create 'converted' spies with bribes, housing. Goal: Knowledge of your opponent. The 'converted' spy is the foundation of this knowledge. Therefore, the 'converted' spy is treated with the \"utmost liberality\". Spies are a more important element in water because the army's ability to move depends on them.","title":"Summary"},{"location":"docs/digests/becoming_a_magician/","text":"Becoming A Magician Inspired by Becoming a Magician any significantly advanced technologist seems like a magician imagine a version of myself that i cannot yet understand you would simply have to step back and build something completely different altogether magic is competence is so far advanced from your confidence with such alien mental models that you cannot predict the outcome of the models at all. people typically try to \"double down on what worked\" which means wringing more value out of the same mental models, tools, and processes The way to extraordinary growth and changes often involves a fundamental ontological or \u2018lens\u2019 shift in how you see the world. Magicians are wearing not just better, but fundamentally differently shaped lenses to the rest of us. Meeting magicians is the first step to becoming one \u2013 when you are attempting to learn implicit knowledge that by definition you don\u2019t understand, it is important to have a bunch of examples in front of you to feed your brain\u2019s pattern-recognition systems. Concrete steps I take to find them include asking my most interesting friends to introduce me to their most interesting friends, going down similar rabbit holes with the bibliographies of books that excite me, and generally living in \u2018explore\u2019 mode at various points in life, while recognising that not every avenue will lead to a jackpot. Questions I like to ask myself include: - \u2018What is the most capable version of me that I can imagine?\u2019 - \u2018What would I be like/spend my time doing if all my current major problems had been solved?\u2019 - \u2018What are the things I say I value but don\u2019t act as if I value, and what would my life feel like on inside if I actually acted as if I valued those things?\u2019 - \u2018What am I afraid of doing, and what would my life be like if I wasn\u2019t afraid of doing those things?\u2019. author refers to a \"nonlinear strategy\", what they mean is a strategy that cannot be extrapolated from your current artifacts, methods, language, and training (engelbart H-LAM/T) Conclusions daily grow/explore your graph of interesting people deeply and broadly build an engine to build new whole sets of mental models generate new language and artifacts and methods and training i think i stick to methods too much, i need to be inventive with all 4 surround myself with magicians who do the magic i want to do References Engelbart \"Augmenting Human Intellect - H-LAM/T\" naive Vision for myself Before taking the advice of the post, here are some thoughts about what I would value. The post explains that you have to write a version of yourself you cannot imagine, so you cannot write within your existing constraints. Therefore, the below goals are naively small and close to who I am and what I could start doing today. reimplementing and contributing to core oss tools, lisps and vim etc. breaking new ground on terminal and tui as a first class citizen of a graphical window manager no constraints from physical space to walk in and start drafting 3d art in some scad-clj derivative or composite tools no frustrating time constraints to learn the needed skills to produce art no frustrating time constraints to maintain a 90 minute x 6 day fitness routine with low impact and no real risk of injury (not running outdoors) need to add an elliptical at home, eventually a treadmill? increase my transit range while still maintaining the level of simplicity, increase access to tools live somewhere turnkey, never want to think about stress or logistics or traffic or weather if possible expand my thinking more, sure i have done that a lot, but on what dimensions haven't i (beginner's mind and assimilating new skills) pick up inspiring old ideas and write them out to their blockers","title":"Becoming A Magician"},{"location":"docs/digests/becoming_a_magician/#becoming-a-magician","text":"","title":"Becoming A Magician"},{"location":"docs/digests/becoming_a_magician/#inspired-by","text":"Becoming a Magician any significantly advanced technologist seems like a magician imagine a version of myself that i cannot yet understand you would simply have to step back and build something completely different altogether magic is competence is so far advanced from your confidence with such alien mental models that you cannot predict the outcome of the models at all. people typically try to \"double down on what worked\" which means wringing more value out of the same mental models, tools, and processes The way to extraordinary growth and changes often involves a fundamental ontological or \u2018lens\u2019 shift in how you see the world. Magicians are wearing not just better, but fundamentally differently shaped lenses to the rest of us. Meeting magicians is the first step to becoming one \u2013 when you are attempting to learn implicit knowledge that by definition you don\u2019t understand, it is important to have a bunch of examples in front of you to feed your brain\u2019s pattern-recognition systems. Concrete steps I take to find them include asking my most interesting friends to introduce me to their most interesting friends, going down similar rabbit holes with the bibliographies of books that excite me, and generally living in \u2018explore\u2019 mode at various points in life, while recognising that not every avenue will lead to a jackpot. Questions I like to ask myself include: - \u2018What is the most capable version of me that I can imagine?\u2019 - \u2018What would I be like/spend my time doing if all my current major problems had been solved?\u2019 - \u2018What are the things I say I value but don\u2019t act as if I value, and what would my life feel like on inside if I actually acted as if I valued those things?\u2019 - \u2018What am I afraid of doing, and what would my life be like if I wasn\u2019t afraid of doing those things?\u2019. author refers to a \"nonlinear strategy\", what they mean is a strategy that cannot be extrapolated from your current artifacts, methods, language, and training (engelbart H-LAM/T)","title":"Inspired by"},{"location":"docs/digests/becoming_a_magician/#conclusions","text":"daily grow/explore your graph of interesting people deeply and broadly build an engine to build new whole sets of mental models generate new language and artifacts and methods and training i think i stick to methods too much, i need to be inventive with all 4 surround myself with magicians who do the magic i want to do","title":"Conclusions"},{"location":"docs/digests/becoming_a_magician/#references","text":"Engelbart \"Augmenting Human Intellect - H-LAM/T\"","title":"References"},{"location":"docs/digests/becoming_a_magician/#naive-vision-for-myself","text":"Before taking the advice of the post, here are some thoughts about what I would value. The post explains that you have to write a version of yourself you cannot imagine, so you cannot write within your existing constraints. Therefore, the below goals are naively small and close to who I am and what I could start doing today. reimplementing and contributing to core oss tools, lisps and vim etc. breaking new ground on terminal and tui as a first class citizen of a graphical window manager no constraints from physical space to walk in and start drafting 3d art in some scad-clj derivative or composite tools no frustrating time constraints to learn the needed skills to produce art no frustrating time constraints to maintain a 90 minute x 6 day fitness routine with low impact and no real risk of injury (not running outdoors) need to add an elliptical at home, eventually a treadmill? increase my transit range while still maintaining the level of simplicity, increase access to tools live somewhere turnkey, never want to think about stress or logistics or traffic or weather if possible expand my thinking more, sure i have done that a lot, but on what dimensions haven't i (beginner's mind and assimilating new skills) pick up inspiring old ideas and write them out to their blockers","title":"naive Vision for myself"},{"location":"docs/digests/compilers-ch1-the-dragon-book/","text":"Compilers ~ The Dragon Book - 1986 Chapter 1 - Introduction to Compiling On the general subject of compiling. Contents components of a compiler environment in which a compiler does its job tools to make it easier to build compilers 1.1 Compilers compiler - a program that reads a program written in the source language and translates it into an equivalent target program in the target language . The compiler reports errors in the source program as error messages . \"basic tasks\" all compilers perform \"are the same\" Thousands of source languages Target languages include Another programming language Machine language of any computer (microprocessor to supercomputer) Some compiler classifications - based on structure or function single-pass multi-pass load-and-go debugging optimizing etc. advances in compilers: implementation languages programming environments software tools The Analysis-Synthesis Model of Compilation The 2 parts of compilation are analysis and synthesis . Analysis - Break the source program into pieces and create an intermediate representation of the source program . Synthesis - Construct the target program from the intermediate representation * requires the most specialized techniques Analysis Operations of source program are determined & recorded in a tree, (hierarchical structure). Often a syntax tree node == operation children of node == arguments of operation in the text diagram, operations can be arguments: position := initial + rate * 60 Many software tools that manipulate source programs first perform some kind of analysis Structure Editors - text editor + autocomplete + linter + static analysis + etc. real-time partial analysis Pretty Printers - structure viewer for humans Static Checkers - attempt to discover potential bugs without running the program. Similar to optimizing compilers . code that cannot be executed in the course of the program variable used before defined catch logical errors (type checking / use real variable as pointer) Interpreters - Instead of producing target program , perform the operations implied by source program Compilers aren't just for machine code The analysis portion of compiling shows up in these examples: Text formatters - Format text for output in a textual format Silicon compilers - Input is a conventional programming source language . Variables represent signals or signal groups in switching circuits. Outputs a circuit design in an appropriate target language Query interpreters - translates a predicate containing relational and boolean operators into commands to search a database for records satisfying the predicate The Context of a Compiler Other programs may be needed to create the executable target program. A preprocessor might: collect parts of the source program stored in separate files expand macros into source language statements. See fig 1.3 page 4. A target program may require further processing to run. assembler - translate assembly to machine code linker - link to library routines 1.2 Analysis of the source program Introducing analysis and illustrate its use in some text-formatting languages . Also see chapters 2-4, 6. Three Phases of Analysis Linear Analysis AKA: lexical analysis or scanning read stream of source program left-to-right and group into tokens , streams of characters, with collective meaning Hierarchical Analysis AKA: syntax analysis or parsing hierarchically group characters/tokens into meaningful nested collections Semantic Analysis find semantic errors, identify operands, type checking check that components of a program fit together meaningfully Lexical Analysis Linear analysis is called lexical analysis or scanning . See example page 5. Create tokens from the source program stream. Discard separators, e.g. whitespace. Syntax Analysis Hierarchical Analsysis is called parsing or syntax analysis . Group the tokens into grammatical phrases for the compiler to synthesize output. Usually the grammatical phrases are represented by a parse tree or a syntax tree . parse tree - statements , expressions , and identifers are all nodes. A precise definition is not given, see fig. 1.4, page 6. syntax tree - Compressed representation of a parse tree. Operators appear as interior nodes and operands are the children of that operator's node. See Section 5.2 . There is a good example here, page 6. expressions , recursive rules , (nonrecursive) basis rules , and definition rules , and statements are described in the example but not introduced as formal terms. The division between lexical and syntactic analysis is somewhat arbitrary. We usually choose a division that simplifies the overall task of analysis. Factors for division between lexical and syntactic analysis: Is the source language construct recursive or not? Lexical constructs - do not require recursion . identifiers - strings of letters+digits beginning with a letter recursion not necessary to recognize identifiers , typically scan until non-(letter+number) and group back to beginning the grouped characters are recorded in a symbol table and removed from the input (so the pointer is back at the beginning) the next token is then processed. Syntactic constructs often require recursion . linear scan cannot analyze expressions or statements cannot match parentheses in expressions cannot match begin and end in statements unless there is a hierarchical or nesting structure ON the input Context-free grammars - formalization of recursive rule that can be used to guide syntactic analysis See chapter 2 for introduction, chapter 4 for extensive treatment. Syntax-directed translation The compiler uses the hierarchical structure on the input to help generate the output . See: Chapters 2, 5. Semantic Analysis check source program for semantic errors gather type information for subsequent code-generation phase use hierarchical structure determined by syntax-analysis phase to identify operators and operands of expressions and statements type checking : compiler checks that each operator has permitted operands based on source language specification. Must also check for operator coercions. Part of semantic analysis , see ch. 6. example: binary arithmetic operator applied to integer & real, converts integer to real, see example 1.1 and fig. 1.5 inttoreal Analysis in Text Formatters TEX uses hierarchical arrangement in boxes as part of the syntax analysis to describe the relative position of groups of vertical and horizontal characters. See p.8-9 for fig 1.6-1.7. 1.3 The Phases of a Compiler A compiler operates in conceptual phases . Each transforms the source program from one representation to another. Some phases may be grouped together. Intermediate representations between grouped phases need not be explicity constructed. See fig. 1.9, page 10 for a \"typical decomposition of a compiler\". Phases There are six phases between source program and target program : Lexical Analyzer Syntax Analyzer Semantic Analyzer Intermediate Code Generator Code Optimizer Code Generator See figure 1.10 , page 13, for a detailed translation of position := initial + rate * 60 . Supplementary Phases (used during every phase) Symbol-table manager Error handler Symbol-Table Management Symbol Table : data structure containing a record for each identifier with fields for the attributes of the identifier. Quickly find, store, and retrieve data for that identifier. The identifier is added by the lexical analyzer but the identifier's attributes are typically added and consumed during later phases. An attribute could be something like storage, scope, type. If the identifier is a procedure: perhaps number and type of arguments, method of passing arguments (by reference, etc.), and type returned, if any. See chapters: 2, 7 for more about symbol tables. Error Detection and Reporting Each phase must encounter and deal with errors, and potentially proceed. The syntax analyzer and semantic analyzer typically handle a large fraction of errors. The lexical analyzer may encounter errors when remaining characters do not form a token. The syntax analyser finds errors where the token stream violates the structure rules. The semantic analyzer can find errors where a meaningless operation occurs, e.g. add an array to the name of a procedure. Further discussion of errors for each phase is included in the part of the book devoted to that phase. The Analysis Phase As translation progresses, the compiler's representatin of the source program changes. note: In this diagram and chapter, the intermediate representation is considered/proxied as the syntax tree and symbol table . The data structure for the tree in fig. 1.10 is shown in fig. 1.11b . Lexical analysis is covered in chapter 3. Intermediate Code Generation Some compilers generate an explicit intermediate representation of the source program , \"a program for an abstract machine\". Variety of forms. Chapter 8 covers principle intermediate representations in compilers. Chapters 5, 8 cover algorithms for generating intermedaite code for typical programming language constructs. Properties of an intermediate representation easy to produce easy to translate into the target program Three-address code Three-address code consists of a sequence of instructions, each of which has at most three operands. Assembly language for a machine in which every memory location can act like a register. Code Optimization Goal: improve intermediate code. Simple example on pages 14-15. Chapter 9 discusses simple optimizations. Chapter 10 gives technology used by most powerful optimizing compilers. Code Generation Goal: generate target code from intermediate code . Normally this gives relocateable machine code or assembly code . A crucial aspect is assignment of variables to registers. Simple example on pages 15-16. Chapter 9 covers code generation. 1.4 Cousins of the Compiler This section is about a compiler's typical operating context. Preprocessors Produce the input to compilers. Everything here seems to boil down to macros. Macro processing : allow user to define macros as shorhand for longer constructs. File inclusion : include header files into the program text, e.g. in c language : #include is replaced by the contents of global.h \"Rational\" preprocessors : Add capabilities to a language, especially for flow control and data structures. Same as macros functionally? Language Extensions : More macros, different use. See example in book. Example 1.2 on page 16. Assemblers Assembly code is a mnemonic version of machine code , where names are used instead of binary codes for operations . Names are also given to memory addresses . It is customary for assembly languages to have macro facilities that are similar to those in the macro preprocessors described above. Two-pass Assembly Simple assemblers make two passes over the input file, where a pass reads a input file once. The first pass finds and stores identifiers , assigning storage locations in the symbol table . The second pass translates operation code into the bits representing that operation in machine language. It also translates each identifier intot he address given for that identifier in the symbol table . The output of the second pass is usually relocateable machine code , which means it can be loaded starting in any memory location, L, in memory. If L is added to all addresses in the code, all references will be correct. Thus, the output of the assembler must distinguish those portions of instructions that refer to addresses that can be relocated. See example 3, page 18-19. Loaders and Link-editors A loader usually performs both loading and link-editing . loading : Taking relocateable machine code, altering the relocateable address, and placing the altered instructions and data in memory at the proper locations. link-editor : Make a single program from several files of relocateable machine code. Many of the files result from separate compiles, and often are stored in separate locations for system-wide use. e.g. libraries. external reference : code in one file references a location in another file. May be data or an entry point to a procedure. relocateable machine code file must retain the information in the symbol table for: each data location defined in one file and used in another each entry point of a procedure defined in one file and used in another if not known in advance, must include entire symbol table as part of relocateable machine code 1.5 The Grouping of Phases Multiple phases are often grouped together in compiler implementations. Front and Back Ends Front end : largely independent of target machine, based on source language lexical analysis syntactic analysis symbol table creation semantic analysis generate intermediate code Back end : code optimization code generation error handling symbol table operations Fairly routine: keep the front end of a compiler and redo the back end for another machine. Parts of the back end can even be kept. Further discussion in Chapter 9. It is also tempting to compile several different languages into the same intermediate language and use a common back end for the different front ends, thereby obtaining several compilers for one machine. However, because of subtle differences in the viewpoints of different languages, there has been only limited success in this direction. Passes Many phases can be done in one pass. Organizing phases into passes is complex and discussed for some specific implementations in chapter 12. The whole back end may be one pass, immedately producing intermediate code . We may think of the syntax analyzer as being 'in charge'. As it discovers grammatical structure, the parser can call intermediate code generation. See chapter 2 for a compiler with this implementation. Reducing the Number of Passes Goal: Have relatively few passes. Goal: Don't use up all the system memory. Reconciling these could create tension. The interface between the lexical and syntactic analyzers can often be limited to a single token. It is often very hard to perform code generation until the intermediate representation has been completely generated. backpatching : merge intermediate code and target code generation can often be merged into one pass by creating a slot and filling it once the information becomes available. See the example, page 21. To ensure you do not use too much space, you can reduce the distance over which backpatching occurs. 1.6 Compiler-Construction Tools Chapter eleven discusses software tools for implementing a compiler. There are specialized tools for implementing various phases of a compiler These tools are called variously: compiler-compilers compiler-generators translator-writing systems Specialized tools are typically oriented around a model of languages and are suitable for languages following that model. Tools exist for automatic design of specific compiler components , they use specialized languages for specifying and implementing the component. The most successful hide details of generation algorithm and make components that are easily integrated into the remainder of the compiler. A list of compiler construction tools Parser generators : produce syntax analyzers normally from in put based on context-free grammar . Syntax analysis used to be very time consuming but now is \"one of the easiest phases to implement\". Often parser generators use parsing algorithms too complex to do by hand. Scanner generators : automatically generate lexical analyzers , normally from a specification based on regular expressions . The lexical analyzer is effectively a finite automaton . See chapter 3 , implementations in section 3.5, section 3.8 . Syntax-directed translation engines : produce collections of routines that walk the parse tree, generating intermediate code . One or more translations are associated with each node of the parse tree, each translation defined in terms of its neighbor nodes in the tree. See chapter 5. Automatic code generators : take a collection of rules defining intermediate language -> target language and replace the intermediate rules with templates that represent sequences of machine instructions. Something about tiling intermediate code without a combinatorial explosion in compiler running time. See chapter 9. Data-flow engines : data flow analysis is used in optimization. How are values transmitted from one part of a program to each other part? Especially as the user defines relationships between intermediate code statements and the information being gathered. See Section 10.11. Bibliographic Notes Lots of parallel discovery, hard to attribute credit. Page 23-24 have references.","title":"Compilers Ch1 The Dragon Book"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#compilers-the-dragon-book-1986","text":"","title":"Compilers ~ The Dragon Book - 1986"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#chapter-1-introduction-to-compiling","text":"On the general subject of compiling.","title":"Chapter 1 - Introduction to Compiling"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#contents","text":"components of a compiler environment in which a compiler does its job tools to make it easier to build compilers","title":"Contents"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#11-compilers","text":"compiler - a program that reads a program written in the source language and translates it into an equivalent target program in the target language . The compiler reports errors in the source program as error messages . \"basic tasks\" all compilers perform \"are the same\" Thousands of source languages Target languages include Another programming language Machine language of any computer (microprocessor to supercomputer) Some compiler classifications - based on structure or function single-pass multi-pass load-and-go debugging optimizing etc. advances in compilers: implementation languages programming environments software tools","title":"1.1 Compilers"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#the-analysis-synthesis-model-of-compilation","text":"The 2 parts of compilation are analysis and synthesis . Analysis - Break the source program into pieces and create an intermediate representation of the source program . Synthesis - Construct the target program from the intermediate representation * requires the most specialized techniques","title":"The Analysis-Synthesis Model of Compilation"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#analysis","text":"Operations of source program are determined & recorded in a tree, (hierarchical structure). Often a syntax tree node == operation children of node == arguments of operation in the text diagram, operations can be arguments: position := initial + rate * 60 Many software tools that manipulate source programs first perform some kind of analysis Structure Editors - text editor + autocomplete + linter + static analysis + etc. real-time partial analysis Pretty Printers - structure viewer for humans Static Checkers - attempt to discover potential bugs without running the program. Similar to optimizing compilers . code that cannot be executed in the course of the program variable used before defined catch logical errors (type checking / use real variable as pointer) Interpreters - Instead of producing target program , perform the operations implied by source program","title":"Analysis"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#compilers-arent-just-for-machine-code","text":"The analysis portion of compiling shows up in these examples: Text formatters - Format text for output in a textual format Silicon compilers - Input is a conventional programming source language . Variables represent signals or signal groups in switching circuits. Outputs a circuit design in an appropriate target language Query interpreters - translates a predicate containing relational and boolean operators into commands to search a database for records satisfying the predicate","title":"Compilers aren't just for machine code"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#the-context-of-a-compiler","text":"Other programs may be needed to create the executable target program. A preprocessor might: collect parts of the source program stored in separate files expand macros into source language statements. See fig 1.3 page 4. A target program may require further processing to run. assembler - translate assembly to machine code linker - link to library routines","title":"The Context of a Compiler"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#12-analysis-of-the-source-program","text":"Introducing analysis and illustrate its use in some text-formatting languages . Also see chapters 2-4, 6.","title":"1.2 Analysis of the source program"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#three-phases-of-analysis","text":"Linear Analysis AKA: lexical analysis or scanning read stream of source program left-to-right and group into tokens , streams of characters, with collective meaning Hierarchical Analysis AKA: syntax analysis or parsing hierarchically group characters/tokens into meaningful nested collections Semantic Analysis find semantic errors, identify operands, type checking check that components of a program fit together meaningfully","title":"Three Phases of Analysis"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#lexical-analysis","text":"Linear analysis is called lexical analysis or scanning . See example page 5. Create tokens from the source program stream. Discard separators, e.g. whitespace.","title":"Lexical Analysis"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#syntax-analysis","text":"Hierarchical Analsysis is called parsing or syntax analysis . Group the tokens into grammatical phrases for the compiler to synthesize output. Usually the grammatical phrases are represented by a parse tree or a syntax tree . parse tree - statements , expressions , and identifers are all nodes. A precise definition is not given, see fig. 1.4, page 6. syntax tree - Compressed representation of a parse tree. Operators appear as interior nodes and operands are the children of that operator's node. See Section 5.2 . There is a good example here, page 6. expressions , recursive rules , (nonrecursive) basis rules , and definition rules , and statements are described in the example but not introduced as formal terms. The division between lexical and syntactic analysis is somewhat arbitrary. We usually choose a division that simplifies the overall task of analysis.","title":"Syntax Analysis"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#factors-for-division-between-lexical-and-syntactic-analysis","text":"Is the source language construct recursive or not? Lexical constructs - do not require recursion . identifiers - strings of letters+digits beginning with a letter recursion not necessary to recognize identifiers , typically scan until non-(letter+number) and group back to beginning the grouped characters are recorded in a symbol table and removed from the input (so the pointer is back at the beginning) the next token is then processed. Syntactic constructs often require recursion . linear scan cannot analyze expressions or statements cannot match parentheses in expressions cannot match begin and end in statements unless there is a hierarchical or nesting structure ON the input Context-free grammars - formalization of recursive rule that can be used to guide syntactic analysis See chapter 2 for introduction, chapter 4 for extensive treatment.","title":"Factors for division between lexical and syntactic analysis:"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#syntax-directed-translation","text":"The compiler uses the hierarchical structure on the input to help generate the output . See: Chapters 2, 5.","title":"Syntax-directed translation"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#semantic-analysis","text":"check source program for semantic errors gather type information for subsequent code-generation phase use hierarchical structure determined by syntax-analysis phase to identify operators and operands of expressions and statements type checking : compiler checks that each operator has permitted operands based on source language specification. Must also check for operator coercions. Part of semantic analysis , see ch. 6. example: binary arithmetic operator applied to integer & real, converts integer to real, see example 1.1 and fig. 1.5 inttoreal","title":"Semantic Analysis"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#analysis-in-text-formatters","text":"TEX uses hierarchical arrangement in boxes as part of the syntax analysis to describe the relative position of groups of vertical and horizontal characters. See p.8-9 for fig 1.6-1.7.","title":"Analysis in Text Formatters"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#13-the-phases-of-a-compiler","text":"A compiler operates in conceptual phases . Each transforms the source program from one representation to another. Some phases may be grouped together. Intermediate representations between grouped phases need not be explicity constructed. See fig. 1.9, page 10 for a \"typical decomposition of a compiler\".","title":"1.3 The Phases of a Compiler"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#phases","text":"There are six phases between source program and target program : Lexical Analyzer Syntax Analyzer Semantic Analyzer Intermediate Code Generator Code Optimizer Code Generator See figure 1.10 , page 13, for a detailed translation of position := initial + rate * 60 .","title":"Phases"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#supplementary-phases-used-during-every-phase","text":"Symbol-table manager Error handler","title":"Supplementary Phases (used during every phase)"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#symbol-table-management","text":"Symbol Table : data structure containing a record for each identifier with fields for the attributes of the identifier. Quickly find, store, and retrieve data for that identifier. The identifier is added by the lexical analyzer but the identifier's attributes are typically added and consumed during later phases. An attribute could be something like storage, scope, type. If the identifier is a procedure: perhaps number and type of arguments, method of passing arguments (by reference, etc.), and type returned, if any. See chapters: 2, 7 for more about symbol tables.","title":"Symbol-Table Management"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#error-detection-and-reporting","text":"Each phase must encounter and deal with errors, and potentially proceed. The syntax analyzer and semantic analyzer typically handle a large fraction of errors. The lexical analyzer may encounter errors when remaining characters do not form a token. The syntax analyser finds errors where the token stream violates the structure rules. The semantic analyzer can find errors where a meaningless operation occurs, e.g. add an array to the name of a procedure. Further discussion of errors for each phase is included in the part of the book devoted to that phase.","title":"Error Detection and Reporting"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#the-analysis-phase","text":"As translation progresses, the compiler's representatin of the source program changes. note: In this diagram and chapter, the intermediate representation is considered/proxied as the syntax tree and symbol table . The data structure for the tree in fig. 1.10 is shown in fig. 1.11b . Lexical analysis is covered in chapter 3.","title":"The Analysis Phase"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#intermediate-code-generation","text":"Some compilers generate an explicit intermediate representation of the source program , \"a program for an abstract machine\". Variety of forms. Chapter 8 covers principle intermediate representations in compilers. Chapters 5, 8 cover algorithms for generating intermedaite code for typical programming language constructs.","title":"Intermediate Code Generation"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#properties-of-an-intermediate-representation","text":"easy to produce easy to translate into the target program","title":"Properties of an intermediate representation"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#three-address-code","text":"Three-address code consists of a sequence of instructions, each of which has at most three operands. Assembly language for a machine in which every memory location can act like a register.","title":"Three-address code"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#code-optimization","text":"Goal: improve intermediate code. Simple example on pages 14-15. Chapter 9 discusses simple optimizations. Chapter 10 gives technology used by most powerful optimizing compilers.","title":"Code Optimization"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#code-generation","text":"Goal: generate target code from intermediate code . Normally this gives relocateable machine code or assembly code . A crucial aspect is assignment of variables to registers. Simple example on pages 15-16. Chapter 9 covers code generation.","title":"Code Generation"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#14-cousins-of-the-compiler","text":"This section is about a compiler's typical operating context.","title":"1.4 Cousins of the Compiler"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#preprocessors","text":"Produce the input to compilers. Everything here seems to boil down to macros. Macro processing : allow user to define macros as shorhand for longer constructs. File inclusion : include header files into the program text, e.g. in c language : #include is replaced by the contents of global.h \"Rational\" preprocessors : Add capabilities to a language, especially for flow control and data structures. Same as macros functionally? Language Extensions : More macros, different use. See example in book. Example 1.2 on page 16.","title":"Preprocessors"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#assemblers","text":"Assembly code is a mnemonic version of machine code , where names are used instead of binary codes for operations . Names are also given to memory addresses . It is customary for assembly languages to have macro facilities that are similar to those in the macro preprocessors described above.","title":"Assemblers"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#two-pass-assembly","text":"Simple assemblers make two passes over the input file, where a pass reads a input file once. The first pass finds and stores identifiers , assigning storage locations in the symbol table . The second pass translates operation code into the bits representing that operation in machine language. It also translates each identifier intot he address given for that identifier in the symbol table . The output of the second pass is usually relocateable machine code , which means it can be loaded starting in any memory location, L, in memory. If L is added to all addresses in the code, all references will be correct. Thus, the output of the assembler must distinguish those portions of instructions that refer to addresses that can be relocated. See example 3, page 18-19.","title":"Two-pass Assembly"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#loaders-and-link-editors","text":"A loader usually performs both loading and link-editing . loading : Taking relocateable machine code, altering the relocateable address, and placing the altered instructions and data in memory at the proper locations. link-editor : Make a single program from several files of relocateable machine code. Many of the files result from separate compiles, and often are stored in separate locations for system-wide use. e.g. libraries. external reference : code in one file references a location in another file. May be data or an entry point to a procedure. relocateable machine code file must retain the information in the symbol table for: each data location defined in one file and used in another each entry point of a procedure defined in one file and used in another if not known in advance, must include entire symbol table as part of relocateable machine code","title":"Loaders and Link-editors"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#15-the-grouping-of-phases","text":"Multiple phases are often grouped together in compiler implementations.","title":"1.5 The Grouping of Phases"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#front-and-back-ends","text":"Front end : largely independent of target machine, based on source language lexical analysis syntactic analysis symbol table creation semantic analysis generate intermediate code Back end : code optimization code generation error handling symbol table operations Fairly routine: keep the front end of a compiler and redo the back end for another machine. Parts of the back end can even be kept. Further discussion in Chapter 9. It is also tempting to compile several different languages into the same intermediate language and use a common back end for the different front ends, thereby obtaining several compilers for one machine. However, because of subtle differences in the viewpoints of different languages, there has been only limited success in this direction.","title":"Front and Back Ends"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#passes","text":"Many phases can be done in one pass. Organizing phases into passes is complex and discussed for some specific implementations in chapter 12. The whole back end may be one pass, immedately producing intermediate code . We may think of the syntax analyzer as being 'in charge'. As it discovers grammatical structure, the parser can call intermediate code generation. See chapter 2 for a compiler with this implementation.","title":"Passes"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#reducing-the-number-of-passes","text":"Goal: Have relatively few passes. Goal: Don't use up all the system memory. Reconciling these could create tension. The interface between the lexical and syntactic analyzers can often be limited to a single token. It is often very hard to perform code generation until the intermediate representation has been completely generated. backpatching : merge intermediate code and target code generation can often be merged into one pass by creating a slot and filling it once the information becomes available. See the example, page 21. To ensure you do not use too much space, you can reduce the distance over which backpatching occurs.","title":"Reducing the Number of Passes"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#16-compiler-construction-tools","text":"Chapter eleven discusses software tools for implementing a compiler. There are specialized tools for implementing various phases of a compiler These tools are called variously: compiler-compilers compiler-generators translator-writing systems Specialized tools are typically oriented around a model of languages and are suitable for languages following that model. Tools exist for automatic design of specific compiler components , they use specialized languages for specifying and implementing the component. The most successful hide details of generation algorithm and make components that are easily integrated into the remainder of the compiler.","title":"1.6 Compiler-Construction Tools"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#a-list-of-compiler-construction-tools","text":"Parser generators : produce syntax analyzers normally from in put based on context-free grammar . Syntax analysis used to be very time consuming but now is \"one of the easiest phases to implement\". Often parser generators use parsing algorithms too complex to do by hand. Scanner generators : automatically generate lexical analyzers , normally from a specification based on regular expressions . The lexical analyzer is effectively a finite automaton . See chapter 3 , implementations in section 3.5, section 3.8 . Syntax-directed translation engines : produce collections of routines that walk the parse tree, generating intermediate code . One or more translations are associated with each node of the parse tree, each translation defined in terms of its neighbor nodes in the tree. See chapter 5. Automatic code generators : take a collection of rules defining intermediate language -> target language and replace the intermediate rules with templates that represent sequences of machine instructions. Something about tiling intermediate code without a combinatorial explosion in compiler running time. See chapter 9. Data-flow engines : data flow analysis is used in optimization. How are values transmitted from one part of a program to each other part? Especially as the user defines relationships between intermediate code statements and the information being gathered. See Section 10.11.","title":"A list of compiler construction tools"},{"location":"docs/digests/compilers-ch1-the-dragon-book/#bibliographic-notes","text":"Lots of parallel discovery, hard to attribute credit. Page 23-24 have references.","title":"Bibliographic Notes"},{"location":"docs/digests/cracking_creativity_michalko/","text":"Cracking Creativity My condensed notes and summaries. Intro / Overview The book presents thinking strategies of creative giants from: science, arts, industry. Advice: Find excellent mentors. It is obvious that creative geniuses successfully transmitted their genius. Fermi's students had 6 nobel prize winners. Bohr's students had 4 nobel prize winners. Productive Thinking First (stop using reproductive thinking) Feynman proposed schools should teach productive thinking instead of reproductive thinking. Productive Thinking: Creative. Generate as many approaches as you can no matter how likely. look for all the possible needles by dissecting the haystack. Reproductive Thinking: Not creative. Rehash your experience into solutions. Rigid and narrow. Not competitive, others already thought of it. Idea Goals: Quantify and Qualify Be Productive: Geniuses set concrete numeric goals for their ideas in the short term. Writers set quotas for writing, Edison set goals for small (1 per 10 days) and big inventions (1 per 6 months). Blind Variations: Produce original and novel variations. This is the core principle. Selecting Ideas to Invest Time Into Within the mileu of ideas, let natural selection make choices. Evolution finds novel paths with a fitness algorithm. What is the fitness algorithm for our ideas? I suspect the book to be light on this topic. Place to dig deeper on my own? Practice, Practice, Practice (Productive Thinking) Organize your thinking by practicing these 9 strategies. Without practice, you will get no benefit. Intro Summaries These are summaries of the intro, not the whole book. Part 1: Seeing what no one else is seeing. Knowing How to See Use many unrelated perspectives to reimagine a problem Don't just solve the existing problem, invent new problems and improve the problem space Trent: I often find that the solution is obvious if I use my practical skills to enrich the question space Define new problems as necessary even if they don't seem related. Making Your Thought Visible Use diagrams, mock ups, anything to break out of written and verbal (away from language, math, dialogue) Formulate the subject as many ways as possible, especially with diagrams Part 2: Thinking What No One Else is Thinking Strategy 1 is used to produce a quantity of ideas. Strategies 2-6 are for getting \"blind variations\" demonstrate how to incorporate chance and randomness to destabilize existing patterns of thinking and reorganize thoughts in new ways. Strategy 7 is \"conditions for effective group brainstorming\" and \"a selection of world class brainstorm techniques\". Thinking Fluently The most respected scientists produced the most GREAT works -and- the most BAD works. Geniuses produce. Period. Edison had invention quotas: small every 10 days, large every 6 months Bach wrote a Cantana per week, even when exhausted Einstein produced 248+ papers Writers have daily writing quotas, trent: see john steinbeck and stephen king Making Novel Combinations \"Combinatory Play\" - Einstein's self-proclaimed essential feature in productive thought. Form more novel combinations than anyone else. Constantly combine and recombine from a large pool of parts (like legos) The more you do the more success you will have. Go quickly and thoroughly. Also use your subconscious (diffuse mode) by switching between different idea spaces then entering diffuse mode (meditation, sleep, eating, talking, physical labor, resting, exercise) Connecting the Unconnected Force completely unrealistic connections, see where they work, repeat. The winners will come out. Tesla: the sun aroud the earth and the AC motor (magnet rotates). - example of zany idea yielding creative outcome Da Vinci: The sound of a bell and a stone hitting water (visual & auditory waves) Looking at the Other Side David Bohm: Tolerate ambivalence between opposite or incompatible subjects Niels Bohr: if you hold opposites together, you suspend your thought and your mind moves to a new level Niels Bohr imagined light as both a particle and a wave (incompatible, yet it is still true) Looking in Other Worlds Analogies between unrelated systems Inspiration from toys and nature Finding What You Are Not Looking For First principle of the Creative Accident Answering the question in a novel, unexpected way is the essential creative act B.F. Skinner's first principle for scientific methodologists: \"When you find something interesting, drop everything and study it.\" Drop your preconcieved plan with conviction and study the new thing. Awakening the Collaborative Spirit Principles and conditions for participants to retain their individuality while combining their efforts and talents in a group in ways vital for collaborative synthesis. Collegial. Open & honest collaboration. Strategy One: Knowing How to See Da Vinci: \"saper vedere\" is knowing how to see first perspective is usually wrong move repeatedly to new perspectives, deepen understanding along the way \"Invitational Stem\" - start problem statement with \"In what ways may I...\" to avoid narrowing the problem statement to one perspective. Human language plays a role: Verbalize and write out a problem (and other ways) -- do not solve silently -- for better outcomes. Don't persist with any one perspective. Try using a whole different system and terms to express the same relationship Restructuring your problems more makes it more likely you will deepen your perspective Ways to restructure your problem: Global and Specific Abstractions Separate the parts from the whole Change the words in some fashion Make positive action statements Switch perspective Use Da Vinci's multiple perspectives Use Questions Global and Specific Abstractions Quip \"Make it more global and specific.\" Tips To widen your perspective use the \"5 whys\": Ask why 5 times to your answer to the previous why. Find the level of abstraction that fits. Ask \"Who, what, when, where, why, how?\" The more specifically you define your problem statement, the easier it will be to generate ideas. (tradeoffs) Trent: Specific statements miss solutions, abstraction may be necessary to discover something great. Summary \"Abstraction is a basic principle in restructuring a problem.\" \"Widening the perspective\", at the maximum \"globalize\" the problem Find the APPROPRIATE level of abstaction. \"Standard procedure for physical science is abstraction.\" Galileo \"ideal vacuum\" thought experiment imagined a large vacuum existed (none was available) all items fall through a vacuum with the same acceleration regardless of their weight More abstract version of \"what weighs more, a pound of feathers or a pound of bricks?\" removes the pound: \"what accelerates faster in a vacuum, a feather or a brick?\" (neither) Einstein relativity was also unobservable. \"More specific problem statements lead to faster solutions with less conceptual clarity.\" oil spill: driveway vs gulf coast new keyboard design vs new global IT industry niche Shipping industry too focused on reducing costs of ships Perspective change, global problem statement: \"In what way can the shipping industry lower reduce costs?\" Solution: Separate loading and stowing. Container ships reduced port time, congestion, theft. Ships spend more time traveling ship is \"capital equipment\" - spends more time doing its unique work of moving) costs down 60% Separate the Parts from the Whole Move from one detail to another examining it in isolation from the rest. Fishbone Diagram good for processing a \"north star\" or large vision find relationships between causes and effects use more than one session to work on a diagram let the diagram cook overnight (in your mind) and then return to find your fresh thoughts & ideas Words and Word Chains Aristotle work titled \"On Interpretation\" - words and chains of words are powerful tools of thought both reflect thinking and shape thinking Words crystallize thought, creating precision and rigidity. (both strength and weakness) Rephrase the Problem / Feynman avoid definitions such as \"friction\", \"energy\" (trent: this abstraction can hide important meaning too early) students should rephrase what they learn in their own language example of avoiding \"friction\": shoe soles go flat because notches and bumps in the sidewalk grab pieces and pull them off trent: now we see the sidewalk-shoe interface is more like a slow table saw, scooping a little rubber from various places each step Example: Toyota asked employees a question 2 ways, the 1st failed, the 2nd worked: \"How can you be more productive at work?\" \"How can you make your job easier?\" Change the Words Try changing the verb, it is easier to do. Play with verbs and nouns: Transpose the Words Aristotle \"convertibility\" - \"if every pleasure is good, some good must be pleasure.\" (questionable) find a \"verbal-conceptual chain\" to trigger a \"different view\" \"How can I get a promotion?\" vs \"How can I promote myself?\" interesting relationship even though it's just a random transposition. \"How can I learn to use the internet?\" vs \"How can I use the internet to learn?\" 21 years later this one hits spot on, that's a major use of the internet. The first word often influences, for example: \"skyscraper prayer temple cathedral\" = architectural concepts \"prayer skyscraper temple cathedral\" = religious concepts One Word Technique","title":"Cracking Creativity Michalko"},{"location":"docs/digests/cracking_creativity_michalko/#cracking-creativity","text":"My condensed notes and summaries.","title":"Cracking Creativity"},{"location":"docs/digests/cracking_creativity_michalko/#intro-overview","text":"The book presents thinking strategies of creative giants from: science, arts, industry. Advice: Find excellent mentors. It is obvious that creative geniuses successfully transmitted their genius. Fermi's students had 6 nobel prize winners. Bohr's students had 4 nobel prize winners.","title":"Intro / Overview"},{"location":"docs/digests/cracking_creativity_michalko/#productive-thinking-first-stop-using-reproductive-thinking","text":"Feynman proposed schools should teach productive thinking instead of reproductive thinking. Productive Thinking: Creative. Generate as many approaches as you can no matter how likely. look for all the possible needles by dissecting the haystack. Reproductive Thinking: Not creative. Rehash your experience into solutions. Rigid and narrow. Not competitive, others already thought of it.","title":"Productive Thinking First (stop using reproductive thinking)"},{"location":"docs/digests/cracking_creativity_michalko/#idea-goals-quantify-and-qualify","text":"Be Productive: Geniuses set concrete numeric goals for their ideas in the short term. Writers set quotas for writing, Edison set goals for small (1 per 10 days) and big inventions (1 per 6 months). Blind Variations: Produce original and novel variations. This is the core principle.","title":"Idea Goals: Quantify and Qualify"},{"location":"docs/digests/cracking_creativity_michalko/#selecting-ideas-to-invest-time-into","text":"Within the mileu of ideas, let natural selection make choices. Evolution finds novel paths with a fitness algorithm. What is the fitness algorithm for our ideas? I suspect the book to be light on this topic. Place to dig deeper on my own?","title":"Selecting Ideas to Invest Time Into"},{"location":"docs/digests/cracking_creativity_michalko/#practice-practice-practice-productive-thinking","text":"Organize your thinking by practicing these 9 strategies. Without practice, you will get no benefit.","title":"Practice, Practice, Practice (Productive Thinking)"},{"location":"docs/digests/cracking_creativity_michalko/#intro-summaries","text":"These are summaries of the intro, not the whole book.","title":"Intro Summaries"},{"location":"docs/digests/cracking_creativity_michalko/#part-1-seeing-what-no-one-else-is-seeing","text":"Knowing How to See Use many unrelated perspectives to reimagine a problem Don't just solve the existing problem, invent new problems and improve the problem space Trent: I often find that the solution is obvious if I use my practical skills to enrich the question space Define new problems as necessary even if they don't seem related. Making Your Thought Visible Use diagrams, mock ups, anything to break out of written and verbal (away from language, math, dialogue) Formulate the subject as many ways as possible, especially with diagrams","title":"Part 1: Seeing what no one else is seeing."},{"location":"docs/digests/cracking_creativity_michalko/#part-2-thinking-what-no-one-else-is-thinking","text":"Strategy 1 is used to produce a quantity of ideas. Strategies 2-6 are for getting \"blind variations\" demonstrate how to incorporate chance and randomness to destabilize existing patterns of thinking and reorganize thoughts in new ways. Strategy 7 is \"conditions for effective group brainstorming\" and \"a selection of world class brainstorm techniques\". Thinking Fluently The most respected scientists produced the most GREAT works -and- the most BAD works. Geniuses produce. Period. Edison had invention quotas: small every 10 days, large every 6 months Bach wrote a Cantana per week, even when exhausted Einstein produced 248+ papers Writers have daily writing quotas, trent: see john steinbeck and stephen king Making Novel Combinations \"Combinatory Play\" - Einstein's self-proclaimed essential feature in productive thought. Form more novel combinations than anyone else. Constantly combine and recombine from a large pool of parts (like legos) The more you do the more success you will have. Go quickly and thoroughly. Also use your subconscious (diffuse mode) by switching between different idea spaces then entering diffuse mode (meditation, sleep, eating, talking, physical labor, resting, exercise) Connecting the Unconnected Force completely unrealistic connections, see where they work, repeat. The winners will come out. Tesla: the sun aroud the earth and the AC motor (magnet rotates). - example of zany idea yielding creative outcome Da Vinci: The sound of a bell and a stone hitting water (visual & auditory waves) Looking at the Other Side David Bohm: Tolerate ambivalence between opposite or incompatible subjects Niels Bohr: if you hold opposites together, you suspend your thought and your mind moves to a new level Niels Bohr imagined light as both a particle and a wave (incompatible, yet it is still true) Looking in Other Worlds Analogies between unrelated systems Inspiration from toys and nature Finding What You Are Not Looking For First principle of the Creative Accident Answering the question in a novel, unexpected way is the essential creative act B.F. Skinner's first principle for scientific methodologists: \"When you find something interesting, drop everything and study it.\" Drop your preconcieved plan with conviction and study the new thing. Awakening the Collaborative Spirit Principles and conditions for participants to retain their individuality while combining their efforts and talents in a group in ways vital for collaborative synthesis. Collegial. Open & honest collaboration.","title":"Part 2: Thinking What No One Else is Thinking"},{"location":"docs/digests/cracking_creativity_michalko/#strategy-one-knowing-how-to-see","text":"Da Vinci: \"saper vedere\" is knowing how to see first perspective is usually wrong move repeatedly to new perspectives, deepen understanding along the way \"Invitational Stem\" - start problem statement with \"In what ways may I...\" to avoid narrowing the problem statement to one perspective. Human language plays a role: Verbalize and write out a problem (and other ways) -- do not solve silently -- for better outcomes. Don't persist with any one perspective. Try using a whole different system and terms to express the same relationship Restructuring your problems more makes it more likely you will deepen your perspective","title":"Strategy One: Knowing How to See"},{"location":"docs/digests/cracking_creativity_michalko/#ways-to-restructure-your-problem","text":"Global and Specific Abstractions Separate the parts from the whole Change the words in some fashion Make positive action statements Switch perspective Use Da Vinci's multiple perspectives Use Questions","title":"Ways to restructure your problem:"},{"location":"docs/digests/cracking_creativity_michalko/#global-and-specific-abstractions","text":"","title":"Global and Specific Abstractions"},{"location":"docs/digests/cracking_creativity_michalko/#quip","text":"\"Make it more global and specific.\"","title":"Quip"},{"location":"docs/digests/cracking_creativity_michalko/#tips","text":"To widen your perspective use the \"5 whys\": Ask why 5 times to your answer to the previous why. Find the level of abstraction that fits. Ask \"Who, what, when, where, why, how?\" The more specifically you define your problem statement, the easier it will be to generate ideas. (tradeoffs) Trent: Specific statements miss solutions, abstraction may be necessary to discover something great.","title":"Tips"},{"location":"docs/digests/cracking_creativity_michalko/#summary","text":"\"Abstraction is a basic principle in restructuring a problem.\" \"Widening the perspective\", at the maximum \"globalize\" the problem Find the APPROPRIATE level of abstaction. \"Standard procedure for physical science is abstraction.\" Galileo \"ideal vacuum\" thought experiment imagined a large vacuum existed (none was available) all items fall through a vacuum with the same acceleration regardless of their weight More abstract version of \"what weighs more, a pound of feathers or a pound of bricks?\" removes the pound: \"what accelerates faster in a vacuum, a feather or a brick?\" (neither) Einstein relativity was also unobservable. \"More specific problem statements lead to faster solutions with less conceptual clarity.\" oil spill: driveway vs gulf coast new keyboard design vs new global IT industry niche Shipping industry too focused on reducing costs of ships Perspective change, global problem statement: \"In what way can the shipping industry lower reduce costs?\" Solution: Separate loading and stowing. Container ships reduced port time, congestion, theft. Ships spend more time traveling ship is \"capital equipment\" - spends more time doing its unique work of moving) costs down 60%","title":"Summary"},{"location":"docs/digests/cracking_creativity_michalko/#separate-the-parts-from-the-whole","text":"Move from one detail to another examining it in isolation from the rest. Fishbone Diagram good for processing a \"north star\" or large vision find relationships between causes and effects use more than one session to work on a diagram let the diagram cook overnight (in your mind) and then return to find your fresh thoughts & ideas","title":"Separate the Parts from the Whole"},{"location":"docs/digests/cracking_creativity_michalko/#words-and-word-chains","text":"Aristotle work titled \"On Interpretation\" - words and chains of words are powerful tools of thought both reflect thinking and shape thinking Words crystallize thought, creating precision and rigidity. (both strength and weakness)","title":"Words and Word Chains"},{"location":"docs/digests/cracking_creativity_michalko/#rephrase-the-problem-feynman","text":"avoid definitions such as \"friction\", \"energy\" (trent: this abstraction can hide important meaning too early) students should rephrase what they learn in their own language example of avoiding \"friction\": shoe soles go flat because notches and bumps in the sidewalk grab pieces and pull them off trent: now we see the sidewalk-shoe interface is more like a slow table saw, scooping a little rubber from various places each step Example: Toyota asked employees a question 2 ways, the 1st failed, the 2nd worked: \"How can you be more productive at work?\" \"How can you make your job easier?\"","title":"Rephrase the Problem / Feynman"},{"location":"docs/digests/cracking_creativity_michalko/#change-the-words","text":"Try changing the verb, it is easier to do. Play with verbs and nouns: Transpose the Words Aristotle \"convertibility\" - \"if every pleasure is good, some good must be pleasure.\" (questionable) find a \"verbal-conceptual chain\" to trigger a \"different view\" \"How can I get a promotion?\" vs \"How can I promote myself?\" interesting relationship even though it's just a random transposition. \"How can I learn to use the internet?\" vs \"How can I use the internet to learn?\" 21 years later this one hits spot on, that's a major use of the internet. The first word often influences, for example: \"skyscraper prayer temple cathedral\" = architectural concepts \"prayer skyscraper temple cathedral\" = religious concepts","title":"Change the Words"},{"location":"docs/digests/cracking_creativity_michalko/#one-word-technique","text":"","title":"One Word Technique"},{"location":"docs/digests/data_portal_dictionary_catalog/","text":"Data Portal Support Pages, Data Catalog, and Data Dictionary. Capabilities Ideas drawn from DataSF Support Pages A set of pages to help people: Find data Integrate data into their tools excel tableau etc. Serve as a data catalog and data dictionary . Data Catalog A searchable list of data sources for discovering available data. Resources Inspiration: Microsoft Azure Data Catalog Data Dictionary A set of wiki-like pages that provides information about available data. Warby Parker used an internally hosted gitbook to disseminate information about datasets. Resources Wikipedia - Data Dictionary Dan Woods - \"Why You Can't Be Data-driven Without A Data Catalog\" (Wayback Machine Cache Link) In conversations with Carl Anderson, director of data science at Warby Parker, I discovered an elegant approach based on creating an integrated model. Anderson and his team did exhaustive research about the concepts used by executives and analysts to describe and understand business activity. Much of this knowledge was embedded in spreadsheet formulas or handcrafted SQL. Anderson and his team worked with each department to create a common definition of concepts like customer, product and revenue. Often, two distinct definitions were needed because marketing and finance think of the customer differently. In the end, Anderson created a shared, integrated and explorable model using Looker, which brought all departments to a common understanding. A data dictionary stored in GitBook described all the data fields and definitions and showed where to find them in Looker. (See \u201cThe Warby Parker Data Book\u201d for why GitBook was chosen.) This type of approach is just one of many lessons you can learn from Anderson\u2019s book, Creating a Data Driven Organization. Warby Parker Data Book (Wayback Machine Cache Link)","title":"Data Portal Dictionary Catalog"},{"location":"docs/digests/data_portal_dictionary_catalog/#data-portal","text":"Support Pages, Data Catalog, and Data Dictionary.","title":"Data Portal"},{"location":"docs/digests/data_portal_dictionary_catalog/#capabilities","text":"Ideas drawn from DataSF Support Pages A set of pages to help people: Find data Integrate data into their tools excel tableau etc. Serve as a data catalog and data dictionary .","title":"Capabilities"},{"location":"docs/digests/data_portal_dictionary_catalog/#data-catalog","text":"A searchable list of data sources for discovering available data.","title":"Data Catalog"},{"location":"docs/digests/data_portal_dictionary_catalog/#resources","text":"Inspiration: Microsoft Azure Data Catalog","title":"Resources"},{"location":"docs/digests/data_portal_dictionary_catalog/#data-dictionary","text":"A set of wiki-like pages that provides information about available data. Warby Parker used an internally hosted gitbook to disseminate information about datasets.","title":"Data Dictionary"},{"location":"docs/digests/data_portal_dictionary_catalog/#resources_1","text":"Wikipedia - Data Dictionary Dan Woods - \"Why You Can't Be Data-driven Without A Data Catalog\" (Wayback Machine Cache Link) In conversations with Carl Anderson, director of data science at Warby Parker, I discovered an elegant approach based on creating an integrated model. Anderson and his team did exhaustive research about the concepts used by executives and analysts to describe and understand business activity. Much of this knowledge was embedded in spreadsheet formulas or handcrafted SQL. Anderson and his team worked with each department to create a common definition of concepts like customer, product and revenue. Often, two distinct definitions were needed because marketing and finance think of the customer differently. In the end, Anderson created a shared, integrated and explorable model using Looker, which brought all departments to a common understanding. A data dictionary stored in GitBook described all the data fields and definitions and showed where to find them in Looker. (See \u201cThe Warby Parker Data Book\u201d for why GitBook was chosen.) This type of approach is just one of many lessons you can learn from Anderson\u2019s book, Creating a Data Driven Organization. Warby Parker Data Book (Wayback Machine Cache Link)","title":"Resources"},{"location":"docs/digests/engelbart_hlamt_1962/","text":"Outline for Doug Engelbart's \"Augmenting Human Intellect: A Conceptual Framework\" These notes are typed into an outline from paper notes taken while reading this paper. Version: 0.02 Future: Try to get the notes structure to match the table of contents. Find another copy to verify against my printed copy, make sure no info was lost. Try to get at least an outline of part 3A together. Part 3B is long and not very helpful but maybe some richer definitions can be pulled from it. Part 4 was research recommendations. Needs summarized to some degree but is very old and may not be useful. Key References: (1) Kenneth J.L., Putt, G.H. - \" Administration of Research in a Research Corporation\", RAND Corporation Report P-847 (20 April 1956) (20) Fein, Louis - \"The Computer Related Science (Synnoetics) at a University in the Year 1975\" What is the Whorfian Hypothesis? Neo-Whorfian Hypothesis? See language section in Part II. Outcomes: This paper generates language for approaching the H-LAM/T system. Does it give methodology or artifacts? Is it my job to keep generating language and start building artifacts and methodology to continue amplifying our intelligence? Are computers sufficient? Do we write computer programs for 500 years now, progressively generating language and automating more metholology as we spike off as more abstract beings? This paper wants to \"automate external symbol manipulation\" - in other words it wants to build giant trees of language which are used to uncover new language. See section on language. Augmenting Human Intellect: Abstract: \"This is an initial summary report of a project taking a new and systematic approach to improving the intellectual effectiveness of the individual human being. A detailed conceptual framekwork explores the nature of the system composed of the individual and the tools, concepts, and methods that match his basic capabilities to his problems. One of the tools that shows the greatest immediate promise is the computer, when it can be harnessed for direct on-line assistance, integrated with new concepts and methods. Part I - Introduction Part 1A - General ( \"Terms and Definitions\" ) Augmenting Human Intellect = \"Increasing a human's ability to...\" Approach a complex problem situation Gain comprehension to suit his needs Derive solutions to problem Increased Capabilities \"Faster, better, beyond original capabilities\" Complex Situations = \"Professional Problems\" Problem scale is 20 minutes to 20 years Means extensions of native sensory, motor, and mental capabilities Improvement Space Visualize this extending from/with the H-LAM/T Capability Space Will cover in section 2 Part 1B - Objective of the Study Find: factors that limit effectiveness of the individual's basic information-handling capabilities in meeting society's needs for problem solving in its most general sense Develop: Techniques, Procedures, Systems - \"which better match these basic capabilities to the needs, problems, and progress of society\" Specifications: Both long- and short-term research goals in augmentation Specific actions in: Work Environment Thinking Skills Methods of working Framework is a basis for: evaluating possible relevance of work/knowledge from existing fields assimilate relevant things from those fields \"Not be in a vacuum of study\" Framework is a basis for choosing starting points reveal areas where research can be done develop methodologies for that research H-LAM/T Conceptual Framework is a \"rudimentary framework\" a place to start at and evolve from Part II - Conceptual Framework Human has: Motor channels: Transmit information Sensory channels: Receive information Human processing: Conscious Processing Unconscious Processing Augmentation Means: Artifacts Language Methodology Organization by methods, procedures, and strategies Training \"Process Hierarchies\" Structure / Organization of each tiny step \"Augmentation Means\" Serve to break down complex problems to tiny steps \" tiny step \" = \"sub-process\" There is no way to \"find the bottom\" of the subprocess tree It is not necessary to start at the bottom A \"simple enough\" bottom layer will do Does Engelbart mean simple enough to describe wholly or pragmatically? May not matter. Begin from basic capabilities : Sensory-Mental-Motor Process Capabilities Add process capabilities of Artifacts Each individual has their own repertoire of process capabilities which are selected and adapted for execution on a process A person and his/her artifacts can be said to have a \"toolkit\" called a repertoire hierarchy which extends from his basic capabilities 3 categories of process capability : Explicit-Human Explicit-Artifact Composite (Human to Artifact Interface) H-LAM/T System - Definition Human using Language, Artifacts, and Methodology in which he is Trained H/LAM-T System - Terms has the capability and uses the repertoire to perform the process Executive processes embody all methodology of H/LAM-T System. Habit Strategy Rules of Thumb Prejudice Learned Method - NOTE: implies training is contained in methodology? Intuition Unconscious Dictates NOTE: Methodology is enumerated above, which leaves only artifacts and language. Is this collection (and any similar extensions) along with artifacts, language enough to embody all interactions a human has with his substrate? Language evolves around systems. Uncovering new systems will resolve new language. What is training then? It seems to be a subset of method but is included in the acronym. Maybe training is intended to be an extension of methods but as a special and critical process for onboarding process capabilities in humans (viewing a human as an artifact as well). There is an analogy Engelbart uses between humans and artifacts, both containing repertoire hierarchies of process capabilities . An artifact is generally designed to execute a process capability . A human can be trained to execute a process capability . A new innovation ripples/propagates both up and down the capability hierarchy . \"Synthesis\" New capabilities from old capabiltiies. Calls for a systems engineering approach. \"Synergy and Synthesis\" - Use metal allow tensile strength analogy to understand how organizing some capabilities can create a radical new \"synthetic capability\" NOTE: This is cribbed BY Buckminster Fuller 's \"Operating Manual for Spaceship Earth\". Engelbart was first unless it can be found in an earlier work. Regardless, the idea of alloys having complex new properties is potent. The world still has magic and it is materials engineering. NOTE: It would be nice to have analogies other than materials engineering otherwise we should all just become materials engineers... capabilities are \"changeable parts\" When changed, capabilities explose latent \"synthetic capabilities\" in that \"repertoire hierarchy\" His idea: by changing interchangeable parts, \" side reactions \" or new capabilities can be unearthed. An internal definition for what we call inventing by benevolent mistakes in experiment. Consider the whole H-LAM/T System as an ongoing experiment. NOTE: All humanity is in a PERMANENT , UNIFIED experiment. All action is data. Gather data as such (on the interactions in the system) some data targets: capabilities, effectiveness, etc. As humans have added tools, our common/shared repertoire hierarchies have grown and formed around us. Radical change is the norm. Can we accelerate radical change with guided research? \"Intelligence Amplifier\" Does not imply increasing raw intelligence. An amplifier makes louder what is already there. We seek to amplify intelligence by restructuring the H-LAM/T System. NOTE: He doesn't say repertoire hierarchies here, he says restructure the whole system. NOTE: His hooks for restructure are Language, Artifacts, Methods (including Training). NOTE: So what does he focus on? We could do: automation - move more and more trained methods into artifacts science - create and apply new models and language (math?) to describe the universe applications engineering - human methods seems like the weakest part of H-LAM/T... get a human to do more complex techniques Unless we are already down this rabbit hole and people increasingly program complex capabilities into dynamic artifacts right now NOTE: Often H/LAM-T will exist natively in a poorly built and/or poorly maintained state. Retraining may be 80% of the value of amplification.... sometimes. LAM-T Augmentation means represent the amplifier: Simplified using Doug's definitions: \"The means by which we augment LAM-T are the amplifier\" Simplified more: \"The means are the amplifier\" Man-Artifact Interface: NOTE: Human-Computer Interaction is the field today. This term is derived from industrial revolution term \"man-machine interface\" Two Domains: Human Artifact Explicit-Human processes often exchange across an interface to Explicit-Artifact processes Composite Processes - often designed solely for a functional match, \"coupling\", between the explicit processes . Language evolves to a situation Language can force its users down a way of thinking. Language does exert a force on its own evolution. NOTE: Language evolves to describe new concepts, which is a form of mental modeling of phenomena which can reveal new capabilities and thus contribute to novel processes. NOTE: Human-Language aided thought generates new ways of thinking, new methods, and new processes. These can later be trained or incorporated in artifacts. Capabilities drive actions and drive language evolution \"We offer the following hypothesis, which is related to the Whorfian Hypothesis: Both the language used by a culture, and the capability for effective intellectual activity, are directly affected during their evolution by the means by which individuals control the external manipulation of symbols.\" \"Automated external symbol manipulation\" - Synmbols which humans represents concepts he is manipulating can be rearranged before his eyes. Essentially giant trees of words and concepts that can uncover new language automatically by processing the base concepts of current language. Note that in the next paragraph, Doug predicts the action of using google on a smartphone to search a term in real time. To some degree we are already living in a much more fluid-language world. Question: How would having a complete, fast dictionary impact language evolution? NOTE: See encyclopedia dramatica, urban dictionary. People try to redefine things to what they want them to mean all the time, today. Terminology enters the zeitgeist very quickly but fades as quickly and terms often have different meanings to different clades. See: \"Safe Space\", 2016 representations and attacks. Organizations have to maintain internal definitions to be able to communicate. Two points in designing new repertoire hierarchies: Materials - fundamental capabilities from which all others must be constructed. Decomposition Search Decompose capabilities to discover new materials (see: synthetic capabilities) De Novo - e.g. Materials Engineering (other analogies?) Principles - Structures, explicitly synergetic structures \"synergism\" used by biologists and physicists for a siimilar concept: Webster's Unabridged Dictionary (quote from paper): \"...cooperative action of discrete agencies such that the total effect is greater than the sum of the two effects taken independently...\" Synergy is important because it is the threshold beyond which the means become greater than the sum of their materials. Five tentative types of structure: Mental Concept Symbol Process Physical Human contributes many types of capability... \"wears many hats\" A complex capability has two classes of capability (NOTE: manager vs employee) Executive class Direct contributive class Repertoire Hierarchy (sic) A mountain of white collar talent that sits atop and controls the talens of the \"workers\" Goal: Maximize productivity, Gain comprehension, Solve problems. Engelbart sees the production work as a flat base layer with a pyramid of white collar talent on top \"Theorem\" - We could expect significant gains from improving symbol and process structuring. Finding: Humans switch frequently between one symbol structure and another continuously. \"Human Augmentation Means\" will require: Training Mental Tricks Improved Language New Methodology \"Unconscious Processes may be important\" A human should be able to draw on explicit artifact capabilities at many levels in the process hierarchy","title":"Engelbart Hlamt 1962"},{"location":"docs/digests/engelbart_hlamt_1962/#outline-for-doug-engelbarts-augmenting-human-intellect-a-conceptual-framework","text":"These notes are typed into an outline from paper notes taken while reading this paper.","title":"Outline for Doug Engelbart's \"Augmenting Human Intellect: A Conceptual Framework\""},{"location":"docs/digests/engelbart_hlamt_1962/#version-002","text":"","title":"Version: 0.02"},{"location":"docs/digests/engelbart_hlamt_1962/#future","text":"Try to get the notes structure to match the table of contents. Find another copy to verify against my printed copy, make sure no info was lost. Try to get at least an outline of part 3A together. Part 3B is long and not very helpful but maybe some richer definitions can be pulled from it. Part 4 was research recommendations. Needs summarized to some degree but is very old and may not be useful.","title":"Future:"},{"location":"docs/digests/engelbart_hlamt_1962/#key-references","text":"(1) Kenneth J.L., Putt, G.H. - \" Administration of Research in a Research Corporation\", RAND Corporation Report P-847 (20 April 1956) (20) Fein, Louis - \"The Computer Related Science (Synnoetics) at a University in the Year 1975\" What is the Whorfian Hypothesis? Neo-Whorfian Hypothesis? See language section in Part II.","title":"Key References:"},{"location":"docs/digests/engelbart_hlamt_1962/#outcomes","text":"This paper generates language for approaching the H-LAM/T system. Does it give methodology or artifacts? Is it my job to keep generating language and start building artifacts and methodology to continue amplifying our intelligence? Are computers sufficient? Do we write computer programs for 500 years now, progressively generating language and automating more metholology as we spike off as more abstract beings? This paper wants to \"automate external symbol manipulation\" - in other words it wants to build giant trees of language which are used to uncover new language. See section on language.","title":"Outcomes:"},{"location":"docs/digests/engelbart_hlamt_1962/#augmenting-human-intellect","text":"","title":"Augmenting Human Intellect:"},{"location":"docs/digests/engelbart_hlamt_1962/#abstract","text":"\"This is an initial summary report of a project taking a new and systematic approach to improving the intellectual effectiveness of the individual human being. A detailed conceptual framekwork explores the nature of the system composed of the individual and the tools, concepts, and methods that match his basic capabilities to his problems. One of the tools that shows the greatest immediate promise is the computer, when it can be harnessed for direct on-line assistance, integrated with new concepts and methods.","title":"Abstract:"},{"location":"docs/digests/engelbart_hlamt_1962/#part-i-introduction","text":"Part 1A - General ( \"Terms and Definitions\" ) Augmenting Human Intellect = \"Increasing a human's ability to...\" Approach a complex problem situation Gain comprehension to suit his needs Derive solutions to problem Increased Capabilities \"Faster, better, beyond original capabilities\" Complex Situations = \"Professional Problems\" Problem scale is 20 minutes to 20 years Means extensions of native sensory, motor, and mental capabilities Improvement Space Visualize this extending from/with the H-LAM/T Capability Space Will cover in section 2 Part 1B - Objective of the Study Find: factors that limit effectiveness of the individual's basic information-handling capabilities in meeting society's needs for problem solving in its most general sense Develop: Techniques, Procedures, Systems - \"which better match these basic capabilities to the needs, problems, and progress of society\" Specifications: Both long- and short-term research goals in augmentation Specific actions in: Work Environment Thinking Skills Methods of working Framework is a basis for: evaluating possible relevance of work/knowledge from existing fields assimilate relevant things from those fields \"Not be in a vacuum of study\" Framework is a basis for choosing starting points reveal areas where research can be done develop methodologies for that research H-LAM/T Conceptual Framework is a \"rudimentary framework\" a place to start at and evolve from","title":"Part I - Introduction"},{"location":"docs/digests/engelbart_hlamt_1962/#part-ii-conceptual-framework","text":"Human has: Motor channels: Transmit information Sensory channels: Receive information Human processing: Conscious Processing Unconscious Processing Augmentation Means: Artifacts Language Methodology Organization by methods, procedures, and strategies Training \"Process Hierarchies\" Structure / Organization of each tiny step \"Augmentation Means\" Serve to break down complex problems to tiny steps \" tiny step \" = \"sub-process\" There is no way to \"find the bottom\" of the subprocess tree It is not necessary to start at the bottom A \"simple enough\" bottom layer will do Does Engelbart mean simple enough to describe wholly or pragmatically? May not matter. Begin from basic capabilities : Sensory-Mental-Motor Process Capabilities Add process capabilities of Artifacts Each individual has their own repertoire of process capabilities which are selected and adapted for execution on a process A person and his/her artifacts can be said to have a \"toolkit\" called a repertoire hierarchy which extends from his basic capabilities 3 categories of process capability : Explicit-Human Explicit-Artifact Composite (Human to Artifact Interface) H-LAM/T System - Definition Human using Language, Artifacts, and Methodology in which he is Trained H/LAM-T System - Terms has the capability and uses the repertoire to perform the process Executive processes embody all methodology of H/LAM-T System. Habit Strategy Rules of Thumb Prejudice Learned Method - NOTE: implies training is contained in methodology? Intuition Unconscious Dictates NOTE: Methodology is enumerated above, which leaves only artifacts and language. Is this collection (and any similar extensions) along with artifacts, language enough to embody all interactions a human has with his substrate? Language evolves around systems. Uncovering new systems will resolve new language. What is training then? It seems to be a subset of method but is included in the acronym. Maybe training is intended to be an extension of methods but as a special and critical process for onboarding process capabilities in humans (viewing a human as an artifact as well). There is an analogy Engelbart uses between humans and artifacts, both containing repertoire hierarchies of process capabilities . An artifact is generally designed to execute a process capability . A human can be trained to execute a process capability . A new innovation ripples/propagates both up and down the capability hierarchy . \"Synthesis\" New capabilities from old capabiltiies. Calls for a systems engineering approach. \"Synergy and Synthesis\" - Use metal allow tensile strength analogy to understand how organizing some capabilities can create a radical new \"synthetic capability\" NOTE: This is cribbed BY Buckminster Fuller 's \"Operating Manual for Spaceship Earth\". Engelbart was first unless it can be found in an earlier work. Regardless, the idea of alloys having complex new properties is potent. The world still has magic and it is materials engineering. NOTE: It would be nice to have analogies other than materials engineering otherwise we should all just become materials engineers... capabilities are \"changeable parts\" When changed, capabilities explose latent \"synthetic capabilities\" in that \"repertoire hierarchy\" His idea: by changing interchangeable parts, \" side reactions \" or new capabilities can be unearthed. An internal definition for what we call inventing by benevolent mistakes in experiment. Consider the whole H-LAM/T System as an ongoing experiment. NOTE: All humanity is in a PERMANENT , UNIFIED experiment. All action is data. Gather data as such (on the interactions in the system) some data targets: capabilities, effectiveness, etc. As humans have added tools, our common/shared repertoire hierarchies have grown and formed around us. Radical change is the norm. Can we accelerate radical change with guided research? \"Intelligence Amplifier\" Does not imply increasing raw intelligence. An amplifier makes louder what is already there. We seek to amplify intelligence by restructuring the H-LAM/T System. NOTE: He doesn't say repertoire hierarchies here, he says restructure the whole system. NOTE: His hooks for restructure are Language, Artifacts, Methods (including Training). NOTE: So what does he focus on? We could do: automation - move more and more trained methods into artifacts science - create and apply new models and language (math?) to describe the universe applications engineering - human methods seems like the weakest part of H-LAM/T... get a human to do more complex techniques Unless we are already down this rabbit hole and people increasingly program complex capabilities into dynamic artifacts right now NOTE: Often H/LAM-T will exist natively in a poorly built and/or poorly maintained state. Retraining may be 80% of the value of amplification.... sometimes. LAM-T Augmentation means represent the amplifier: Simplified using Doug's definitions: \"The means by which we augment LAM-T are the amplifier\" Simplified more: \"The means are the amplifier\" Man-Artifact Interface: NOTE: Human-Computer Interaction is the field today. This term is derived from industrial revolution term \"man-machine interface\" Two Domains: Human Artifact Explicit-Human processes often exchange across an interface to Explicit-Artifact processes Composite Processes - often designed solely for a functional match, \"coupling\", between the explicit processes . Language evolves to a situation Language can force its users down a way of thinking. Language does exert a force on its own evolution. NOTE: Language evolves to describe new concepts, which is a form of mental modeling of phenomena which can reveal new capabilities and thus contribute to novel processes. NOTE: Human-Language aided thought generates new ways of thinking, new methods, and new processes. These can later be trained or incorporated in artifacts. Capabilities drive actions and drive language evolution \"We offer the following hypothesis, which is related to the Whorfian Hypothesis: Both the language used by a culture, and the capability for effective intellectual activity, are directly affected during their evolution by the means by which individuals control the external manipulation of symbols.\" \"Automated external symbol manipulation\" - Synmbols which humans represents concepts he is manipulating can be rearranged before his eyes. Essentially giant trees of words and concepts that can uncover new language automatically by processing the base concepts of current language. Note that in the next paragraph, Doug predicts the action of using google on a smartphone to search a term in real time. To some degree we are already living in a much more fluid-language world. Question: How would having a complete, fast dictionary impact language evolution? NOTE: See encyclopedia dramatica, urban dictionary. People try to redefine things to what they want them to mean all the time, today. Terminology enters the zeitgeist very quickly but fades as quickly and terms often have different meanings to different clades. See: \"Safe Space\", 2016 representations and attacks. Organizations have to maintain internal definitions to be able to communicate. Two points in designing new repertoire hierarchies: Materials - fundamental capabilities from which all others must be constructed. Decomposition Search Decompose capabilities to discover new materials (see: synthetic capabilities) De Novo - e.g. Materials Engineering (other analogies?) Principles - Structures, explicitly synergetic structures \"synergism\" used by biologists and physicists for a siimilar concept: Webster's Unabridged Dictionary (quote from paper): \"...cooperative action of discrete agencies such that the total effect is greater than the sum of the two effects taken independently...\" Synergy is important because it is the threshold beyond which the means become greater than the sum of their materials. Five tentative types of structure: Mental Concept Symbol Process Physical Human contributes many types of capability... \"wears many hats\" A complex capability has two classes of capability (NOTE: manager vs employee) Executive class Direct contributive class Repertoire Hierarchy (sic) A mountain of white collar talent that sits atop and controls the talens of the \"workers\" Goal: Maximize productivity, Gain comprehension, Solve problems. Engelbart sees the production work as a flat base layer with a pyramid of white collar talent on top \"Theorem\" - We could expect significant gains from improving symbol and process structuring. Finding: Humans switch frequently between one symbol structure and another continuously. \"Human Augmentation Means\" will require: Training Mental Tricks Improved Language New Methodology \"Unconscious Processes may be important\" A human should be able to draw on explicit artifact capabilities at many levels in the process hierarchy","title":"Part II - Conceptual Framework"},{"location":"docs/digests/golang/","text":"Golang Reference Local Docs go install golang.org/x/tools/cmd/godoc@latest godoc -http=:6060 Path & Setup/Install This handles go on home path I like. Might replace with asdf or something. This also handles go commands installed on $GOPATH, like godoc. export GOPATH =$ HOME / code / go export PATH =$ PATH : $ HOME /. go / go / bin # version these maybe or does asdf handle this? export PATH =$ PATH : $ GOPATH / bin","title":"Golang"},{"location":"docs/digests/golang/#golang-reference","text":"","title":"Golang Reference"},{"location":"docs/digests/golang/#local-docs","text":"go install golang.org/x/tools/cmd/godoc@latest godoc -http=:6060","title":"Local Docs"},{"location":"docs/digests/golang/#path-setupinstall","text":"This handles go on home path I like. Might replace with asdf or something. This also handles go commands installed on $GOPATH, like godoc. export GOPATH =$ HOME / code / go export PATH =$ PATH : $ HOME /. go / go / bin # version these maybe or does asdf handle this? export PATH =$ PATH : $ GOPATH / bin","title":"Path & Setup/Install"},{"location":"docs/digests/how-to-get-your-point-across-30sec/","text":"Summary: How to get your point across in 30 seconds or less Resources An excellent summary presentation Summary of Presentation Presentation . The presentation is 24 slides. Why 30 seconds? The attention span of a person is 30 seconds. doctors listen to their patients for 19 seconds TV commercials do a good job in 30 seconds if you can't say it in 30 seconds, you likely are not thinking about your message clearly Uses Memos faxes letters thank you notes voicemails, text messages, telephone requests, conversations messages left with a staff person technical abstracts, technical proposals formal presentations at meetings interviews sales pitch complaint social situation with superiors chance meetings giving a toast Preparation note: Message could take an hour or more to prepare, plus speech prep time on top! OBJECTIVE: What do you want to acheve and why? AUDIENCE: Who is the target of your message? STRATEGY: How can you get what you want? Preparation Questions Do you have a single, clear-cut specific OBJECTIVE What does your AUDIENCE want from you? Can you speak in their thinking quadrant? What benefits can you offer them? Brainstorm different STRATEGIES, then select the approach that best meets the objective. What format would be most effective (phone, memo, email, formal presentation, creative presentation, etc.) Message Content HOOK: How can you get the audiences attention? SUBJECT: Are you providing all necessary details? CLOSE: Are you asking for a specific action or reaction? Tips for Coming Up With a Killer Hook Use the first statement as a hook to get attention Relate the hook to your objective, audience, approach Your hook can be a dramatic or humorous question or statement. Your entire message can be a hook The hook can be non verbal: action, mime, picture, object Keep a \"hook book\" of ideas and quotes. Tips for Preparing a Memorable Message Answer who, what, where, when, why, and how - as they relate to the objective Be brief, be clear, and touch the heart. Use imagery so the message will be remembered. If you don't know the primary thinking preference of the audience, try to communicate IN ALL FOUR QUADRANTS. CLARITY: Concise facts for Quadrant A thinkers ACTION PLAN: Well-organized implementation for Quadrant B IMAGERY: Creative word pictures for Quadrant D EMOTIONAL APPEAL: Building relationships, sharing emotions, personal stories for Quadrant C. Tips for an Effective Close You must ask for what you want. Demand action within a specific time frame. Or ask for a reaction through the power of suggestion or example. A message without a specific close or bottom-line is a wasted opportunity. Message Type: Verbal Delivery STYLE: What non-verbal messages are you giving? Monitor your body language. APPEARANCE: Are you well-groomed? SPEAKING: Learn to modulate your voice. Use pauses. Be animated. ACTING: Smile. Use eye contact. Transmit a positive, friendly attitude. Message Type: Written Write legibly and neatly Use good grammar and correct spelling Where appropriate, also pay attention to a pleasing layout Act as required by the situation, maybe one of these: positive and friendly polite and formal Proof read, edit, then proof read again. Then check again. Get it perfect. Tips for giving a Formal Presentation Start and finish on time Make sure each person on your team is introduced clearly Speak the language of your audience and state the purpose of your presentation Use visual aids so peole will better remember your main ideas Plan time for questions at the end; respond directly to the questions Be yourself; project energy, enthusiasm, and confidence Don't exaggerate or critisize -- don't bad-mouth the competition PRACTICE - make sure you know how to operate your equipment (projector, screen, computers, mikes, lighting, etc.) How to make your presentation Memorable Listeners can only remember 3 to 5 points. Preview the main points to have listeners anticipate them Continuously tie the points to the structure of the presentation Provide summaries as handouts if you have many details At the end, review or reinforce the main points to provide closure","title":"How To Get Your Point Across 30Sec"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#summary-how-to-get-your-point-across-in-30-seconds-or-less","text":"","title":"Summary: How to get your point across in 30 seconds or less"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#resources","text":"An excellent summary presentation","title":"Resources"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#summary-of-presentation","text":"Presentation . The presentation is 24 slides. Why 30 seconds? The attention span of a person is 30 seconds. doctors listen to their patients for 19 seconds TV commercials do a good job in 30 seconds if you can't say it in 30 seconds, you likely are not thinking about your message clearly Uses Memos faxes letters thank you notes voicemails, text messages, telephone requests, conversations messages left with a staff person technical abstracts, technical proposals formal presentations at meetings interviews sales pitch complaint social situation with superiors chance meetings giving a toast","title":"Summary of Presentation"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#preparation","text":"note: Message could take an hour or more to prepare, plus speech prep time on top! OBJECTIVE: What do you want to acheve and why? AUDIENCE: Who is the target of your message? STRATEGY: How can you get what you want?","title":"Preparation"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#preparation-questions","text":"Do you have a single, clear-cut specific OBJECTIVE What does your AUDIENCE want from you? Can you speak in their thinking quadrant? What benefits can you offer them? Brainstorm different STRATEGIES, then select the approach that best meets the objective. What format would be most effective (phone, memo, email, formal presentation, creative presentation, etc.)","title":"Preparation Questions"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#message-content","text":"HOOK: How can you get the audiences attention? SUBJECT: Are you providing all necessary details? CLOSE: Are you asking for a specific action or reaction?","title":"Message Content"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#tips-for-coming-up-with-a-killer-hook","text":"Use the first statement as a hook to get attention Relate the hook to your objective, audience, approach Your hook can be a dramatic or humorous question or statement. Your entire message can be a hook The hook can be non verbal: action, mime, picture, object Keep a \"hook book\" of ideas and quotes.","title":"Tips for Coming Up With a Killer Hook"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#tips-for-preparing-a-memorable-message","text":"Answer who, what, where, when, why, and how - as they relate to the objective Be brief, be clear, and touch the heart. Use imagery so the message will be remembered. If you don't know the primary thinking preference of the audience, try to communicate IN ALL FOUR QUADRANTS. CLARITY: Concise facts for Quadrant A thinkers ACTION PLAN: Well-organized implementation for Quadrant B IMAGERY: Creative word pictures for Quadrant D EMOTIONAL APPEAL: Building relationships, sharing emotions, personal stories for Quadrant C.","title":"Tips for Preparing a Memorable Message"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#tips-for-an-effective-close","text":"You must ask for what you want. Demand action within a specific time frame. Or ask for a reaction through the power of suggestion or example. A message without a specific close or bottom-line is a wasted opportunity.","title":"Tips for an Effective Close"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#message-type-verbal-delivery","text":"STYLE: What non-verbal messages are you giving? Monitor your body language. APPEARANCE: Are you well-groomed? SPEAKING: Learn to modulate your voice. Use pauses. Be animated. ACTING: Smile. Use eye contact. Transmit a positive, friendly attitude.","title":"Message Type: Verbal Delivery"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#message-type-written","text":"Write legibly and neatly Use good grammar and correct spelling Where appropriate, also pay attention to a pleasing layout Act as required by the situation, maybe one of these: positive and friendly polite and formal Proof read, edit, then proof read again. Then check again. Get it perfect.","title":"Message Type: Written"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#tips-for-giving-a-formal-presentation","text":"Start and finish on time Make sure each person on your team is introduced clearly Speak the language of your audience and state the purpose of your presentation Use visual aids so peole will better remember your main ideas Plan time for questions at the end; respond directly to the questions Be yourself; project energy, enthusiasm, and confidence Don't exaggerate or critisize -- don't bad-mouth the competition PRACTICE - make sure you know how to operate your equipment (projector, screen, computers, mikes, lighting, etc.)","title":"Tips for giving a Formal Presentation"},{"location":"docs/digests/how-to-get-your-point-across-30sec/#how-to-make-your-presentation-memorable","text":"Listeners can only remember 3 to 5 points. Preview the main points to have listeners anticipate them Continuously tie the points to the structure of the presentation Provide summaries as handouts if you have many details At the end, review or reinforce the main points to provide closure","title":"How to make your presentation Memorable"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/","text":"Introduction to Proposal Writing Video Notes are from this video Source: Foundation Center Speaker: The Proposal Writing Process Planning what do you need the money for? Research who will you approach Writing how you put it all together? Followup what you do once a decision has been made? Planning Do you have enough time? Not a quick fix, 6-9 months between beginning proposal and receiving funds. What are you asking for? What kind of support: operations, project, building renovation, equipment. Generating a Project Proposal is our focus today Research Finding the right fit. How does what you do fit with the funder's interests? The why is just as important as the who Tell them how your project achieves their goals, mission, and priorities. Through a combination of your program and their resources. Writing the Proposal Grantwriters are moving to online formats. Limited space and character restrictions. Always follow the funder's guidelines. Put together a master proposal or base proposal using the format we are about to go over. There is a directory of common form grants on the Foundation Center Knowledge Base website . Four Typical Proposal Elements Executive Summary How do I reduce everything to one page? Extract the key information from the full proposal (write the full proposal first). They will look at this first to determine if they want to read the rest of the proposal. May not continue reading if they are not interested right away. Also used to present your project to the foundation board for consideration. This can be used for the letter of inquiry as well. Includes: Statement of Need Brief description project incl goals and objectives Information about your objectives How much money you are asking for Narrative Statement of Need What specific need are you addressing? fits size and scale of your solution What audience and community are you serving? What evidence do you have to support the need? Project Description What are you trying to achieve? Your outcomes must be measurable SMART Goals Specific Measurable Achievable Realistic Time-based What is your specific plan? Your proposal is your organizing plan . Who will do the work? Both paid and volunteer. What? When? Where? Why? How? Evaluation: How do you know you are successful? Specify program objectives in measurable terms Identify key indicators of success Outline data collection and analysis activites Develop a TIMELINE to monitor the success of the program on an ongoing basis What you will do with your information TRACY - Tools and Reseources for Measuring Social Impact (or something like that, i may have mistyped) Why are you the best organization to do this work? Organization Information Conclusion Budget Supporting Materials Follow the funder's guidelines. Include everything (and very little of anything else). For online applications it's ok to add links where possible. Organization's most recent audited financial statements IRS Form 990 Current Operating Budget and last year's budget versus actual List of board of director names and professional affiliation Brief biographical information of key staffers People carrying out your project have sufficient knowledge and experience for success Other Stuff Grant is the beginning of the relationship with your funder Regular reports, keep them informed! Significant accomplishment? Send a note or make a phone call. Having an event? Invite them as a courtesy no matter what, even if you know they cannot or will not go. Follow Up It's not personal Find out why Ask about future funding Don't just put them on your generic mailing list! Keep them up to date Key Takeaways Start with an outline Keep the language clear and concise Focus on the funders' interests Follow the funders' guidelines Revise and edit before submitting Tell them a story Avoid jargon and acronyms. Additional Resources Foundation Center Resources Foundation Center Training Proposal Writing Workshop - 1 day - In Person Proposal Writing Bootcamp - 3 day - In Person There is also an Intro to Writing Grants course. There is also an Intro to Finding Grants course. grantspace.org skill space grantspace.org sample documents (yes sample proposals from funders, including comments as to why they got the grant)","title":"Intro To Grant Proposal Writing Foundation Ctr"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#introduction-to-proposal-writing-video","text":"Notes are from this video Source: Foundation Center Speaker:","title":"Introduction to Proposal Writing Video"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#the-proposal-writing-process","text":"Planning what do you need the money for? Research who will you approach Writing how you put it all together? Followup what you do once a decision has been made?","title":"The Proposal Writing Process"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#planning","text":"","title":"Planning"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#do-you-have-enough-time","text":"Not a quick fix, 6-9 months between beginning proposal and receiving funds.","title":"Do you have enough time?"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#what-are-you-asking-for","text":"What kind of support: operations, project, building renovation, equipment. Generating a Project Proposal is our focus today","title":"What are you asking for?"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#research","text":"Finding the right fit. How does what you do fit with the funder's interests? The why is just as important as the who Tell them how your project achieves their goals, mission, and priorities. Through a combination of your program and their resources.","title":"Research"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#writing-the-proposal","text":"Grantwriters are moving to online formats. Limited space and character restrictions. Always follow the funder's guidelines. Put together a master proposal or base proposal using the format we are about to go over. There is a directory of common form grants on the Foundation Center Knowledge Base website .","title":"Writing the Proposal"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#four-typical-proposal-elements","text":"","title":"Four Typical Proposal Elements"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#executive-summary","text":"How do I reduce everything to one page? Extract the key information from the full proposal (write the full proposal first). They will look at this first to determine if they want to read the rest of the proposal. May not continue reading if they are not interested right away. Also used to present your project to the foundation board for consideration. This can be used for the letter of inquiry as well.","title":"Executive Summary"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#includes","text":"Statement of Need Brief description project incl goals and objectives Information about your objectives How much money you are asking for","title":"Includes:"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#narrative","text":"","title":"Narrative"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#statement-of-need","text":"What specific need are you addressing? fits size and scale of your solution What audience and community are you serving? What evidence do you have to support the need?","title":"Statement of Need"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#project-description","text":"What are you trying to achieve? Your outcomes must be measurable SMART Goals Specific Measurable Achievable Realistic Time-based What is your specific plan? Your proposal is your organizing plan . Who will do the work? Both paid and volunteer. What? When? Where? Why? How? Evaluation: How do you know you are successful? Specify program objectives in measurable terms Identify key indicators of success Outline data collection and analysis activites Develop a TIMELINE to monitor the success of the program on an ongoing basis What you will do with your information TRACY - Tools and Reseources for Measuring Social Impact (or something like that, i may have mistyped) Why are you the best organization to do this work?","title":"Project Description"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#organization","text":"","title":"Organization"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#information","text":"","title":"Information"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#conclusion","text":"","title":"Conclusion"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#budget","text":"","title":"Budget"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#supporting-materials","text":"Follow the funder's guidelines. Include everything (and very little of anything else). For online applications it's ok to add links where possible. Organization's most recent audited financial statements IRS Form 990 Current Operating Budget and last year's budget versus actual List of board of director names and professional affiliation Brief biographical information of key staffers People carrying out your project have sufficient knowledge and experience for success","title":"Supporting Materials"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#other-stuff","text":"Grant is the beginning of the relationship with your funder Regular reports, keep them informed! Significant accomplishment? Send a note or make a phone call. Having an event? Invite them as a courtesy no matter what, even if you know they cannot or will not go.","title":"Other Stuff"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#follow-up","text":"It's not personal Find out why Ask about future funding Don't just put them on your generic mailing list! Keep them up to date","title":"Follow Up"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#key-takeaways","text":"Start with an outline Keep the language clear and concise Focus on the funders' interests Follow the funders' guidelines Revise and edit before submitting Tell them a story Avoid jargon and acronyms.","title":"Key Takeaways"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#additional-resources","text":"","title":"Additional Resources"},{"location":"docs/digests/intro_to_grant_proposal_writing_foundation_ctr/#foundation-center-resources","text":"Foundation Center Training Proposal Writing Workshop - 1 day - In Person Proposal Writing Bootcamp - 3 day - In Person There is also an Intro to Writing Grants course. There is also an Intro to Finding Grants course. grantspace.org skill space grantspace.org sample documents (yes sample proposals from funders, including comments as to why they got the grant)","title":"Foundation Center Resources"},{"location":"docs/digests/meditations_Marcus_Aurelius/","text":"Meditations - Marcus Aurelius Some things that stood out to me Book 1 He gives a lot of things he has lived by Spend liberally on private trainings at home Work with your own hands Be happy with a plank bed and hide covering and whatever goes with a greek discipline Write letters in a simple style If someone offends you, be easily disposed to be pacified and reconciled as soon as they have shown a readiness to be reconciled from appolonious I learnt freedom of will and undeviating steadiness of purpose, and to take no other viewpoint, even for a moment, but that of reason to see clearly (trent: a.k.a. \"to reason\") on all occasions whether it be extreme pain, the loss of a child, or long illness be most resolute and yielding receive favors without letting them go unnoticed or being put in an awkward position correct people's language later by example without bringing specific attention to their mistake never say to anyone \"that you have no time\" or allege \"you have urgent business to attend to\" thankful that he did not fall into the hands of sophists when he became interested in philosophy, waste his time on observing the movements of the heavens, literature, and intellectual puzzles, \"for all these things require the help of the gods and fortune\" Book 2 (chapter 5)","title":"Meditations Marcus Aurelius"},{"location":"docs/digests/meditations_Marcus_Aurelius/#meditations-marcus-aurelius","text":"Some things that stood out to me","title":"Meditations - Marcus Aurelius"},{"location":"docs/digests/meditations_Marcus_Aurelius/#book-1","text":"He gives a lot of things he has lived by Spend liberally on private trainings at home Work with your own hands Be happy with a plank bed and hide covering and whatever goes with a greek discipline Write letters in a simple style If someone offends you, be easily disposed to be pacified and reconciled as soon as they have shown a readiness to be reconciled from appolonious I learnt freedom of will and undeviating steadiness of purpose, and to take no other viewpoint, even for a moment, but that of reason to see clearly (trent: a.k.a. \"to reason\") on all occasions whether it be extreme pain, the loss of a child, or long illness be most resolute and yielding receive favors without letting them go unnoticed or being put in an awkward position correct people's language later by example without bringing specific attention to their mistake never say to anyone \"that you have no time\" or allege \"you have urgent business to attend to\" thankful that he did not fall into the hands of sophists when he became interested in philosophy, waste his time on observing the movements of the heavens, literature, and intellectual puzzles, \"for all these things require the help of the gods and fortune\"","title":"Book 1"},{"location":"docs/digests/meditations_Marcus_Aurelius/#book-2-chapter-5","text":"","title":"Book 2 (chapter 5)"},{"location":"docs/digests/rules_for_radicals_1971/","text":"Rules For Radicals - 1971 Author: Saul Alinksy Safety Note Do not store or supply unsafe materials for Anything Illegal , especially for \"People You Trust\". In 2012-2017, the FBI has repeatedly radicalized left-wing organizations to cross strict legal barriers in perceived assistance of domestic terrorism. If an agent knocks, federal investigators and your rights Today, the FBI may begin a full investigation whenever there is a reasonable indication that \"two or more persons are engaged in an enterprise for the purpose of furthering political or social goals wholly or in part through activities that involve force or violence and a violation of the criminal laws of the United States.\" The FBI has interpreted \"force or violence\" to include the destruction of property as a symbolic act, and the mere advocacy of such property destruction would trigger an investigation. Even without any reasonable indication, under a separate guideline on \"Civil Disorders and Demonstrations Involving a Federal Interest,\" the FBI may investigate an organization that plans only legal and peaceful demonstrations. Another set of rules governing federal intelligence gathering is Executive Order 12333, in force since 1981. It authorizes the FBI and CIA to infiltrate, manipulate and destroy U.S.political organizations, as well as to use electronic surveillance -- under the pretext of an international intelligence investigation. Here is a half baked guide about what infiltrators might do . Also in Texas, a left-wing group was infiltrated by an FBI informant who insisted that the group become violent in response to the Republican scourge. Once he convinced members to make Molotov cocktails, the FBI stormed in and made arrests . Lastly, the FBI infiltrated middle-aged peace activists and filed trumped-up charges of them providing \u201cassistance\u201d to terrorists. The bogus charges were eventually dropped. The FBI has also infiltrated Oil Pipeline Protestors using legal loopholes. Dictionary The book is dated in some political terminology. See the below list for clarifications. radical means activist in 2017 revolution means political revolution in 2017 Although, Alinsky doesn't make this strict distinction between whether violence is actually used. reformation means reorganization of values or priorities for your political base General Notes Wikipedia offers a summary of the rules : \u201cPower is not only what you have, but what the enemy thinks you have.\u201d Power is derived from 2 main sources \u2013 money and people. \u201cHave-Nots\u201d must build power from flesh and blood. \u201cNever go outside the expertise of your people.\u201d It results in confusion, fear and retreat. Feeling secure adds to the backbone of anyone. \u201cWhenever possible, go outside the expertise of the enemy.\u201d Look for ways to increase insecurity, anxiety and uncertainty. \u201cMake the enemy live up to its own book of rules.\u201d If the rule is that every letter gets a reply, send 30,000 letters. You can kill them with this because no one can possibly obey all of their own rules. \u201cRidicule is man\u2019s most potent weapon.\u201d There is no defense. It\u2019s irrational. It\u2019s infuriating. It also works as a key pressure point to force the enemy into concessions. \u201cA good tactic is one your people enjoy.\u201d They\u2019ll keep doing it without urging and come back to do more. They\u2019re doing their thing, and will even suggest better ones. \u201cA tactic that drags on too long becomes a drag.\u201d Don\u2019t become old news. \u201cKeep the pressure on. Never let up.\u201d Keep trying new things to keep the opposition off balance. As the opposition masters one approach, hit them from the flank with something new. \u201cThe threat is usually more terrifying than the thing itself.\u201d Imagination and ego can dream up many more consequences than any activist. \"The major premise for tactics is the development of operations that will maintain a constant pressure upon the opposition.\" It is this unceasing pressure that results in the reactions from the opposition that are essential for the success of the campaign. \u201cIf you push a negative hard enough, it will push through and become a positive.\u201d Violence from the other side can win the public to your side because the public sympathizes with the underdog. \u201cThe price of a successful attack is a constructive alternative.\u201d Never let the enemy score points because you\u2019re caught without a solution to the problem. \u201cPick the target, freeze it, personalize it, and polarize it.\u201d Cut off the support network and isolate the target from sympathy. Go after people and not institutions; people hurt faster than institutions. Rules for Radicals Notes Taken while reading the book. Prologue McCarthy Era \"Few [radicals] survived the Joe McCarthy Holocaust of the 1950s and of those there were even fewer whose understanding and insights had developed beyond the dialectical materialism of orthodox Marxism. My fellow radicals who were supposed to pass on the torch of experience and insights to the new generation just were not there. As the young looked around at society around them, it was all, in their words, 'materialistic, decadent, bourgeois in its values, bankrupt, and violent.' Is it any wonder that they rejected us in toto.\" (p. xiii) Reader note: McCarthyism is seen now as a reactionary backlash to issues as far ranging as women's suffrage , child labor laws , and gay rights , as well as a means for certain politicians to use fear to keep power. The FBI is also implicated heavily in performing illegal spying. There are loophopes for domestic spying used by the FBI today . Young vs. Old Young people have seen 'activist democracies' turn into 'nihilistic bombing and murder' and there is no panacea for it as there was in the past, 'revolution in Russia and China has since become the same old stuff under a different name'. Young people are looking for a way of life that has some meaning or sense: religion, political philosophy, science, or ideologies. The small world of the past inspired trust, and the big world of today inspires confusion and incomprehensibility. Generation Gap - Older people think younger people haven't learned how the world is, younger people think the old people will never get with the changing times. Approaches to the chaotic world by the young: Panic and run - \"copping out\" Hippies and Yuppies Taking drugs Trying communes Anything to escape Sure-loser confrontations: \"We tried and did our part\" Dying Jail Followed by panic and run, \"copping out\" Guilt and \"not knowing where to turn to\" Suicide Contempt \"take off for Algeria\" There are no rules for revolution as there are for revelation. There are no rules for revolution but there are rules for radicals . \"Remember we are talking about revolution, not revelation; you can miss the target by shooting too high as well as too low. First, there are no rules for revolution any more than there are rules for love or rules for happiness, but there are rules for radicals who want to change their world; there are central concepts of action in human politics that operate regardless of the scene or the time. To know these is basic to a pragmatic attack on the system. These rules make the difference between a realistic radical and being a rhetorical one who uses the tired old words and slogans, calls the police 'pig' or 'white fascist racist' or 'motherfucker' and has so stereotyped himself that others react by saying, 'oh, he's one of those ,' and then promptly turn off.\" (p. xviii) Communication Throughout history, silence has been regarded as assent -- in this case, assent to the system. If you cannot communicate in a way that your audience listens to you, you are silent no matter how loudly you scream. The inference here is that if you are not accepted in the community you wish to change, you are assenting to the system by not truly seeking a path to change that brings the community with you. Communicate within the experience of your audience Pay full respect to its values A fool attacks the American flag: it is the establishment which has betrayed the flag while the flag, itself, remains the glorious symbol of America's hopes and aspirations Humor and comedy are essential Through humor much is accepted that would be rejected if presented seriously. Note: People want to laugh and find joy in whatever they do. It inspires growth more than anything. Radicalism is social Do it for, and with, people If the real radical finds that having long hair sets up psychological barriers to communication and organization, he cuts his hair. Start your battle where the world is, not where you would like it to be. Work inside the system Dostoyevsky said that taking a new step is what people fear the most. Any revolutionary change must be preceded by a passive, affirmative, non-challenging attitude toward change among the mass of our people. They must feel so frustrated, so defeated, so lost, so futureless in the prevailing system that they are willing to let go of the past and chance the future. That acceptance is the reformation essential to any revolution. To bring on this reformation requires that the organizer work inside the system, among not only the middle class but the 40 percent of American families... whose income ranges from $5000 to$10000 a year [in 1971 dollars]... IF we fail to communicate with them... they will move to the right... maybe they will anyways, but lets not let it happen by default. (p. xix) Non-Violence Violence is absurd when the other side has all the guns. Just one violent incident like has happened in the US would have resulted in a sweeping purge and mass executions in Russia, China, or Cuba. Lets keep some perspective. (paraphrased) Remember that we have the freedom to fight with our words and to build an opposition base against the administration. Start with the system There is no other place to start. Revolution is precededed by Reformation Also called popular reformation of your opposition political base People need a bridge to cross from their own experience to a new way Shake up the patterns of their lives Agitate Create Disenchantment Discontent with current values Goal: Produce a passive, affirmative, non-challenging climate or a passion for change in the political base . Revolution without prior reformation will collapse or become totalitarian tyranny. Reformation - People are fed up with past ways. They don't know what will work but they know that the present system is hopeless. They won't act for change but won't strongly oppose those who do. Then the time is ripe for revolution . Participation Citizen participation is the animating spirit and force in a society predicated on voluntarism. We are not here concerned with people who profess the democratic faith but yearn for the dark security of dependency where they can be spared the burden of decisions. To lose your \"identity\" as a citizen of democracy is but a step from losing your identity as a person. People react to this frustration by not acting at all. Hang on to one of the most precious parts of youth, laughter... (p. xxvii) Chapter 1 - The Purpose \"The Prince\" by Machiavelli is for the Haves on how to hold power. \"Rules for Radicals\" is for the Have Nots on how to take it away. Defining This Book Purpose: Create mass organizations to seize power and give it to the people. Premise: The significant changes in history have been made by revolutions. Content: The book proposes: Certain general observations propositions concepts of the mechanics of mass movements various stages of the cycle of action and reaction in a revolution This book will not contain any panacea or dogma; I detest and fear dogma. I know that all revolutions must have ideologies to spur them on. That in the heat of conflict these ideologies tend to be smelted into rigid dogmas claiming exclusive possession of the truth, and the keys to paradise, is tragic. Dogma is the enemy of human freedom. Dogma must be watched for and apprehended at every turn and twist of the revolutionary movement... To diminish the danger that ideology will deteriorate into dogma, and to protect the free, open, questing, and creative mind of man, as well as to allow for change, no ideology should be more specific than that of America's founding fathers: \"For the general welfare.\" (p. 4) Political Sensitivity & Control Over Events Resilient , Adaptable , and Sensitive \"Radicals must have a degree of control over the flow of events\" Have a plan for each branch in the path Adaptable: Merge the plan, old plans, similar experiences Adapt to shifting political circumstances Resilient: Don't back down!! Sensitive: find , create , and take opportunities Avoid being trapped by your own tactics Forced to travel a road not of your choosing. Keep the initiative. Do not pass the initiative. Keep things in motion!! Revolutionary \"how-to\" Guides Are Rare This text is dedicated to splitting two atomic ideas: revolution from communism Revolutionary literature is sparse! Literature extolling the virtues of the Haves is prolific Literature decrying revolution as reptilian, evil, and hellish is prolific To the status quo, revolution \"is the only force which has no image, but instead casts a dark, ominous shadow of things to come.\" A significant body of communist revolutionary literature exists It is embedded in the \"language of communism, red and yellow\" Tactics, maneuvers, strategy, and principles of action in the making of revolutions Today's situation is suicidal: revolution and communism have become one in peoples' minds We only accept revolution if it is guaranteed to be on our side and we can't find a way out Revolution is associated with communism \"The Status Quo\" is associated with capitalism Section: The Ideology of Change Question: What, if any, is my ideology? The prerequisite for ideology is possession of a basic truth Easy for christians, marxists Hard for an organizer working for open society, who must be a political relativist A free-society organizer is free of the shackles of dogma One belief: that people, given the power to act, will do the right thing in the long run, most of the time Politics of Change : free to focus on what matters to people now, rather than serve a dogma Note: This is perhaps better called the un-dogma of a free society. Political realists see the world as it is: an arena of power politics moved primarily by perceived immediate self-interests, where morality is rhetorical rationale for expedient action and self-interest. (p.12) Duality of Revolution and Counter-Revolution Accept and embrace the duality of revolution and counter-revolution . If you understand the big picture of revolution and counter-revolution then you can seek to alter the historical pattern of \"two steps forwards, one step back\". Examples of the duality of revolution and reaction (p. 16) Urban Housing Projects - A dream of replacing the tenements vs. a doubly segregated place. CIO + AF of L - CIO reforming AF of L becomes entrenched member of establishment as AFLCIO etc. Section: Class Distinctions: The Trinity Three Parts of Mankind Haves : want to keep power, money, food, security, luxury determined to freeze the Status Quo \"When do we sleep?\" - fear violent uprising Have-Nots : want to get poverty, rotten housing, disease, ignorance, political impotence, despair jobs pay the least deprived in all areas basic to human growth caged by color physical or political, barred from representation hate the establishment, opulence, police, courts, churches Justice, morality, law, and order are mere words when used by the Haves : justify and secure the status quo Power in Numbers. \"When do we eat?\", \"get off our backs\" Have-A-Little, Want Mores : the middle class Torn between status quo and change things to get more social, economic, political schizoids Generally seek the safe way Insist on three aces in their hand before playing the poker game of revolution Majority in the US, and generally in Western society. Argument by Alinksy that the greats come out of the middle class The middle class spawns people who provoke action but Do Nothing , \"I agree with your ends but not with your means.\" Act as a blanket for the sparks of disension. The book will examine both the Doers and the Do-Nothings . Edmund Burke: \"The only thing necessary for the triumph of evil is for good men to do nothing.\" Alice in Wonderland : Tiger-Lily points out that the flowers that talk grow out of hard beds of ground. In most gardens, they make the beds too soft so that the flowers are always asleep. (p. 21) Change means movement. Movement means friction. Only in the frictionless vacuum of a nonexistent abstract world can movement or change occur without that abrasive friction of conflict. In these pages it is our open political purpose to cooperate with the great law of change; to want otherwise would be like King Canute's commanding the tides and waves to cease. Alinsky's personal philosophy is anchored in optimism. If we imagine the struggle as a mountain, we must visualize a mountain with no top.... Knowing that the mountain has no top... Why do we continue? ... because it's there... Different than Sisyphis, doomed to have the boulder roll back down again. We see new vistas at each plateau. The low road to morality. If you have bread and your neighbor has none, he will kill you and eat yours. We must accept that we rely on each other to continue a free society. You must share some of your wealth, or lose all of it. Remember: organizations are wealth, you can't destroy everyone. Note: Following this low road, welfare and basic income can be viewed, for better or for worse, as ransom on society's wealth. This is the low road to morality. There is no other. (p. 23) Chapter 2 - Of Means and Ends","title":"Rules For Radicals 1971"},{"location":"docs/digests/rules_for_radicals_1971/#rules-for-radicals-1971","text":"Author: Saul Alinksy","title":"Rules For Radicals - 1971"},{"location":"docs/digests/rules_for_radicals_1971/#safety-note","text":"Do not store or supply unsafe materials for Anything Illegal , especially for \"People You Trust\". In 2012-2017, the FBI has repeatedly radicalized left-wing organizations to cross strict legal barriers in perceived assistance of domestic terrorism. If an agent knocks, federal investigators and your rights Today, the FBI may begin a full investigation whenever there is a reasonable indication that \"two or more persons are engaged in an enterprise for the purpose of furthering political or social goals wholly or in part through activities that involve force or violence and a violation of the criminal laws of the United States.\" The FBI has interpreted \"force or violence\" to include the destruction of property as a symbolic act, and the mere advocacy of such property destruction would trigger an investigation. Even without any reasonable indication, under a separate guideline on \"Civil Disorders and Demonstrations Involving a Federal Interest,\" the FBI may investigate an organization that plans only legal and peaceful demonstrations. Another set of rules governing federal intelligence gathering is Executive Order 12333, in force since 1981. It authorizes the FBI and CIA to infiltrate, manipulate and destroy U.S.political organizations, as well as to use electronic surveillance -- under the pretext of an international intelligence investigation. Here is a half baked guide about what infiltrators might do . Also in Texas, a left-wing group was infiltrated by an FBI informant who insisted that the group become violent in response to the Republican scourge. Once he convinced members to make Molotov cocktails, the FBI stormed in and made arrests . Lastly, the FBI infiltrated middle-aged peace activists and filed trumped-up charges of them providing \u201cassistance\u201d to terrorists. The bogus charges were eventually dropped. The FBI has also infiltrated Oil Pipeline Protestors using legal loopholes.","title":"Safety Note"},{"location":"docs/digests/rules_for_radicals_1971/#dictionary","text":"The book is dated in some political terminology. See the below list for clarifications. radical means activist in 2017 revolution means political revolution in 2017 Although, Alinsky doesn't make this strict distinction between whether violence is actually used. reformation means reorganization of values or priorities for your political base","title":"Dictionary"},{"location":"docs/digests/rules_for_radicals_1971/#general-notes","text":"Wikipedia offers a summary of the rules : \u201cPower is not only what you have, but what the enemy thinks you have.\u201d Power is derived from 2 main sources \u2013 money and people. \u201cHave-Nots\u201d must build power from flesh and blood. \u201cNever go outside the expertise of your people.\u201d It results in confusion, fear and retreat. Feeling secure adds to the backbone of anyone. \u201cWhenever possible, go outside the expertise of the enemy.\u201d Look for ways to increase insecurity, anxiety and uncertainty. \u201cMake the enemy live up to its own book of rules.\u201d If the rule is that every letter gets a reply, send 30,000 letters. You can kill them with this because no one can possibly obey all of their own rules. \u201cRidicule is man\u2019s most potent weapon.\u201d There is no defense. It\u2019s irrational. It\u2019s infuriating. It also works as a key pressure point to force the enemy into concessions. \u201cA good tactic is one your people enjoy.\u201d They\u2019ll keep doing it without urging and come back to do more. They\u2019re doing their thing, and will even suggest better ones. \u201cA tactic that drags on too long becomes a drag.\u201d Don\u2019t become old news. \u201cKeep the pressure on. Never let up.\u201d Keep trying new things to keep the opposition off balance. As the opposition masters one approach, hit them from the flank with something new. \u201cThe threat is usually more terrifying than the thing itself.\u201d Imagination and ego can dream up many more consequences than any activist. \"The major premise for tactics is the development of operations that will maintain a constant pressure upon the opposition.\" It is this unceasing pressure that results in the reactions from the opposition that are essential for the success of the campaign. \u201cIf you push a negative hard enough, it will push through and become a positive.\u201d Violence from the other side can win the public to your side because the public sympathizes with the underdog. \u201cThe price of a successful attack is a constructive alternative.\u201d Never let the enemy score points because you\u2019re caught without a solution to the problem. \u201cPick the target, freeze it, personalize it, and polarize it.\u201d Cut off the support network and isolate the target from sympathy. Go after people and not institutions; people hurt faster than institutions.","title":"General Notes"},{"location":"docs/digests/rules_for_radicals_1971/#rules-for-radicals-notes","text":"Taken while reading the book.","title":"Rules for Radicals Notes"},{"location":"docs/digests/rules_for_radicals_1971/#prologue","text":"","title":"Prologue"},{"location":"docs/digests/rules_for_radicals_1971/#mccarthy-era","text":"\"Few [radicals] survived the Joe McCarthy Holocaust of the 1950s and of those there were even fewer whose understanding and insights had developed beyond the dialectical materialism of orthodox Marxism. My fellow radicals who were supposed to pass on the torch of experience and insights to the new generation just were not there. As the young looked around at society around them, it was all, in their words, 'materialistic, decadent, bourgeois in its values, bankrupt, and violent.' Is it any wonder that they rejected us in toto.\" (p. xiii) Reader note: McCarthyism is seen now as a reactionary backlash to issues as far ranging as women's suffrage , child labor laws , and gay rights , as well as a means for certain politicians to use fear to keep power. The FBI is also implicated heavily in performing illegal spying. There are loophopes for domestic spying used by the FBI today .","title":"McCarthy Era"},{"location":"docs/digests/rules_for_radicals_1971/#young-vs-old","text":"Young people have seen 'activist democracies' turn into 'nihilistic bombing and murder' and there is no panacea for it as there was in the past, 'revolution in Russia and China has since become the same old stuff under a different name'. Young people are looking for a way of life that has some meaning or sense: religion, political philosophy, science, or ideologies. The small world of the past inspired trust, and the big world of today inspires confusion and incomprehensibility. Generation Gap - Older people think younger people haven't learned how the world is, younger people think the old people will never get with the changing times. Approaches to the chaotic world by the young: Panic and run - \"copping out\" Hippies and Yuppies Taking drugs Trying communes Anything to escape Sure-loser confrontations: \"We tried and did our part\" Dying Jail Followed by panic and run, \"copping out\" Guilt and \"not knowing where to turn to\" Suicide Contempt \"take off for Algeria\" There are no rules for revolution as there are for revelation.","title":"Young vs. Old"},{"location":"docs/digests/rules_for_radicals_1971/#there-are-no-rules-for-revolution-but-there-are-rules-for-radicals","text":"\"Remember we are talking about revolution, not revelation; you can miss the target by shooting too high as well as too low. First, there are no rules for revolution any more than there are rules for love or rules for happiness, but there are rules for radicals who want to change their world; there are central concepts of action in human politics that operate regardless of the scene or the time. To know these is basic to a pragmatic attack on the system. These rules make the difference between a realistic radical and being a rhetorical one who uses the tired old words and slogans, calls the police 'pig' or 'white fascist racist' or 'motherfucker' and has so stereotyped himself that others react by saying, 'oh, he's one of those ,' and then promptly turn off.\" (p. xviii)","title":"There are no rules for revolution but there are rules for radicals."},{"location":"docs/digests/rules_for_radicals_1971/#communication","text":"Throughout history, silence has been regarded as assent -- in this case, assent to the system. If you cannot communicate in a way that your audience listens to you, you are silent no matter how loudly you scream. The inference here is that if you are not accepted in the community you wish to change, you are assenting to the system by not truly seeking a path to change that brings the community with you. Communicate within the experience of your audience Pay full respect to its values A fool attacks the American flag: it is the establishment which has betrayed the flag while the flag, itself, remains the glorious symbol of America's hopes and aspirations Humor and comedy are essential Through humor much is accepted that would be rejected if presented seriously. Note: People want to laugh and find joy in whatever they do. It inspires growth more than anything. Radicalism is social Do it for, and with, people If the real radical finds that having long hair sets up psychological barriers to communication and organization, he cuts his hair. Start your battle where the world is, not where you would like it to be. Work inside the system Dostoyevsky said that taking a new step is what people fear the most. Any revolutionary change must be preceded by a passive, affirmative, non-challenging attitude toward change among the mass of our people. They must feel so frustrated, so defeated, so lost, so futureless in the prevailing system that they are willing to let go of the past and chance the future. That acceptance is the reformation essential to any revolution. To bring on this reformation requires that the organizer work inside the system, among not only the middle class but the 40 percent of American families... whose income ranges from $5000 to$10000 a year [in 1971 dollars]... IF we fail to communicate with them... they will move to the right... maybe they will anyways, but lets not let it happen by default. (p. xix)","title":"Communication"},{"location":"docs/digests/rules_for_radicals_1971/#non-violence","text":"Violence is absurd when the other side has all the guns. Just one violent incident like has happened in the US would have resulted in a sweeping purge and mass executions in Russia, China, or Cuba. Lets keep some perspective. (paraphrased) Remember that we have the freedom to fight with our words and to build an opposition base against the administration.","title":"Non-Violence"},{"location":"docs/digests/rules_for_radicals_1971/#start-with-the-system","text":"There is no other place to start. Revolution is precededed by Reformation Also called popular reformation of your opposition political base People need a bridge to cross from their own experience to a new way Shake up the patterns of their lives Agitate Create Disenchantment Discontent with current values Goal: Produce a passive, affirmative, non-challenging climate or a passion for change in the political base . Revolution without prior reformation will collapse or become totalitarian tyranny. Reformation - People are fed up with past ways. They don't know what will work but they know that the present system is hopeless. They won't act for change but won't strongly oppose those who do. Then the time is ripe for revolution .","title":"Start with the system"},{"location":"docs/digests/rules_for_radicals_1971/#participation","text":"Citizen participation is the animating spirit and force in a society predicated on voluntarism. We are not here concerned with people who profess the democratic faith but yearn for the dark security of dependency where they can be spared the burden of decisions. To lose your \"identity\" as a citizen of democracy is but a step from losing your identity as a person. People react to this frustration by not acting at all. Hang on to one of the most precious parts of youth, laughter... (p. xxvii)","title":"Participation"},{"location":"docs/digests/rules_for_radicals_1971/#chapter-1-the-purpose","text":"\"The Prince\" by Machiavelli is for the Haves on how to hold power. \"Rules for Radicals\" is for the Have Nots on how to take it away.","title":"Chapter 1 - The Purpose"},{"location":"docs/digests/rules_for_radicals_1971/#defining-this-book","text":"Purpose: Create mass organizations to seize power and give it to the people. Premise: The significant changes in history have been made by revolutions. Content: The book proposes: Certain general observations propositions concepts of the mechanics of mass movements various stages of the cycle of action and reaction in a revolution This book will not contain any panacea or dogma; I detest and fear dogma. I know that all revolutions must have ideologies to spur them on. That in the heat of conflict these ideologies tend to be smelted into rigid dogmas claiming exclusive possession of the truth, and the keys to paradise, is tragic. Dogma is the enemy of human freedom. Dogma must be watched for and apprehended at every turn and twist of the revolutionary movement... To diminish the danger that ideology will deteriorate into dogma, and to protect the free, open, questing, and creative mind of man, as well as to allow for change, no ideology should be more specific than that of America's founding fathers: \"For the general welfare.\" (p. 4)","title":"Defining This Book"},{"location":"docs/digests/rules_for_radicals_1971/#political-sensitivity-control-over-events","text":"Resilient , Adaptable , and Sensitive \"Radicals must have a degree of control over the flow of events\" Have a plan for each branch in the path Adaptable: Merge the plan, old plans, similar experiences Adapt to shifting political circumstances Resilient: Don't back down!! Sensitive: find , create , and take opportunities Avoid being trapped by your own tactics Forced to travel a road not of your choosing. Keep the initiative. Do not pass the initiative. Keep things in motion!!","title":"Political Sensitivity & Control Over Events"},{"location":"docs/digests/rules_for_radicals_1971/#revolutionary-how-to-guides-are-rare","text":"This text is dedicated to splitting two atomic ideas: revolution from communism Revolutionary literature is sparse! Literature extolling the virtues of the Haves is prolific Literature decrying revolution as reptilian, evil, and hellish is prolific To the status quo, revolution \"is the only force which has no image, but instead casts a dark, ominous shadow of things to come.\" A significant body of communist revolutionary literature exists It is embedded in the \"language of communism, red and yellow\" Tactics, maneuvers, strategy, and principles of action in the making of revolutions Today's situation is suicidal: revolution and communism have become one in peoples' minds We only accept revolution if it is guaranteed to be on our side and we can't find a way out Revolution is associated with communism \"The Status Quo\" is associated with capitalism","title":"Revolutionary \"how-to\" Guides Are Rare"},{"location":"docs/digests/rules_for_radicals_1971/#section-the-ideology-of-change","text":"Question: What, if any, is my ideology? The prerequisite for ideology is possession of a basic truth Easy for christians, marxists Hard for an organizer working for open society, who must be a political relativist A free-society organizer is free of the shackles of dogma One belief: that people, given the power to act, will do the right thing in the long run, most of the time Politics of Change : free to focus on what matters to people now, rather than serve a dogma Note: This is perhaps better called the un-dogma of a free society. Political realists see the world as it is: an arena of power politics moved primarily by perceived immediate self-interests, where morality is rhetorical rationale for expedient action and self-interest. (p.12)","title":"Section: The Ideology of Change"},{"location":"docs/digests/rules_for_radicals_1971/#duality-of-revolution-and-counter-revolution","text":"Accept and embrace the duality of revolution and counter-revolution . If you understand the big picture of revolution and counter-revolution then you can seek to alter the historical pattern of \"two steps forwards, one step back\". Examples of the duality of revolution and reaction (p. 16) Urban Housing Projects - A dream of replacing the tenements vs. a doubly segregated place. CIO + AF of L - CIO reforming AF of L becomes entrenched member of establishment as AFLCIO etc.","title":"Duality of Revolution and Counter-Revolution"},{"location":"docs/digests/rules_for_radicals_1971/#section-class-distinctions-the-trinity","text":"Three Parts of Mankind Haves : want to keep power, money, food, security, luxury determined to freeze the Status Quo \"When do we sleep?\" - fear violent uprising Have-Nots : want to get poverty, rotten housing, disease, ignorance, political impotence, despair jobs pay the least deprived in all areas basic to human growth caged by color physical or political, barred from representation hate the establishment, opulence, police, courts, churches Justice, morality, law, and order are mere words when used by the Haves : justify and secure the status quo Power in Numbers. \"When do we eat?\", \"get off our backs\" Have-A-Little, Want Mores : the middle class Torn between status quo and change things to get more social, economic, political schizoids Generally seek the safe way Insist on three aces in their hand before playing the poker game of revolution Majority in the US, and generally in Western society. Argument by Alinksy that the greats come out of the middle class The middle class spawns people who provoke action but Do Nothing , \"I agree with your ends but not with your means.\" Act as a blanket for the sparks of disension. The book will examine both the Doers and the Do-Nothings . Edmund Burke: \"The only thing necessary for the triumph of evil is for good men to do nothing.\" Alice in Wonderland : Tiger-Lily points out that the flowers that talk grow out of hard beds of ground. In most gardens, they make the beds too soft so that the flowers are always asleep. (p. 21) Change means movement. Movement means friction. Only in the frictionless vacuum of a nonexistent abstract world can movement or change occur without that abrasive friction of conflict. In these pages it is our open political purpose to cooperate with the great law of change; to want otherwise would be like King Canute's commanding the tides and waves to cease. Alinsky's personal philosophy is anchored in optimism. If we imagine the struggle as a mountain, we must visualize a mountain with no top.... Knowing that the mountain has no top... Why do we continue? ... because it's there... Different than Sisyphis, doomed to have the boulder roll back down again. We see new vistas at each plateau.","title":"Section: Class Distinctions: The Trinity"},{"location":"docs/digests/rules_for_radicals_1971/#the-low-road-to-morality","text":"If you have bread and your neighbor has none, he will kill you and eat yours. We must accept that we rely on each other to continue a free society. You must share some of your wealth, or lose all of it. Remember: organizations are wealth, you can't destroy everyone. Note: Following this low road, welfare and basic income can be viewed, for better or for worse, as ransom on society's wealth. This is the low road to morality. There is no other. (p. 23)","title":"The low road to morality."},{"location":"docs/digests/rules_for_radicals_1971/#chapter-2-of-means-and-ends","text":"","title":"Chapter 2 - Of Means and Ends"},{"location":"docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/","text":"Thoughts on \"The Tyranny of Structurelessness\" by Jo Freeman Referenced work: http://www.jofreeman.com/joreen/tyranny.htm Thoughts - October 2017 This paper is not an attack on the informal elite, but an attack on how structurelessness overempowers the INEVITABLE informal elite The author says: if the informal elite is both well structured and exercises fair amounts of power, then it should become formalized. let us hope no informal elite at noisebridge ever does these things. (anyways, that assumes the author's premise is correct in blanket terms, which is a safe assumption as long as we don't fill her preconditions for formalization) In other words, as long as any informal elite at noisebridge doesn't fill her conditions for formalization, it is not necessary to make judgments about the author's correctness and reject or implement her recommendation (which would be formalizing a power structure). I agree that formalization is often used to hide the elites and prevent other elites from forming. In corporations, the internal elites (corporate officers) often create snaking structures for middle management, but recruit new elites from outside the organization except in exceptional cases, which usually bypass the 'snaking structures' I agree that formalization is usually a means of consolidating power I agree that sometimes formalization exists by the grace of elites and that elites leave or crush formal structures that stop benefiting them I think that some organizations might outgrow their original elites, accumulating a high amount of a certain type of capital, e.g. media attention, can legitimize the formal power structure and cause the elites to be sloughed off, who then go make something else. Especially if the elites were there for a different reason than that accumulated capital. I think formal structure is necessary, but that spending the energy developing a custom-fit is too challenging for most organizations, and the \"standard structures\" we adopt don't fit very well at all. I think it's totally spooky how well this paper predicts things It definitely says explicitly that groups like this are natural and important, and outlines how they can become awful. I think her last section, \"Principles of Democratic Structuring\" is tailor-fit to some particular organizations in the women's liberation movement that already had lots of established capital at stake They were probably good candidates for a higher quantity of structure to wield that capital as an interface to the rest of the humans I don't think it fits the general tone of the paper.","title":"Thoughts On Tyrrany Of Structurelessness Jo Freeman"},{"location":"docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/#thoughts-on-the-tyranny-of-structurelessness-by-jo-freeman","text":"Referenced work: http://www.jofreeman.com/joreen/tyranny.htm","title":"Thoughts on \"The Tyranny of Structurelessness\" by Jo Freeman"},{"location":"docs/digests/thoughts-on-tyrrany-of-structurelessness-jo-freeman/#thoughts-october-2017","text":"This paper is not an attack on the informal elite, but an attack on how structurelessness overempowers the INEVITABLE informal elite The author says: if the informal elite is both well structured and exercises fair amounts of power, then it should become formalized. let us hope no informal elite at noisebridge ever does these things. (anyways, that assumes the author's premise is correct in blanket terms, which is a safe assumption as long as we don't fill her preconditions for formalization) In other words, as long as any informal elite at noisebridge doesn't fill her conditions for formalization, it is not necessary to make judgments about the author's correctness and reject or implement her recommendation (which would be formalizing a power structure). I agree that formalization is often used to hide the elites and prevent other elites from forming. In corporations, the internal elites (corporate officers) often create snaking structures for middle management, but recruit new elites from outside the organization except in exceptional cases, which usually bypass the 'snaking structures' I agree that formalization is usually a means of consolidating power I agree that sometimes formalization exists by the grace of elites and that elites leave or crush formal structures that stop benefiting them I think that some organizations might outgrow their original elites, accumulating a high amount of a certain type of capital, e.g. media attention, can legitimize the formal power structure and cause the elites to be sloughed off, who then go make something else. Especially if the elites were there for a different reason than that accumulated capital. I think formal structure is necessary, but that spending the energy developing a custom-fit is too challenging for most organizations, and the \"standard structures\" we adopt don't fit very well at all. I think it's totally spooky how well this paper predicts things It definitely says explicitly that groups like this are natural and important, and outlines how they can become awful. I think her last section, \"Principles of Democratic Structuring\" is tailor-fit to some particular organizations in the women's liberation movement that already had lots of established capital at stake They were probably good candidates for a higher quantity of structure to wield that capital as an interface to the rest of the humans I don't think it fits the general tone of the paper.","title":"Thoughts - October 2017"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/","text":"Notes on Calculus - Early Transcendentals 9th Ed. by Stewart The 8th edition is the first book recommended by https://www.susanrigetti.com/math . However, there is a 9th edition so I got that. How to Study by Susan Rigetti: I learn the same way as Susan and hope to use LaTeX a lot, but may use a blend based on learning facility with or without tech in the loop. Every person learns in their own special way, and knowing your learning style is important: do you learn by reading, by taking notes, by talking, by watching, by doing, or by a combination of some or all of these? For example, I learn by reading and by note-taking, so I read through textbooks very carefully, take copious notes, and summarize each concept in my own words before moving on to something new. Think about this before you begin so that you'll know how to structure your studies. Regardless of your learning style, you'll still need to solve the problems in each textbook. Just like in physics, solving problems is the only way to understand mathematics. There's no way around it. One tough thing about learning on your own is that you may not know whether you are solving the problems correctly. A number of the textbooks listed below have answers to selected exercises in the back of the book, but these aren\u2019t always adequate for two reasons: (1) they often only show the solutions to the problems, and not the steps taken to get there; and (2) it\u2019s much better to do all of the exercises rather than just a select few. The good news is that many of the solutions (and step-by-step ways to solve them) can be found online with a simple google search. If you are going to google the answers, however, please first try to solve the problems on your own, and try multiple times (you\u2019re not in school trying to get a perfect grade \u2014 you\u2019re trying to learn and understand). Notes & Assignments with LaTeX It is strongly recommended that I take notes using LaTeX. Supposedly I can learn enough LaTeX in an afternoon using the LaTeX/Basics wikibook I hope github displays latex visually, I will have to test it. Vim+LaTeX == lervag/vimtex A Complete Guide on Writing LaTeX with Vimtex in Neovim Use the help in vim: :h vimtex-completion :h vimtex-default-mappings LaTeX Resources I'm planning to work with vim-tex, but am interested in trying gui editors potentially. The integrated skim viewer is a lot like my old macdown workflow so I am excited about it. homework.tex: Homework Template How I'm able to take notes in mathematics lectures using LaTeX and Vim zathura on macox i am giving up on this for now and trying skim with vim-tex (replace zathura in vimrc) detexify: Find LaTeX Symbols lyx: editor, available in homebrew too long list of latex editors reddit: how to learn LaTeX TeX: LaTeX stack exchange Versions I am reading these and bookmarking them on the kindle app to save bookmarks temporarily between devices using kindle. I suspect all important notes will not require these bookmarks and they are just for convenience. Calculus_EarlyTranscendenals_9th_Solutions_Stewart.pdf Calculus_EarlyTranscendenals_9th_Stewart.pdf","title":"Readme"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#notes-on-calculus-early-transcendentals-9th-ed-by-stewart","text":"The 8th edition is the first book recommended by https://www.susanrigetti.com/math . However, there is a 9th edition so I got that.","title":"Notes on Calculus - Early Transcendentals 9th Ed. by Stewart"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#how-to-study-by-susan-rigetti","text":"I learn the same way as Susan and hope to use LaTeX a lot, but may use a blend based on learning facility with or without tech in the loop. Every person learns in their own special way, and knowing your learning style is important: do you learn by reading, by taking notes, by talking, by watching, by doing, or by a combination of some or all of these? For example, I learn by reading and by note-taking, so I read through textbooks very carefully, take copious notes, and summarize each concept in my own words before moving on to something new. Think about this before you begin so that you'll know how to structure your studies. Regardless of your learning style, you'll still need to solve the problems in each textbook. Just like in physics, solving problems is the only way to understand mathematics. There's no way around it. One tough thing about learning on your own is that you may not know whether you are solving the problems correctly. A number of the textbooks listed below have answers to selected exercises in the back of the book, but these aren\u2019t always adequate for two reasons: (1) they often only show the solutions to the problems, and not the steps taken to get there; and (2) it\u2019s much better to do all of the exercises rather than just a select few. The good news is that many of the solutions (and step-by-step ways to solve them) can be found online with a simple google search. If you are going to google the answers, however, please first try to solve the problems on your own, and try multiple times (you\u2019re not in school trying to get a perfect grade \u2014 you\u2019re trying to learn and understand).","title":"How to Study by Susan Rigetti:"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#notes-assignments-with-latex","text":"It is strongly recommended that I take notes using LaTeX. Supposedly I can learn enough LaTeX in an afternoon using the LaTeX/Basics wikibook I hope github displays latex visually, I will have to test it.","title":"Notes & Assignments with LaTeX"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#vimlatex-lervagvimtex","text":"A Complete Guide on Writing LaTeX with Vimtex in Neovim Use the help in vim: :h vimtex-completion :h vimtex-default-mappings","title":"Vim+LaTeX == lervag/vimtex"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#latex-resources","text":"I'm planning to work with vim-tex, but am interested in trying gui editors potentially. The integrated skim viewer is a lot like my old macdown workflow so I am excited about it. homework.tex: Homework Template How I'm able to take notes in mathematics lectures using LaTeX and Vim zathura on macox i am giving up on this for now and trying skim with vim-tex (replace zathura in vimrc) detexify: Find LaTeX Symbols lyx: editor, available in homebrew too long list of latex editors reddit: how to learn LaTeX TeX: LaTeX stack exchange","title":"LaTeX Resources"},{"location":"docs/digests/calculus_early_transcendentals_9th_stewart/#versions","text":"I am reading these and bookmarking them on the kindle app to save bookmarks temporarily between devices using kindle. I suspect all important notes will not require these bookmarks and they are just for convenience. Calculus_EarlyTranscendenals_9th_Solutions_Stewart.pdf Calculus_EarlyTranscendenals_9th_Stewart.pdf","title":"Versions"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/","text":"Design Patterns in Python Gang of Four book, translated to Python. End-of-section coding exercise. One Python file per demo. \"Latest\" version of Python (as of when?) liberal use of decorators, metaclasses where applicable external packages will also be used if valuable Author Dmitri Nesteruk, quant finance professional Course author on: Pluralsight, Udemy, Elsewhere Design patterns in: C#, Java, C++, Swift, Python Other Topics Sequence processing (streams/Rx) Concurrency Dependency injection Languages picked up these design patterns already C# implementation of observer pattern Python implementation of decorator third party libraries Three Categories of Design Patterns All from the book. Creational Builder Factories (two patterns): Abstract Factory, Factory Method Prototype Singleton Structural Adapter Bridge Composite Decorator Facade Flyweight Proxy Behavioral Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor Solid Design Principles Introduced by \"Uncle Bob\", Robert C. Martin Multiple books, plus blog There are a rather large number of design principles 5 selected SOLID Single Responsibility Principle (SRP): \"Separation of Concerns\" Open-Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle 1. Single Responsibility Principle (SRP): \"Separation of Concerns\" Example: Journal class that also has persistence (save, load) Journal class stores and allows manipulating entries, but then also gets functionality for persistence. This is a bad idea for a number of reasons. Persistence would go in its own class. Instead write a PersistenceManager class with a static save_to_file(j, filename) method. Antipattern: 'God Object', everything into a single class. 2. Open-Closed Principle: \"Open for Extension, Closed for Modification.\" Example: Product has some properties, size, color. How do you filter product by color? Use a for loop to filter by color. But now we want to filter by size. When you add new functionality, add by extension, not modification. Now try filter by color and size... you add a third function for color AND size. This approach is combinatorial. You are also causing a state-space explosion . Add weight and for 3 params you need summation(3) filters: 3+2+1 Lets add the new filters through modification and use an \"enterprise pattern\". \"Enterprise patterns require a separate course.\" Enterprise Pattern: \"Specification\" class Product : def __init__ ( self , name , color , size ) : self . name = name self . color = color self . size = size # OCP = open for extension, closed for modification # see the course resources for the full implementation with some testing class Specification : ' '' determine if an item specifies a criteria This is a base class. You are intended to override the methods. '' ' def is_satisfied ( self , item ) : pass # this is explained later, i think it's foolish and breaks expectations for the reader of the code... def __and__ ( self , other ) : return AndSpecification ( self , other ) class Filter : ' '' General method, doesn' t specify any particular criteria . This is a base class . You are intended to override the methods . ' '' def filter(self, items, spec): pass class ColorSpecification(Specification): def __init__(self, color): self.color = color def is_satisfied(self, item): return item.color == self.color class SizeSpecification(Specification): def __init__(self, size): self.size = size def is_satisfied(self, item): return item.size == self.size class BetterFilter(Filter): def filter(self, items, spec): for item in items: if spec.is_satisfied(item): yield item # How do we implement the combinator `AND` with these? class AndSpecification(Specification): '' ' check that any number of specifications apply ' '' def __init__(self, *args): self.args = args def is_satisfied(self, item): # NB: all() returns True if empty, but false for e.g. [ '' ] or [None] return all(map( lambda spec: spec.is_satisfied(item), self.args )) # This is the combinator large_and_blue = AndSpecification(SizeSpecification(Size.LARGE), ColorSpecification(Color.BLUE)) bf = BetterFilter() for p in bf.filter(products, large_and_blue) # we want to simplify large_and_blue though, we can overload the `binary and` operator, `&` # lets do this in `Specification` above, are we breaking the open closed principle? no we would do this at the beginning (trent: not business realistic...) # This is silly, breaks type expectation for reader. Just keep it simple, accumulate and explode a sequence or something large_and_blue = SizeSpecification(Size.LARGE) & ColorSpecification(Color.BLUE) 3. Liskov Substitution Principle Named after Barbara Liskov. If you have an interface named after a base class you should be able to stick a derived class in and everything should work. Imagine a Rectangle class and a Square class that inherits from rectangle. Square should work wherever rectangle worked. So maybe we expect width*height=area , where class rectangle has each @property : width, height. so for square, lets just take one dimension, size , since width is height. Now if we set width and height at the same time, both from size , \"this looks very innocent\" now if we use use_it , it only works on a rectangle, because it sets width, height explicitly. We can fix use_it a few ways: don't have a square class (doesn't solve use_it), don't allow the setters trent: avoid square class is the right answer, we should still use @property in Python. trent: so this means that our descendants are constrained by our downstream implementations? i don't love this... So uh... When we need to refactor, we need to enumerate downstream impelementation before we can subclass something? Well, alright... 4. Interface Segregation Principle If you have a \"kitchen sink interface\", then individual implementations have a bunch of NOOP methods. If someone makes an instance of a limited implementation, they try using the NOOP methods. 5. Dependency Inversion Principle","title":"Intro And Solid Design Principles"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#design-patterns-in-python","text":"Gang of Four book, translated to Python. End-of-section coding exercise. One Python file per demo. \"Latest\" version of Python (as of when?) liberal use of decorators, metaclasses where applicable external packages will also be used if valuable","title":"Design Patterns in Python"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#author","text":"Dmitri Nesteruk, quant finance professional Course author on: Pluralsight, Udemy, Elsewhere Design patterns in: C#, Java, C++, Swift, Python","title":"Author"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#other-topics","text":"Sequence processing (streams/Rx) Concurrency Dependency injection","title":"Other Topics"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#languages-picked-up-these-design-patterns-already","text":"C# implementation of observer pattern Python implementation of decorator third party libraries","title":"Languages picked up these design patterns already"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#three-categories-of-design-patterns","text":"All from the book. Creational Builder Factories (two patterns): Abstract Factory, Factory Method Prototype Singleton Structural Adapter Bridge Composite Decorator Facade Flyweight Proxy Behavioral Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor","title":"Three Categories of Design Patterns"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#solid-design-principles","text":"Introduced by \"Uncle Bob\", Robert C. Martin Multiple books, plus blog There are a rather large number of design principles 5 selected SOLID Single Responsibility Principle (SRP): \"Separation of Concerns\" Open-Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle","title":"Solid Design Principles"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#1-single-responsibility-principle-srp-separation-of-concerns","text":"Example: Journal class that also has persistence (save, load) Journal class stores and allows manipulating entries, but then also gets functionality for persistence. This is a bad idea for a number of reasons. Persistence would go in its own class. Instead write a PersistenceManager class with a static save_to_file(j, filename) method. Antipattern: 'God Object', everything into a single class.","title":"1. Single Responsibility Principle (SRP): \"Separation of Concerns\""},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#2-open-closed-principle-open-for-extension-closed-for-modification","text":"Example: Product has some properties, size, color. How do you filter product by color? Use a for loop to filter by color. But now we want to filter by size. When you add new functionality, add by extension, not modification. Now try filter by color and size... you add a third function for color AND size. This approach is combinatorial. You are also causing a state-space explosion . Add weight and for 3 params you need summation(3) filters: 3+2+1 Lets add the new filters through modification and use an \"enterprise pattern\". \"Enterprise patterns require a separate course.\"","title":"2. Open-Closed Principle: \"Open for Extension, Closed for Modification.\""},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#enterprise-pattern-specification","text":"class Product : def __init__ ( self , name , color , size ) : self . name = name self . color = color self . size = size # OCP = open for extension, closed for modification # see the course resources for the full implementation with some testing class Specification : ' '' determine if an item specifies a criteria This is a base class. You are intended to override the methods. '' ' def is_satisfied ( self , item ) : pass # this is explained later, i think it's foolish and breaks expectations for the reader of the code... def __and__ ( self , other ) : return AndSpecification ( self , other ) class Filter : ' '' General method, doesn' t specify any particular criteria . This is a base class . You are intended to override the methods . ' '' def filter(self, items, spec): pass class ColorSpecification(Specification): def __init__(self, color): self.color = color def is_satisfied(self, item): return item.color == self.color class SizeSpecification(Specification): def __init__(self, size): self.size = size def is_satisfied(self, item): return item.size == self.size class BetterFilter(Filter): def filter(self, items, spec): for item in items: if spec.is_satisfied(item): yield item # How do we implement the combinator `AND` with these? class AndSpecification(Specification): '' ' check that any number of specifications apply ' '' def __init__(self, *args): self.args = args def is_satisfied(self, item): # NB: all() returns True if empty, but false for e.g. [ '' ] or [None] return all(map( lambda spec: spec.is_satisfied(item), self.args )) # This is the combinator large_and_blue = AndSpecification(SizeSpecification(Size.LARGE), ColorSpecification(Color.BLUE)) bf = BetterFilter() for p in bf.filter(products, large_and_blue) # we want to simplify large_and_blue though, we can overload the `binary and` operator, `&` # lets do this in `Specification` above, are we breaking the open closed principle? no we would do this at the beginning (trent: not business realistic...) # This is silly, breaks type expectation for reader. Just keep it simple, accumulate and explode a sequence or something large_and_blue = SizeSpecification(Size.LARGE) & ColorSpecification(Color.BLUE)","title":"Enterprise Pattern: \"Specification\""},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#3-liskov-substitution-principle","text":"Named after Barbara Liskov. If you have an interface named after a base class you should be able to stick a derived class in and everything should work. Imagine a Rectangle class and a Square class that inherits from rectangle. Square should work wherever rectangle worked. So maybe we expect width*height=area , where class rectangle has each @property : width, height. so for square, lets just take one dimension, size , since width is height. Now if we set width and height at the same time, both from size , \"this looks very innocent\" now if we use use_it , it only works on a rectangle, because it sets width, height explicitly. We can fix use_it a few ways: don't have a square class (doesn't solve use_it), don't allow the setters trent: avoid square class is the right answer, we should still use @property in Python. trent: so this means that our descendants are constrained by our downstream implementations? i don't love this... So uh... When we need to refactor, we need to enumerate downstream impelementation before we can subclass something? Well, alright...","title":"3. Liskov Substitution Principle"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#4-interface-segregation-principle","text":"If you have a \"kitchen sink interface\", then individual implementations have a bunch of NOOP methods. If someone makes an instance of a limited implementation, they try using the NOOP methods.","title":"4. Interface Segregation Principle"},{"location":"docs/digests/design-patterns-in-python/intro-and-solid-design-principles/#5-dependency-inversion-principle","text":"","title":"5. Dependency Inversion Principle"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/","text":"Chunking, Practice, and Recall These notes are my reinterpretation of the material of week 2 (of 4 weeks) of the online course \"Learning How to Learn\" on Coursera by Dr. Barabra Oakley. TODOs There are a few in the document. Important TODO: \"Maintaining a Library of Chunks Topics What is a chunk? How to form a chunk? Pitfalls Extending the analogy A \"Library of Chunks\" Additional context What is a chunk? Human brains have 4 slots of working memory, you can think of your reasoning as 4 armed octopus able to touch only 4 remembered items at a time. A chunk is a collection of memories that form a concept. For example, the snick of a pop bottle opening connects to the word \"pop\" and the letters \"p\" \"o\" \"p\". One is a qualia, the other is a logical construction through written phoenetic glyphs. You can also sketch a can of pop as a visual qualia for this chunk. A chunk can be very large or small. The course says a chunk is like compression but this anaology is flawed, because a chunk itself is more like a nexus of memories and reasonings. A chunk is like a summary with hyperlinks to related chunks that might be larger or smaller in size or relationship. A chunk might be tightly related to some chunks and loosely related to other chunks. \"Conceptual chunk\": Mental leap that unites scattered bits through memory. Trent: There is a concept of scattered bits of memory that are not worth detailing as their own chunk in your context of study. It may or may not be useful to focus in on any of these scattered bits as chunks themselves. For example, in the \"pop\" chunk, the letter \"p\" is a scattered bit, but it has its own chunk with a lot of context, like the vocalization of the letter, it's various forms, \"P\", 'p\", its history through the history of language. But, you probably do not wish to develop that chunk when focusing on a different topic, e.g. the topic at hand, \"learning what a chunk is\". Every discipline is a little different for memories. Imagine: walking, doing a math problem, and telling a story. Synthesizing a collection of chunks and creatively integrating two different chunks in a new context are related to the idea of \"expertise\". Transfer : A chunk in one discipline might share commonalities with a chunk in a different discipline. Trent's Thought Experiment about connecting unrelated chunks This is kind of like mad libs . Thought experiment: How are my grandmother's favorite shoes related to household accounting practices? I know my grandmother is good at accounting, and this starts to fire a lot of memories about how she learned these skills since she did not have much education. This road of obtuse reasoning is long. Thought experiments about unrelated chunks can yield interesting connections. Expertise and Creative Integration Expertise is chunking and performing creative interpretations as you gain fluency. How to form a chunk? Perform these steps when practicing or studying material. 1. \"Undivided Attention\" Turn off all notifications Any single interruption \"uproots\" some neural connections being made (weaker foundation) 2. \"Understand\" Get the \"main idea\" or \"gist\": \"top down learning\" \"Superglue\" the pieces together \"Broad traces\" and \"link to other traces you have\" Finding links to other knowledge will stimulate dopamine reward Do a picture walk through a chapter before reading it 3. \"Gain Context\" - \"deliberate practice\", \"recall\", \"review\", \"when to use the chunk\" Perform: \"deliberate practice\": Process: work on primarily difficult problems TODO: How do we identify \"difficult problems\" in each of the below contexts? problem sets (math, sciences, computer science, etc.) practical experience (medicine, carpentry) physical techniques (judo, dancing) songs foreign language conversations ... (what else?) Perform: \"recall\" Process: Remember everything you can with only your brain: simply use your mind, or use a blank docoument Review your notes against the material, identifying gaps Mediums: Mind: Simply recall what you can, then recall what you can about each item Not easy to validate against the notes later, maybe has other benefits? Physical: Outline, Diagrams, Notes, Sketches, Paragraphs (paper or digital) Easy to validate your progress/success Can create a more organized permanent reference Recall in a different place to decouple your access to a chunk from where you learned it Generation Effect : \"The generation effect is a phenomenon where information is better remembered if it is generated from one's own mind rather than simply read\" On the first recall, you will prime the generation effect, creating \"neural hooks\" On the second recall, you will take advantage of the generation effect. Wikipedia: Generation Effect Trent: probably can do this 1x before needing to dip back into \"diffuse mode\" (workout, sleep, socialize) Perform: \"review\" Perform more \"deliberate practice\" and \"recall\" with previous related chunks. New relationships with the old material and the new material will be stronger Review the material both \"forwards\" and \"backwards\" Learn WHEN to use the \"chunk\" Analogy: when to use a hammer vs a mallet \"Do a picture walk through a chapter before reading it\" Know how the \"pieces of the puzzle\" fit together (knowledge inside the chunk) 4. \"Repair the Flaws\" Process: Identify your misunderstandings and repeat \"deliberate proactice\" with the right ideas This is part of the same study methods above It's important enough here to call out as a step 5. \"Interleaving during Practice\" Mix up your learning within a subject or even between multiple subjects Find other contexts that have this chunk or a similar chunk In a textbook, read through nearby problem sets to find other applications that contain the problem Trent: Time intensive? How to get a library of interleaved problems quickly? Example: Learning a guitar song I like this analogy because it is easy to \"test\" if the song sounds right. \"Understand\" Listen to the song \"Practice\" Grasp bits of the song Review chords and notes and be able to play them Join passages until you know all the parts Try the whole song keep improving Pitfalls Working memory doesn't work as well under stressors: low sleep, stress, sickness, etc. Rereading material once you have context Instead use \"recall\" then compare the material to your recall results Research supports that this is a comparatively better method for learning Compared to some other methods: concept maps, notes, rereading Probably still want to take notes, that's done during studying and can be used for recall comparison Overlearning Repeating problems you already learned Usually a waste of time, instead try to \"cover a lot of ground\" Instead: Once you get more context with more chunks, then repeat your old problems It is useful if you need \"the perfect tennis serve\" Can be used positively to combat \"text anxiety\" but will cost time (tradeoff) Overtraining for perfect public speaking: \"A 20 minute TED Talk can take 70 hours of practice\" Einstellung Stuck in a way of \"focused mode\" thinking you already have Try taking a break, go into \"diffuse mode\" and reapproach the problem fresh later A \"Library of Chunks\" To develop expertise in a discipline, build two things: \"a bigger chunk library\" \"a more well-practiced chunk library\". Extending the analogy Consider a chunk as a ribbon of learning. The ribbon will grow wider and longer as you improve at making chunks. You might listen to the \"whispers of the diffuse mode\" that will forge a new connection between two distance places on the ribbon. Problem: Too much ground to cover! There are so many chunks in a discipline, how will you get to them all? \"Law of Serendipity\": Lady luck favors the one who tries. Solution: As you form a chunk, nearby chunks will be easier to form. A bigger \"library of chunks\" will naturally grow. But you must practice each chunk to make it \"wider\" which will make later practice cover more ground. Later practice will not get easier, but it will cover more ground at the same difficulty. Practicing related chunks will help you begin to classify \"types of chunks\" and \"classes of concepts\". I think these are probably also considred chunks. If you are well studied, you are probably already familiar with a library of \"types of problems\". TODO: Maintaining your \"Library of Chunks\" How can I stay in practice? I might have a group of chunks that I want to have front-of-mind. One shortcut would be to carefully maintain the library of problems I used to develop that chunk and periodically repeat solving those problems. Other parts of the founding material of chunks: primary readings, primary practices, related problems, related readings. How would a graph representation work for managing the inputs to developing a group of related chunks representing a discipline? Additional context \"Sequential Reasoning\" are focused mode reasonings \"Holistic Intution\" are diffuse mode ideas You MUST carefully verify \"holistic intuition\" with \"sequential reasoning\" Trent: Even modern physics has 2 incompatible models, I have enocuntered many people that try to use deductive logic on their mental models. Mental models are generally not sufficient to form a closed system. Deductive reasoning needs to be backed up with inductive facts if possible, otherwise it is generally too leaky and insufficient, especially in highly technical black box systems. Neurochemistry acetylcholine form new long term memory, synaptic plasticity, \"projects widely\" TODO Question: Does this mean this chemical helps form broader connections between topics? dopamine decision making, which sensory input your brain values (perception), released after unexpected reward (unexpected connection between two topics (chunk linking) serotonin risk taking, depression, loneliness, low perceived social rank causes high risk taking prozac is a prescription to increase serotonin Neurochemistry: how to control it for \"higher quality learning\" basic shared controls: sleep nutrition exercise acetylcholine TODO ?? dopamine \"understand\" connections to existing knowledge to release dopamine Celebrate: reward yourself after learning - releases dopamine mental pat on the back vocalized verbal celebration \"Yeah!\" serotonin maintain a healthy social structure that fits your needs focus on mental wellness and mental health therapy, medicine, sleep, exercise, nutrition","title":"Chunking Practice"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#chunking-practice-and-recall","text":"These notes are my reinterpretation of the material of week 2 (of 4 weeks) of the online course \"Learning How to Learn\" on Coursera by Dr. Barabra Oakley.","title":"Chunking, Practice, and Recall"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#todos","text":"There are a few in the document. Important TODO: \"Maintaining a Library of Chunks","title":"TODOs"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#topics","text":"What is a chunk? How to form a chunk? Pitfalls Extending the analogy A \"Library of Chunks\" Additional context","title":"Topics"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#what-is-a-chunk","text":"Human brains have 4 slots of working memory, you can think of your reasoning as 4 armed octopus able to touch only 4 remembered items at a time. A chunk is a collection of memories that form a concept. For example, the snick of a pop bottle opening connects to the word \"pop\" and the letters \"p\" \"o\" \"p\". One is a qualia, the other is a logical construction through written phoenetic glyphs. You can also sketch a can of pop as a visual qualia for this chunk. A chunk can be very large or small. The course says a chunk is like compression but this anaology is flawed, because a chunk itself is more like a nexus of memories and reasonings. A chunk is like a summary with hyperlinks to related chunks that might be larger or smaller in size or relationship. A chunk might be tightly related to some chunks and loosely related to other chunks. \"Conceptual chunk\": Mental leap that unites scattered bits through memory. Trent: There is a concept of scattered bits of memory that are not worth detailing as their own chunk in your context of study. It may or may not be useful to focus in on any of these scattered bits as chunks themselves. For example, in the \"pop\" chunk, the letter \"p\" is a scattered bit, but it has its own chunk with a lot of context, like the vocalization of the letter, it's various forms, \"P\", 'p\", its history through the history of language. But, you probably do not wish to develop that chunk when focusing on a different topic, e.g. the topic at hand, \"learning what a chunk is\". Every discipline is a little different for memories. Imagine: walking, doing a math problem, and telling a story. Synthesizing a collection of chunks and creatively integrating two different chunks in a new context are related to the idea of \"expertise\". Transfer : A chunk in one discipline might share commonalities with a chunk in a different discipline.","title":"What is a chunk?"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#trents-thought-experiment-about-connecting-unrelated-chunks","text":"This is kind of like mad libs . Thought experiment: How are my grandmother's favorite shoes related to household accounting practices? I know my grandmother is good at accounting, and this starts to fire a lot of memories about how she learned these skills since she did not have much education. This road of obtuse reasoning is long. Thought experiments about unrelated chunks can yield interesting connections.","title":"Trent's Thought Experiment about connecting unrelated chunks"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#expertise-and-creative-integration","text":"Expertise is chunking and performing creative interpretations as you gain fluency.","title":"Expertise and Creative Integration"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#how-to-form-a-chunk","text":"Perform these steps when practicing or studying material.","title":"How to form a chunk?"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#1-undivided-attention","text":"Turn off all notifications Any single interruption \"uproots\" some neural connections being made (weaker foundation)","title":"1. \"Undivided Attention\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#2-understand","text":"Get the \"main idea\" or \"gist\": \"top down learning\" \"Superglue\" the pieces together \"Broad traces\" and \"link to other traces you have\" Finding links to other knowledge will stimulate dopamine reward Do a picture walk through a chapter before reading it","title":"2. \"Understand\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#3-gain-context-deliberate-practice-recall-review-when-to-use-the-chunk","text":"Perform: \"deliberate practice\": Process: work on primarily difficult problems TODO: How do we identify \"difficult problems\" in each of the below contexts? problem sets (math, sciences, computer science, etc.) practical experience (medicine, carpentry) physical techniques (judo, dancing) songs foreign language conversations ... (what else?) Perform: \"recall\" Process: Remember everything you can with only your brain: simply use your mind, or use a blank docoument Review your notes against the material, identifying gaps Mediums: Mind: Simply recall what you can, then recall what you can about each item Not easy to validate against the notes later, maybe has other benefits? Physical: Outline, Diagrams, Notes, Sketches, Paragraphs (paper or digital) Easy to validate your progress/success Can create a more organized permanent reference Recall in a different place to decouple your access to a chunk from where you learned it Generation Effect : \"The generation effect is a phenomenon where information is better remembered if it is generated from one's own mind rather than simply read\" On the first recall, you will prime the generation effect, creating \"neural hooks\" On the second recall, you will take advantage of the generation effect. Wikipedia: Generation Effect Trent: probably can do this 1x before needing to dip back into \"diffuse mode\" (workout, sleep, socialize) Perform: \"review\" Perform more \"deliberate practice\" and \"recall\" with previous related chunks. New relationships with the old material and the new material will be stronger Review the material both \"forwards\" and \"backwards\" Learn WHEN to use the \"chunk\" Analogy: when to use a hammer vs a mallet \"Do a picture walk through a chapter before reading it\" Know how the \"pieces of the puzzle\" fit together (knowledge inside the chunk)","title":"3. \"Gain Context\" - \"deliberate practice\", \"recall\", \"review\", \"when to use the chunk\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#4-repair-the-flaws","text":"Process: Identify your misunderstandings and repeat \"deliberate proactice\" with the right ideas This is part of the same study methods above It's important enough here to call out as a step","title":"4. \"Repair the Flaws\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#5-interleaving-during-practice","text":"Mix up your learning within a subject or even between multiple subjects Find other contexts that have this chunk or a similar chunk In a textbook, read through nearby problem sets to find other applications that contain the problem Trent: Time intensive? How to get a library of interleaved problems quickly?","title":"5. \"Interleaving during Practice\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#example-learning-a-guitar-song","text":"I like this analogy because it is easy to \"test\" if the song sounds right. \"Understand\" Listen to the song \"Practice\" Grasp bits of the song Review chords and notes and be able to play them Join passages until you know all the parts Try the whole song keep improving","title":"Example: Learning a guitar song"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#pitfalls","text":"Working memory doesn't work as well under stressors: low sleep, stress, sickness, etc. Rereading material once you have context Instead use \"recall\" then compare the material to your recall results Research supports that this is a comparatively better method for learning Compared to some other methods: concept maps, notes, rereading Probably still want to take notes, that's done during studying and can be used for recall comparison Overlearning Repeating problems you already learned Usually a waste of time, instead try to \"cover a lot of ground\" Instead: Once you get more context with more chunks, then repeat your old problems It is useful if you need \"the perfect tennis serve\" Can be used positively to combat \"text anxiety\" but will cost time (tradeoff) Overtraining for perfect public speaking: \"A 20 minute TED Talk can take 70 hours of practice\" Einstellung Stuck in a way of \"focused mode\" thinking you already have Try taking a break, go into \"diffuse mode\" and reapproach the problem fresh later","title":"Pitfalls"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#a-library-of-chunks","text":"To develop expertise in a discipline, build two things: \"a bigger chunk library\" \"a more well-practiced chunk library\".","title":"A \"Library of Chunks\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#extending-the-analogy","text":"Consider a chunk as a ribbon of learning. The ribbon will grow wider and longer as you improve at making chunks. You might listen to the \"whispers of the diffuse mode\" that will forge a new connection between two distance places on the ribbon.","title":"Extending the analogy"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#problem-too-much-ground-to-cover","text":"There are so many chunks in a discipline, how will you get to them all? \"Law of Serendipity\": Lady luck favors the one who tries. Solution: As you form a chunk, nearby chunks will be easier to form. A bigger \"library of chunks\" will naturally grow. But you must practice each chunk to make it \"wider\" which will make later practice cover more ground. Later practice will not get easier, but it will cover more ground at the same difficulty. Practicing related chunks will help you begin to classify \"types of chunks\" and \"classes of concepts\". I think these are probably also considred chunks. If you are well studied, you are probably already familiar with a library of \"types of problems\".","title":"Problem: Too much ground to cover!"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#todo-maintaining-your-library-of-chunks","text":"How can I stay in practice? I might have a group of chunks that I want to have front-of-mind. One shortcut would be to carefully maintain the library of problems I used to develop that chunk and periodically repeat solving those problems. Other parts of the founding material of chunks: primary readings, primary practices, related problems, related readings. How would a graph representation work for managing the inputs to developing a group of related chunks representing a discipline?","title":"TODO: Maintaining your \"Library of Chunks\""},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#additional-context","text":"\"Sequential Reasoning\" are focused mode reasonings \"Holistic Intution\" are diffuse mode ideas You MUST carefully verify \"holistic intuition\" with \"sequential reasoning\" Trent: Even modern physics has 2 incompatible models, I have enocuntered many people that try to use deductive logic on their mental models. Mental models are generally not sufficient to form a closed system. Deductive reasoning needs to be backed up with inductive facts if possible, otherwise it is generally too leaky and insufficient, especially in highly technical black box systems.","title":"Additional context"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#neurochemistry","text":"acetylcholine form new long term memory, synaptic plasticity, \"projects widely\" TODO Question: Does this mean this chemical helps form broader connections between topics? dopamine decision making, which sensory input your brain values (perception), released after unexpected reward (unexpected connection between two topics (chunk linking) serotonin risk taking, depression, loneliness, low perceived social rank causes high risk taking prozac is a prescription to increase serotonin","title":"Neurochemistry"},{"location":"docs/digests/learning-how-to-learn/chunking-practice/#neurochemistry-how-to-control-it-for-higher-quality-learning","text":"basic shared controls: sleep nutrition exercise acetylcholine TODO ?? dopamine \"understand\" connections to existing knowledge to release dopamine Celebrate: reward yourself after learning - releases dopamine mental pat on the back vocalized verbal celebration \"Yeah!\" serotonin maintain a healthy social structure that fits your needs focus on mental wellness and mental health therapy, medicine, sleep, exercise, nutrition","title":"Neurochemistry: how to control it for \"higher quality learning\""},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/","text":"Learning How to Learn Learn the basics of how the brain works to learn more easily and be less frustrated. The course has 4 modules over 4 weeks. Information Source: coursera.org Speaker: Barbara Oakley, Terrence Sejnowski Basis: \"A Mind for Numbers\" by Barbara Oakley the book formed the basis for this MOOC audible audio or paper/ebook Course Videos You'll gain insight into how we learn by using a variety of different approaches, ranging from personal stories, to insights from cognitive psychology, to an examination of deep neuroscience. Course Activities In-video Quizzes Graded Quiz in each Module Peer-evaluated assignments (optional) Course Objectives By the end of the course, we expect you to be able to do the following: Explain the difference between focused and diffuse modes of thinking. Explain what a chunk is, and how and why you can and should enhance your chunking skills. Explain how working memory and long term memory differ from one another. Describe key techniques to help students learn most efficiently such as: the Pomodoro metaphor story visualization deliberate practice interleaving Describe actions that hinder students from learning most effectively, such as: procrastination over-learning Einstellung choking multi-tasking illusions of learning lack of sleep Describe the most important aspects of proper test preparation. Explain the importance of \u201cmindset\u201d in learning. Video 1: Introduction to the Focused and Diffuse modes There are 4 papers referenced at the end of this video. Two Different Modes of Thinking. The focused and diffuse modes of thinking are fundamentally different. Focused Mode of Thinking Focusing: concentrate intently on what you are trying to understand Diffuse Mode of Thinking Relaxed: related to a set of neural resting states Metaphor and analogy are very helpful when learning something new. Analogy: Pinball Game Think of the brain as an array of pinball bumpers. The focused mode has mamy, tightly packed bumpers. The diffuse mode has fewer, broadly spaced bumpers. The path of a ball between a number of bumpers is a familiar way of thinking. If you haven't thought a thought before, how will you know the path of the ball? How will you get the ball to the new thought pattern? As far as neural scientists know right now, you are either in focused or diffuse mode of thinking. You can see one side of the coin, or the other, but not both at the same time. Being in one mode limits your access to the other mode of thinking. Video 2: Introduction to the Course Structure Goal: Reframe how you think about learning. The course is especially useful for learning math and science. Experts from many professions who give tips about learning. You will see how you can fool yourself about whether you actually know the material. Discover new ways to hold your focus and embed the material more deeply and powerfully in your mind. Condense key ideas you are learning about so you can grasp them more easily. Master the simple approaches outlined here, including simple tips to help prevent procrastination, and you'll be able to learn more effectively and with less frustration. Video 3: sing the Focused and Diffuse Modes--Or, a Little Dali will do You Your mind needs to go back and forth between the two learning modes, that's what makes you learn effectively. Analogy: Lifting weights. You can't work out like a fiend the day before a weightlifting competition. Neural structure is like a muscle, gradually grow a neural scaffold to hang your thinking on. Learning something difficult takes time. Salvador Dali - the very definition of \"a wild and crazy guy\" Thomas Edison - One of the most brilliant inventors ever Dali's technique Relax in a chair and let his mind go free. Dangle a key in his hand just above the floor. And just as he drifted into his dreams, falling asleep he would drop the key, waking himself up. Just in time to gather the diffuse mode connections and ideas in his mind And back he would go into the focused mode , bringing with him the new connections he made in the diffuse mode Edison Technique According to legend... Relax in his chair, holding ball-bearings in his hand His mind would run free and noodle back in a relaxed way to what he would focus on The ball bearings drop and clatter to the ground - same as Dali He is awakened! Off he would go with his ideas in the diffuse mode , ready to build on them in the focused mode Week 1: What is Learning? Some Context Brain weighs 3 lbs. Consumes 10x more energy by weight than rest of body. Most complex device in the known universe. We are not consciously aware of how our brains work. Brains evolved to help us navigate complex environments. Most of heavy lifting is below consciousness. Surprised to find out that running , reaching , seeing , hearing are much more complex problems than we thought (than chess and math ) and still out of the reach of raw computer processing. Much of heavy lifting below the level of consciousness and we don't need to know how it's done to survive We are only aware of a tiny fraction of events in the mind There are areas of the brain that are active during focused states, and other areas of the brain that are active during resting states. Brain connectivity is dynamic and remains so even after it matures. New synapses form and others disappear. How do memories remain stable over so many years? Viewing a dendritic branch on a neuron. After learning and sleep the dendrite has new synapses. Synapses < 1 micron diameter; human hair is 20 microns diameter. Near the limit of light microscopy. You are not the same person you were after a nap or night sleep. Upgrade! Shakespeare: Macbeth laments insomnia, sleep knits up your experiences into the tapestry of your life story. Check out www.brainfacts.org . There are a million billion synapses in the brain. There are references at the end of the video. Introductory Quiz Notes There is a coursera mobile app... 10,000 Video: A procrastination Preview Trent on 10+10 Rules of Studying Recalling what you just read is a validation test . You can verify the work product of your reading. The work product is that you learned the material. Another major plug for flashcards and spaced repetition. Maybe I should just keep a paper system of mixed flashcards that I can rebase as neeed. Electronic ones are not working. Use outside resources early and often. Identify helpful people and don't waste your time on people that aren't successful at teaching you. Airplane Mode: Every text message pulls up the roots of your attempt to learn. Sleep is the foundation of learning and survival. 10 Rules of Studying These rules form a synthesis of some of the main ideas of the course--they are excerpted from the book A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014. Feel free to copy these rules and redistribute them, as long as you keep the original wording and this citation. 10 Rules of Good Studying Use recall. After you read a page, look away and recall the main ideas. Highlight very little, and never highlight anything you haven\u2019t put in your mind first by recalling. Try recalling main ideas when you are walking to class or in a different room from where you originally learned it. An ability to recall\u2014to generate the ideas from inside yourself\u2014is one of the key indicators of good learning. Test yourself. On everything. All the time. Flash cards are your friend. Chunk your problems. Chunking is understanding and practicing with a problem solution so that it can all come to mind in a flash. After you solve a problem, rehearse it. Make sure you can solve it cold\u2014every step. Pretend it\u2019s a song and learn to play it over and over again in your mind, so the information combines into one smooth chunk you can pull up whenever you want. Space your repetition. Spread out your learning in any subject a little every day, just like an athlete. Your brain is like a muscle\u2014it can handle only a limited amount of exercise on one subject at a time. Alternate different problem-solving techniques during your practice. Never practice too long at any one session using only one problem-solving technique\u2014after a while, you are just mimicking what you did on the previous problem. Mix it up and work on different types of problems. This teaches you both how and when to use a technique. (Books generally are not set up this way, so you\u2019ll need to do this on your own.) After every assignment and test, go over your errors, make sure you understand why you made them, and then rework your solutions. To study most effectively, handwrite (don\u2019t type) a problem on one side of a flash card and the solution on the other. (Handwriting builds stronger neural structures in memory than typing.) You might also photograph the card if you want to load it into a study app on your smartphone. Quiz yourself randomly on different types of problems. Another way to do this is to randomly flip through your book, pick out a problem, and see whether you can solve it cold. Take breaks. It is common to be unable to solve problems or figure out concepts in math or science the first time you encounter them. This is why a little study every day is much better than a lot of studying all at once. When you get frustrated with a math or science problem, take a break so that another part of your mind can take over and work in the background. Use explanatory questioning and simple analogies. Whenever you are struggling with a concept, think to yourself, How can I explain this so that a ten-year-old could understand it? Using an analogy really helps, like saying that the flow of electricity is like the flow of water. Don\u2019t just think your explanation\u2014say it out loud or put it in writing. The additional effort of speaking and writing allows you to more deeply encode (that is, convert into neural memory structures) what you are learning. Focus. Turn off all interrupting beeps and alarms on your phone and computer, and then turn on a timer for twenty-five minutes. Focus intently for those twenty-five minutes and try to work as diligently as you can. After the timer goes off, give yourself a small, fun reward. A few of these sessions in a day can really move your studies forward. Try to set up times and places where studying\u2014not glancing at your computer or phone\u2014is just something you naturally do. Eat your frogs first. Do the hardest thing earliest in the day, when you are fresh. Make a mental contrast. Imagine where you\u2019ve come from and contrast that with the dream of where your studies will take you. Post a picture or words in your workspace to remind you of your dream. Look at that when you find your motivation lagging. This work will pay off both for you and those you love! 10 Rules of Bad Studying Excerpted from A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014 Avoid these techniques\u2014they can waste your time even while they fool you into thinking you\u2019re learning! Passive rereading \u2014sitting passively and running your eyes back over a page. Unless you can prove that the material is moving into your brain by recalling the main ideas without looking at the page, rereading is a waste of time. Letting highlights overwhelm you. Highlighting your text can fool your mind into thinking you are putting something in your brain, when all you\u2019re really doing is moving your hand. A little highlighting here and there is okay\u2014sometimes it can be helpful in flagging important points. But if you are using highlighting as a memory tool, make sure that what you mark is also going into your brain. Merely glancing at a problem\u2019s solution and thinking you know how to do it. This is one of the worst errors students make while studying. You need to be able to solve a problem step-by-step, without looking at the solution. Waiting until the last minute to study. Would you cram at the last minute if you were practicing for a track meet? Your brain is like a muscle\u2014it can handle only a limited amount of exercise on one subject at a time. Repeatedly solving problems of the same type that you already know how to solve. If you just sit around solving similar problems during your practice, you\u2019re not actually preparing for a test\u2014it\u2019s like preparing for a big basketball game by just practicing your dribbling. Letting study sessions with friends turn into chat sessions. Checking your problem solving with friends, and quizzing one another on what you know, can make learning more enjoyable, expose flaws in your thinking, and deepen your learning. But if your joint study sessions turn to fun before the work is done, you\u2019re wasting your time and should find another study group. Neglecting to read the textbook before you start working problems. Would you dive into a pool before you knew how to swim? The textbook is your swimming instructor\u2014it guides you toward the answers. You will flounder and waste your time if you don\u2019t bother to read it. Before you begin to read, however, take a quick glance over the chapter or section to get a sense of what it\u2019s about. Not checking with your instructors or classmates to clear up points of confusion. Professors are used to lost students coming in for guidance\u2014it\u2019s our job to help you. The students we worry about are the ones who don\u2019t come in. Don\u2019t be one of those students. Thinking you can learn deeply when you are being constantly distracted. Every tiny pull toward an instant message or conversation means you have less brain power to devote to learning. Every tug of interrupted attention pulls out tiny neural roots before they can grow. Not getting enough sleep. Your brain pieces together problem-solving techniques when you sleep, and it also practices and repeats whatever you put in mind before you go to sleep. Prolonged fatigue allows toxins to build up in the brain that disrupt the neural connections you need to think quickly and well. If you don\u2019t get a good sleep before a test, NOTHING ELSE YOU HAVE DONE WILL MATTER.","title":"Old Reviseme Learning How To Learn Coursera"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#learning-how-to-learn","text":"Learn the basics of how the brain works to learn more easily and be less frustrated. The course has 4 modules over 4 weeks.","title":"Learning How to Learn"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#information","text":"Source: coursera.org Speaker: Barbara Oakley, Terrence Sejnowski Basis: \"A Mind for Numbers\" by Barbara Oakley the book formed the basis for this MOOC audible audio or paper/ebook","title":"Information"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#course-videos","text":"You'll gain insight into how we learn by using a variety of different approaches, ranging from personal stories, to insights from cognitive psychology, to an examination of deep neuroscience.","title":"Course Videos"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#course-activities","text":"In-video Quizzes Graded Quiz in each Module Peer-evaluated assignments (optional)","title":"Course Activities"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#course-objectives","text":"By the end of the course, we expect you to be able to do the following: Explain the difference between focused and diffuse modes of thinking. Explain what a chunk is, and how and why you can and should enhance your chunking skills. Explain how working memory and long term memory differ from one another. Describe key techniques to help students learn most efficiently such as: the Pomodoro metaphor story visualization deliberate practice interleaving Describe actions that hinder students from learning most effectively, such as: procrastination over-learning Einstellung choking multi-tasking illusions of learning lack of sleep Describe the most important aspects of proper test preparation. Explain the importance of \u201cmindset\u201d in learning.","title":"Course Objectives"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#video-1-introduction-to-the-focused-and-diffuse-modes","text":"There are 4 papers referenced at the end of this video. Two Different Modes of Thinking. The focused and diffuse modes of thinking are fundamentally different. Focused Mode of Thinking Focusing: concentrate intently on what you are trying to understand Diffuse Mode of Thinking Relaxed: related to a set of neural resting states Metaphor and analogy are very helpful when learning something new.","title":"Video 1: Introduction to the Focused and Diffuse modes"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#analogy-pinball-game","text":"Think of the brain as an array of pinball bumpers. The focused mode has mamy, tightly packed bumpers. The diffuse mode has fewer, broadly spaced bumpers. The path of a ball between a number of bumpers is a familiar way of thinking. If you haven't thought a thought before, how will you know the path of the ball? How will you get the ball to the new thought pattern? As far as neural scientists know right now, you are either in focused or diffuse mode of thinking. You can see one side of the coin, or the other, but not both at the same time. Being in one mode limits your access to the other mode of thinking.","title":"Analogy: Pinball Game"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#video-2-introduction-to-the-course-structure","text":"Goal: Reframe how you think about learning. The course is especially useful for learning math and science. Experts from many professions who give tips about learning. You will see how you can fool yourself about whether you actually know the material. Discover new ways to hold your focus and embed the material more deeply and powerfully in your mind. Condense key ideas you are learning about so you can grasp them more easily. Master the simple approaches outlined here, including simple tips to help prevent procrastination, and you'll be able to learn more effectively and with less frustration.","title":"Video 2: Introduction to the Course Structure"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#video-3-sing-the-focused-and-diffuse-modes-or-a-little-dali-will-do-you","text":"Your mind needs to go back and forth between the two learning modes, that's what makes you learn effectively. Analogy: Lifting weights. You can't work out like a fiend the day before a weightlifting competition. Neural structure is like a muscle, gradually grow a neural scaffold to hang your thinking on. Learning something difficult takes time. Salvador Dali - the very definition of \"a wild and crazy guy\" Thomas Edison - One of the most brilliant inventors ever","title":"Video 3: sing the Focused and Diffuse Modes--Or, a Little Dali will do You"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#dalis-technique","text":"Relax in a chair and let his mind go free. Dangle a key in his hand just above the floor. And just as he drifted into his dreams, falling asleep he would drop the key, waking himself up. Just in time to gather the diffuse mode connections and ideas in his mind And back he would go into the focused mode , bringing with him the new connections he made in the diffuse mode","title":"Dali's technique"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#edison-technique","text":"According to legend... Relax in his chair, holding ball-bearings in his hand His mind would run free and noodle back in a relaxed way to what he would focus on The ball bearings drop and clatter to the ground - same as Dali He is awakened! Off he would go with his ideas in the diffuse mode , ready to build on them in the focused mode","title":"Edison Technique"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#week-1-what-is-learning","text":"","title":"Week 1: What is Learning?"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#some-context","text":"Brain weighs 3 lbs. Consumes 10x more energy by weight than rest of body. Most complex device in the known universe. We are not consciously aware of how our brains work. Brains evolved to help us navigate complex environments. Most of heavy lifting is below consciousness. Surprised to find out that running , reaching , seeing , hearing are much more complex problems than we thought (than chess and math ) and still out of the reach of raw computer processing. Much of heavy lifting below the level of consciousness and we don't need to know how it's done to survive We are only aware of a tiny fraction of events in the mind There are areas of the brain that are active during focused states, and other areas of the brain that are active during resting states. Brain connectivity is dynamic and remains so even after it matures. New synapses form and others disappear. How do memories remain stable over so many years? Viewing a dendritic branch on a neuron. After learning and sleep the dendrite has new synapses. Synapses < 1 micron diameter; human hair is 20 microns diameter. Near the limit of light microscopy. You are not the same person you were after a nap or night sleep. Upgrade! Shakespeare: Macbeth laments insomnia, sleep knits up your experiences into the tapestry of your life story. Check out www.brainfacts.org . There are a million billion synapses in the brain. There are references at the end of the video.","title":"Some Context"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#introductory-quiz-notes","text":"There is a coursera mobile app... 10,000","title":"Introductory Quiz Notes"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#video-a-procrastination-preview","text":"","title":"Video: A procrastination Preview"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#trent-on-1010-rules-of-studying","text":"Recalling what you just read is a validation test . You can verify the work product of your reading. The work product is that you learned the material. Another major plug for flashcards and spaced repetition. Maybe I should just keep a paper system of mixed flashcards that I can rebase as neeed. Electronic ones are not working. Use outside resources early and often. Identify helpful people and don't waste your time on people that aren't successful at teaching you. Airplane Mode: Every text message pulls up the roots of your attempt to learn. Sleep is the foundation of learning and survival.","title":"Trent on 10+10 Rules of Studying"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#10-rules-of-studying","text":"These rules form a synthesis of some of the main ideas of the course--they are excerpted from the book A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014. Feel free to copy these rules and redistribute them, as long as you keep the original wording and this citation.","title":"10 Rules of Studying"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#10-rules-of-good-studying","text":"Use recall. After you read a page, look away and recall the main ideas. Highlight very little, and never highlight anything you haven\u2019t put in your mind first by recalling. Try recalling main ideas when you are walking to class or in a different room from where you originally learned it. An ability to recall\u2014to generate the ideas from inside yourself\u2014is one of the key indicators of good learning. Test yourself. On everything. All the time. Flash cards are your friend. Chunk your problems. Chunking is understanding and practicing with a problem solution so that it can all come to mind in a flash. After you solve a problem, rehearse it. Make sure you can solve it cold\u2014every step. Pretend it\u2019s a song and learn to play it over and over again in your mind, so the information combines into one smooth chunk you can pull up whenever you want. Space your repetition. Spread out your learning in any subject a little every day, just like an athlete. Your brain is like a muscle\u2014it can handle only a limited amount of exercise on one subject at a time. Alternate different problem-solving techniques during your practice. Never practice too long at any one session using only one problem-solving technique\u2014after a while, you are just mimicking what you did on the previous problem. Mix it up and work on different types of problems. This teaches you both how and when to use a technique. (Books generally are not set up this way, so you\u2019ll need to do this on your own.) After every assignment and test, go over your errors, make sure you understand why you made them, and then rework your solutions. To study most effectively, handwrite (don\u2019t type) a problem on one side of a flash card and the solution on the other. (Handwriting builds stronger neural structures in memory than typing.) You might also photograph the card if you want to load it into a study app on your smartphone. Quiz yourself randomly on different types of problems. Another way to do this is to randomly flip through your book, pick out a problem, and see whether you can solve it cold. Take breaks. It is common to be unable to solve problems or figure out concepts in math or science the first time you encounter them. This is why a little study every day is much better than a lot of studying all at once. When you get frustrated with a math or science problem, take a break so that another part of your mind can take over and work in the background. Use explanatory questioning and simple analogies. Whenever you are struggling with a concept, think to yourself, How can I explain this so that a ten-year-old could understand it? Using an analogy really helps, like saying that the flow of electricity is like the flow of water. Don\u2019t just think your explanation\u2014say it out loud or put it in writing. The additional effort of speaking and writing allows you to more deeply encode (that is, convert into neural memory structures) what you are learning. Focus. Turn off all interrupting beeps and alarms on your phone and computer, and then turn on a timer for twenty-five minutes. Focus intently for those twenty-five minutes and try to work as diligently as you can. After the timer goes off, give yourself a small, fun reward. A few of these sessions in a day can really move your studies forward. Try to set up times and places where studying\u2014not glancing at your computer or phone\u2014is just something you naturally do. Eat your frogs first. Do the hardest thing earliest in the day, when you are fresh. Make a mental contrast. Imagine where you\u2019ve come from and contrast that with the dream of where your studies will take you. Post a picture or words in your workspace to remind you of your dream. Look at that when you find your motivation lagging. This work will pay off both for you and those you love!","title":"10 Rules of Good Studying"},{"location":"docs/digests/learning-how-to-learn/old-reviseme-learning-how-to-learn-coursera/#10-rules-of-bad-studying","text":"Excerpted from A Mind for Numbers: How to Excel in Math and Science (Even if You Flunked Algebra), by Barbara Oakley, Penguin, July, 2014 Avoid these techniques\u2014they can waste your time even while they fool you into thinking you\u2019re learning! Passive rereading \u2014sitting passively and running your eyes back over a page. Unless you can prove that the material is moving into your brain by recalling the main ideas without looking at the page, rereading is a waste of time. Letting highlights overwhelm you. Highlighting your text can fool your mind into thinking you are putting something in your brain, when all you\u2019re really doing is moving your hand. A little highlighting here and there is okay\u2014sometimes it can be helpful in flagging important points. But if you are using highlighting as a memory tool, make sure that what you mark is also going into your brain. Merely glancing at a problem\u2019s solution and thinking you know how to do it. This is one of the worst errors students make while studying. You need to be able to solve a problem step-by-step, without looking at the solution. Waiting until the last minute to study. Would you cram at the last minute if you were practicing for a track meet? Your brain is like a muscle\u2014it can handle only a limited amount of exercise on one subject at a time. Repeatedly solving problems of the same type that you already know how to solve. If you just sit around solving similar problems during your practice, you\u2019re not actually preparing for a test\u2014it\u2019s like preparing for a big basketball game by just practicing your dribbling. Letting study sessions with friends turn into chat sessions. Checking your problem solving with friends, and quizzing one another on what you know, can make learning more enjoyable, expose flaws in your thinking, and deepen your learning. But if your joint study sessions turn to fun before the work is done, you\u2019re wasting your time and should find another study group. Neglecting to read the textbook before you start working problems. Would you dive into a pool before you knew how to swim? The textbook is your swimming instructor\u2014it guides you toward the answers. You will flounder and waste your time if you don\u2019t bother to read it. Before you begin to read, however, take a quick glance over the chapter or section to get a sense of what it\u2019s about. Not checking with your instructors or classmates to clear up points of confusion. Professors are used to lost students coming in for guidance\u2014it\u2019s our job to help you. The students we worry about are the ones who don\u2019t come in. Don\u2019t be one of those students. Thinking you can learn deeply when you are being constantly distracted. Every tiny pull toward an instant message or conversation means you have less brain power to devote to learning. Every tug of interrupted attention pulls out tiny neural roots before they can grow. Not getting enough sleep. Your brain pieces together problem-solving techniques when you sleep, and it also practices and repeats whatever you put in mind before you go to sleep. Prolonged fatigue allows toxins to build up in the brain that disrupt the neural connections you need to think quickly and well. If you don\u2019t get a good sleep before a test, NOTHING ELSE YOU HAVE DONE WILL MATTER.","title":"10 Rules of Bad Studying"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/","text":"Week 3: Procrastination & Memory This is very active time hacking. To do this, write out your plan thoughtfully. Strategies for managing procrastination without spending willpower Use mental tools and tricks to inspire and motivate yourself Procrastination These strategies are more important than you think Understand psychology of procrastination Good learning is a \"brick by brick\" activity Procrastination is the #1 blocker Why not use Willpower Hard to come by Uses lots of mental resources Don't need to waste on procrastination Why procrastination? Unhappy feeling lights up pain centers of the brain.. Avoidance makes you feel better temporarily Shares features with addiction Temporary relief from reality e.g. surfing the web telling yourself false stories: i don't have good spacial reasoning if i study too far ahead i will forget the material belief that procrastination is \"an innate characteristic\" Chunking is related to \"Habit\" Habit allows us to free our mind for other things Zombie mode so we can focus on other things Habits can be brief or long 4 Parts of a habit Neither helpful or harmful innately. Engineer the cue and reward. Update the belief on a plan. The routine will fall away The Cue Seeing a todo list item, time to do some tasks Seeing a text message from a friend, time to stop work The Routine picking up your phone to read the news after waking up zombie responses The Reward Find a way to reward yourself for good habits Find a way to remove the reward for bad habits Procrastination: Moving your mind's focus to something more pleasant The reward is quick and easy The Belief Habits have power because of your belief in them To change a habit, change your underlying belief Build a habit: focus on process To build a habit: Focus on process, not product product is \"outcome\" Easiest way is to do a pomodoro Mind can march mindlessly along Tips use a quiet space or noise cancelling headphones Usually you will have some negative feelings about beginning a learning session Non procrastinators use \"self talk\" to get past the negative feelings and get started: \"just get on with it\" Focus on process, not product: \"I'm going to spend 20 minutes working\" Product is an outcome: \"I'm going to finish my homework.\" Overwriting An Old Habit Change your reaction to a specific \"cue\". The only place to apply willpower is changing your reaction to a \"cue\". The Cue (4 kinds) Action: \"Recognize\" what launches you into zombie procrastination mode. Location Time How you feel Reactions The Routine Action: \"Engineer the routine\". This is the reaction point where you must actively focus on rewiring your old habit. Write a plan for the routine. It may not work perfectly. Adjust as necessary and celebrate the victories when your plan works. Put your cellphone in an unreachable place Use the pomodoro technique Reward Investigate what is happening. Why are you procrastinating? Can you substitute an emotional payoff? A feeling of pride or satisfaction? Can you win a small internal bet or contest? Indulge in a latte or read a favorite website Watch TV or read on the web without guilt for an evening Go out for a movie, buy a sweater or other frivolous purchase A reward can overcome previous cravings Your brain will rewire when it begins to \"EXPECT THE REWARD\" Tips Stopping at 5 PM gives a mini deadline that spurs work Stopping is a nice reward and ties into focus on process It takes a few days of drudgery before flow starts to take hold The better you get, the Belief When the going gets stressful you long to fall into old, comforatable habits Belief that your system works will get you through Develop a new community Virtually hang out with MOOC classmates Juggling Life & Learning This lecture is a bit scattered, break it out into a nice diagram or outline. Once a week, write a weekly list of key tasks On each day write a list you can reasonably work on or accomplish Otherwise they take up space on the edge of your working memory Action: Daily task list the evening before This helps your diffuse mode to grapple with tasks to figure out how to accomplish them Most items are process oriented Only a few items are product oriented because they are very well quantified Sidetracked by email switch to pomodoro, a process orientation 22 minute pomodoro I don't have to do the same thing every time Mixing up tasks keeps things fun and prevents unhealthy bouts of sitting Since I practice, I am good at gauging what I can do in a reasonable period Goal finish time for the day - 5 PM Planning quitting time is as important as planning working time Sometimes review your major work right before you sleep, diffuse mode working Maintaining healthy leisure time will improve your work No matter how busy your life is, you do need a bit of break Eat your frogs first in the morning Action: Most disliked (and important) task, at least 1 pomodoro right when you start working Summary: Procrastination Learning is brick by brick, so procrastination stops this from happening Tackling procrastination is incredibly important Keep a planner journal so you easily track when you reach your goals Observe what does and does not work Commit to certain routines and tasks every day Write your planned tasks out the night before so you can dwell on your goals Arrange work into a series of small challenges Make sure you and \"your zombies\" get lots of rewards Take a few minutes to savor feelings of happiness and triumph, brain temporarily changes modes Delay rewards until you finish a task Try surroundings with few procrastination cues Relax without guilt or worry Have backup plans for when you still procrastinate, no one is perfect Eat your frogs first every day","title":"Procrastination Important"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#week-3-procrastination-memory","text":"This is very active time hacking. To do this, write out your plan thoughtfully. Strategies for managing procrastination without spending willpower Use mental tools and tricks to inspire and motivate yourself","title":"Week 3: Procrastination & Memory"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#procrastination","text":"These strategies are more important than you think Understand psychology of procrastination Good learning is a \"brick by brick\" activity Procrastination is the #1 blocker","title":"Procrastination"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#why-not-use-willpower","text":"Hard to come by Uses lots of mental resources Don't need to waste on procrastination","title":"Why not use Willpower"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#why-procrastination","text":"Unhappy feeling lights up pain centers of the brain.. Avoidance makes you feel better temporarily Shares features with addiction Temporary relief from reality e.g. surfing the web telling yourself false stories: i don't have good spacial reasoning if i study too far ahead i will forget the material belief that procrastination is \"an innate characteristic\"","title":"Why procrastination?"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#chunking-is-related-to-habit","text":"Habit allows us to free our mind for other things Zombie mode so we can focus on other things Habits can be brief or long","title":"Chunking is related to \"Habit\""},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#4-parts-of-a-habit","text":"Neither helpful or harmful innately. Engineer the cue and reward. Update the belief on a plan. The routine will fall away The Cue Seeing a todo list item, time to do some tasks Seeing a text message from a friend, time to stop work The Routine picking up your phone to read the news after waking up zombie responses The Reward Find a way to reward yourself for good habits Find a way to remove the reward for bad habits Procrastination: Moving your mind's focus to something more pleasant The reward is quick and easy The Belief Habits have power because of your belief in them To change a habit, change your underlying belief","title":"4 Parts of a habit"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#build-a-habit-focus-on-process","text":"To build a habit: Focus on process, not product product is \"outcome\" Easiest way is to do a pomodoro Mind can march mindlessly along","title":"Build a habit: focus on process"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#tips","text":"use a quiet space or noise cancelling headphones Usually you will have some negative feelings about beginning a learning session Non procrastinators use \"self talk\" to get past the negative feelings and get started: \"just get on with it\" Focus on process, not product: \"I'm going to spend 20 minutes working\" Product is an outcome: \"I'm going to finish my homework.\"","title":"Tips"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#overwriting-an-old-habit","text":"Change your reaction to a specific \"cue\". The only place to apply willpower is changing your reaction to a \"cue\".","title":"Overwriting An Old Habit"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#the-cue-4-kinds","text":"Action: \"Recognize\" what launches you into zombie procrastination mode. Location Time How you feel Reactions","title":"The Cue (4 kinds)"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#the-routine","text":"Action: \"Engineer the routine\". This is the reaction point where you must actively focus on rewiring your old habit. Write a plan for the routine. It may not work perfectly. Adjust as necessary and celebrate the victories when your plan works. Put your cellphone in an unreachable place Use the pomodoro technique","title":"The Routine"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#reward","text":"Investigate what is happening. Why are you procrastinating? Can you substitute an emotional payoff? A feeling of pride or satisfaction? Can you win a small internal bet or contest? Indulge in a latte or read a favorite website Watch TV or read on the web without guilt for an evening Go out for a movie, buy a sweater or other frivolous purchase A reward can overcome previous cravings Your brain will rewire when it begins to \"EXPECT THE REWARD\" Tips Stopping at 5 PM gives a mini deadline that spurs work Stopping is a nice reward and ties into focus on process It takes a few days of drudgery before flow starts to take hold The better you get, the","title":"Reward"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#belief","text":"When the going gets stressful you long to fall into old, comforatable habits Belief that your system works will get you through Develop a new community Virtually hang out with MOOC classmates","title":"Belief"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#juggling-life-learning","text":"This lecture is a bit scattered, break it out into a nice diagram or outline. Once a week, write a weekly list of key tasks On each day write a list you can reasonably work on or accomplish Otherwise they take up space on the edge of your working memory Action: Daily task list the evening before This helps your diffuse mode to grapple with tasks to figure out how to accomplish them Most items are process oriented Only a few items are product oriented because they are very well quantified Sidetracked by email switch to pomodoro, a process orientation 22 minute pomodoro I don't have to do the same thing every time Mixing up tasks keeps things fun and prevents unhealthy bouts of sitting Since I practice, I am good at gauging what I can do in a reasonable period Goal finish time for the day - 5 PM Planning quitting time is as important as planning working time Sometimes review your major work right before you sleep, diffuse mode working Maintaining healthy leisure time will improve your work No matter how busy your life is, you do need a bit of break Eat your frogs first in the morning Action: Most disliked (and important) task, at least 1 pomodoro right when you start working","title":"Juggling Life & Learning"},{"location":"docs/digests/learning-how-to-learn/procrastination-IMPORTANT/#summary-procrastination","text":"Learning is brick by brick, so procrastination stops this from happening Tackling procrastination is incredibly important Keep a planner journal so you easily track when you reach your goals Observe what does and does not work Commit to certain routines and tasks every day Write your planned tasks out the night before so you can dwell on your goals Arrange work into a series of small challenges Make sure you and \"your zombies\" get lots of rewards Take a few minutes to savor feelings of happiness and triumph, brain temporarily changes modes Delay rewards until you finish a task Try surroundings with few procrastination cues Relax without guilt or worry Have backup plans for when you still procrastinate, no one is perfect Eat your frogs first every day","title":"Summary: Procrastination"},{"location":"docs/external/david_recommendations_keystorage/","text":"That sounds way better. I am hoping to set this up. Do you know where I can find a checklist or aggregation of modern guide about specific implementations? I know a lot of the tech involved but not the specific products. Mostly, I recommend channeling everything through GnuPG and running hardware for that. You'll have issues if you try to simultaneously use something like PKCS#11 for your SSH agent but GnuPG for other tasks. I document using GnuPG for SSH in my desktop config repo , including hardware. There are guides to creating an offline, software-managed root key and then signing the hardware tokens with that, but I prefer to just manage a set of hardware tokens instead. The hierarchical approaches only solve direct GnuPG usage, anyway, not SSH. My secrets include gpg keys, ssh keys, possibly a keepassx key depending on how I decide to do that. I need to check that. Right now I memorize more passwords than is probably advisable. You can centralize all three needs (and more) on GnuPG with a hardware token: GnuPG keys will obviously work as expected when backed with compatible hardware (instead of just software). My repo above explains basic setup from initializing hardware tokens to setting up new machines/installations to use existing tokens. You'll want to move your SSH client to using the agent provided by GnuPG. This will require you to upload SSH public keys generated from your GnuPG keys. My repo above explains the rest, including auto-starting the GnuPG agent. For passwords, I use Password Store . This supports encrypting/decrypting with GnuPG and synchronizing repositories over git, which you can do using git+ssh to leverage the previous work. For mobile password access, NFC-compatible GnuPG tokens (and USB if you're willing to use a dongle) can decrypt entries in hardware on Android devices. For Android's git+ssh access, I just use an SSH key resident on my phone. Hardware tokens aren't yet supported for SSH on Android, but Password Store doesn't depend on repository access for password security, anyway. For Google, GitHub, and Dropbox (and other U2F-supporting services), I use a YubiKey (which can also provide a combination of GnuPG hardware and NFC, depending on model). So, in short, I can nearly run my whole crypto stack in hardware with one YubiKey Neo or any U2F key plus a Sigilance card (my laptop has a smart card reader). The only thing I don't have working yet is backing my browser client certificates with a GnuPG agent.","title":"David Recommendations Keystorage"},{"location":"docs/external/sat-for-noobs/","text":"The SAT problem for noobs Originally posted at: https://raw.githubusercontent.com/crillab/gophersat/master/examples/sat-for-noobs.md This document gives an overview of the SAT problem, and how to use a SAT solver to solve a given problem. It is intended for users of such solvers. It does not describe strategies, algorithms or implementation of such solvers. The intended audience for this document are developpers, so it assumes the reader understands boolean logic. This document is work in progress. Expect it to be improved over time. What is the SAT problem? SAT is a shortcut for \"boolean satisfiability\". Imagine you have a boolean formula , i.e a formula containing boolean variables . For instance: (a and (b or not(c))) or (not(b) and c) In this formula, a , b and c can either be true or false. The SAT problem is the problem of finding an assignment for these variables so that the whole formula becomes true, if such an assignment exists. This assignment is called a model , and a formula can have zero, one or several models. In the above problem, a=false, b=true, c=false is not a model of the formula, because (false and (true or not(false))) or (not(true) and false) reduces to false . However, the assignment a=true, b=true, c=false is a model, because (true and (true or not(false))) or (not(true) and false) reduces to true . Now, the trivial problem a and not(a) has no model, because there is no way to make this formula true, no matter the value associated with a . This formula is said to be unsatisfiable (UNSAT for short). What is a SAT solver? A SAT solver is a piece of software that, when given a formula (more on the input syntax below), returns either one model, if at least one model exists, or the indication that the problem is unsatisfiable . Implementing such a piece of software is rather easy, but there's one little problem: the SAT problem is NP-complete, meaning all known algorithms to solve it take an exponential time (worse-case complexity is O(k^n) , with k > 1 ), and we're not even sure there is a way to make a non-exponential algorithm (this is the famous \"P = NP\" problem). So, the most trivial algorithm to solve the SAT problem (test all possible assignments for all variables, stop when one makes the formula true, return UNSAT once all assignments were unsuccessful), has a worse-case complexity of O(2^n) . That means there are, for instance, more than 1 billion assignments to test for a formula with 30 variables, and about 1.27 * 10^30 for a formula with 100 variables: the time to solve a very simple problem is unacceptable. But all hope is not lost. The first good news is that exponential does not necessarily mean 2^n . It means k^n , with k > 1 . Solving the SAT problem is a whole research field, and algorithms are more and more efficient, trying to bring k as close to 1 as possible. Because, for instance, although an algorithm with a worst-case complexity of O(1.01^n) is still exponential, there are only about 400 million operations to solve a problem with 2000 variables. The second good news is that practical, real-world, industrial problems are generally structured in such a way that worst-case complexity is just a theoretical limit. Those problems are usually easier to solve than theoretical ones. The third good news is that, according to the Cook-Levin theorem, any NP-complete problem can be translated in a SAT problem, meaning all the research effort in emproving the efficiency of SAT solvers also profits all other NP-complete problems. In other words, when you are facing an NP-complete problem, you can either try to develop a specific algorithm to solve it, use a dedicated piece of software (if such a software exists) or try to translate it to SAT and use a SAT solver. What is the input format of a SAT solver? How do I represent my problem? Conjunctive Normal Form To be solved by a SAT solver, a problem must be described in CNF , or Conjunctive Normal Form. The CNF is a conjunction of disjunctions. In other words, a CNF formula is a set of clauses , all of which must be true: F = C1 and C2 and C3 and ... and Cn A clause is a set of literals, of which one (at least) must be true: Ci = L1 or L2 or ... or Lm A literal is a variable, potentially negated. Any boolean formula can be translated to an equivalent CNF formula in polynomial time, although the process can sometimes be tricky. For instance, the formula (a and (b or not(c))) or (not(b) and c) is equivalent to the following CNF formula (x1 or x2) and (not(x1) or a) and (not(x1) or b or not(c)) and (not(x2) or not(b)) and (not(x2) or c) Note that a few more variables had to be introduced. DIMACS format the standard way of describing a CNF formula is through the DIMACS syntax. A DIMACS file consists in a one-line prolog, and the description of each clause on each following lines. The prolog starts with p cnf and is followed by the number of variables and the number of clauses: p cnf 5 5 Then, on each line, a clause is described. A clause is described as a list of integer values separated by spaces, and ending with th value 0. That means each variable must be translated as an integer value. Negation is represented by the minus sign. For instance, let's say a is 1, b is 2, c is 3, x1 is 4, x2 is 5. The clause not(x2) or c will be translated as -5 3 0 . The above formula will then be written as: p cnf 5 5 4 5 0 -4 1 0 -4 2 -3 0 -5 -2 0 -5 3 0 The SAT solver, when given an input, will then return either the string UNSATISFIABLE or the string SATISFIABLE with an assignment that makes the formula true. For instance, when fed the formula above, Gophersat will answer: SATISFIABLE -1 -2 3 -4 5 It means that, when both c and x2 are true, and all other variables are false, the whole formula becomes true. Since x1 and x2 were dummy variables we introduced to make our original formula a CNF, we can say that our original formula is true when a=false, b=false, c=true . Remember this is not necessarily the only model for this formula, but finding all models (or getting the total number of models) would take a longer time and is not always useful. Translating a general boolean formula to a CNF formula Formulas need to be in CNF to be used by a SAT solver. However, problems are usually not formulated this way. Translating general boolean formulas to CNF is thus required. This process can be automated, but for the moment Gophersat doesn't include such a translator. Here are a few guidelines to translate general formulas to CNF. Negation In a CNF formula, negation only applies to literals, not to subformulas. Using DeMorgan's laws, such a transformation is trivial: not(F1 or F2) (where F1 and F2 are subformulas) becomes not(F1) and not(F2) and not(F1 and F2) becomes not(F1) or not(F2) . Such transformations are then applied recursively, until only literals are negated. Implication (if... then) Implication is easily translated in CNF: a -> b is equivalent to not(a) or b . Equivalence (equality) The formula a <-> b is equivalent to (a -> b) and (b -> a) , and can thus be translated as the set of clauses (not(a) or b) and (not(b) or a) . Exclusive or The formula a xor b is equivalent to a <-> not(b) , so it can be written (a or b) and (not(a) or not(b)) . From disjunction of conjunctions to conjunctions of disjunctions In a CNF formula, literals are linked by or operators to form clauses, and clauses are linked by and operators. How do you deal with the opposite, i.e a subformula like (F1 and F2) or (F3 and F4) where F1 , F2 , F3 and F4 are subformulas? There are several ways, but the most efficient one requires the introduction of new variables: let's rewrite this formula as ( x1 <-> ( F1 and F2 )) and ( x2 <-> ( F3 and F4 )) and ( x1 or x2 ) According to the rules above, x1 <-> (F1 and F2) can be rewritten as (not(x1) or F1) and (not(x1) or F2) and (not(F1) or not(F2) or x1) So, the original formula can be written as the following set of clauses: not(x1) or F1 not(x1) or F2 x1 or not(F1) or not(F2) not(x2) or F3 not(x2) or F4 x2 or not(F3) or not(F4) x1 or x2 By applying this rule (and all rules above) recursively, you can translate any boolean formula in a CNF equivalent. Uniqueness Very often, one wants to specify that exactly one boolean variable among several must be true, the others being false. For instance, you may want to state that a device is in one of four states : s1, s2, s3 or s4. It can be written as this set of clauses : s1 or s2 or s3 or s4 not(s1) or not(s2) not(s1) or not(s3) not(s1) or not(s4) not(s2) or not(s3) not(s2) or not(s4) not(s3) or not(s4) The first clause states \"at least one state is true\". Then, for each pair of states, one clause states that at least one of these two states is false. Note that it can lead to the generation of a lot of clauses: there are n*(n-1)/2 pairs of variables. So, when n is big, a huge amount of clauses can be generated. There are other, more efficient encodings, but they are a little more complicated and won't be explained in this document. Examples In this section, you will find the translation of a few problems translated as a boolean formula, then as a CNF boolean formula, then as a DIMACS file format. Sudoku Let's say we want to solve a sudoku problem. Such a problem has a set of constraints: each spot has exactly one number from 1 to 9, on each line, each number appears exctaly once, on each column, each number appears exactly once, in each 3x3 box, each number appears exactly once, a few spots are already assigned numbers. We must translate this problem in a formalism using only boolean variables, i.e assertions that are either true or false. In this problem, the variables we will use will be: line-1-col-1-is-a-1 line-1-col-1-is-a-2 ... line-1-col-1-is-a-9 line-1-col-2-is-a-1 ... and so on. So, we will have 9*9*9=729 variables to represent this problem, each one indicating line-x-col-y-is-a-z , or, as a shortcut, x;y=z , so we will have 1;1=1 , 1;1=2 and so on. Now, we must represent all our contraints. Each spot has exactly one number For each spot, we must indicate that the associated value is unique: unique(1;1=1, 1;1=2, 1;1=3, 1;1=4, 1;1=5, 1;1=6, 1;1=7, 1;1=8, 1;1=9) and unique(1;2=1, 1;2=2, 1;2=3, 1;2=4, 1;2=5, 1;2=6, 1;2=7, 1;2=8, 1;2=9) and ... and unique(9;9=1, 9;9=2, 9;9=3, 9;9=4, 9;9=5, 9;9=6, 9;9=7, 9;9=8, 9;9=9) This can be translated as a CNF set of clauses (see transformation rules above): 1 ; 1 = 1 or 1 ; 1 = 2 or 1 ; 1 = 3 or 1 ; 1 = 4 or 1 ; 1 = 5 or 1 ; 1 = 6 or 1 ; 1 = 7 or 1 ; 1 = 8 or 1 ; 1 = 9 not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 2 ) not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 3 ) not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 4 ) ... not ( 1 ; 1 = 8 ) or not ( 1 ; 1 = 9 ) This will lead to the generation of 1 + (9*8)/2 = 37 clauses for each spot, i.e 9*9*37 = 2997 clauses for all spots. Each line, column, box contains each number Since there are 9 spots in a line and each number from 1 to 9 must appear once, stating that each number must appear at least once is enough. So, we will write: (1;1=1 or 1;2=1 or 1;3=1 or 1;4=1 or 1;5=1 or 1;6=1 or 1;7=1 or 1;8=1 or 1;9=1) and (2;1=1 or 2;2=1 or 2;3=1 or 2;4=1 or 2;5=1 or 2;6=1 or 2;7=1 or 2;8=1 or 2;9=1) and ... and (9;1=1 or 9;2=1 or 9;3=1 or 9;4=1 or 9;5=1 or 9;6=1 or 9;7=1 or 9;8=1 or 9;9=1) and (1;1=2 or 1;2=2 or 1;3=2 or 1;4=2 or 1;5=2 or 1;6=2 or 1;7=2 or 1;8=2 or 1;9=2) and ... This will lead to the generation of 9*9=81 clauses. The same reasoning can be applied for columns and boxes, leading to the generation of 81 clauses each time. Already assigned numbers Now this is easy, we just have to state that a few variables are known to be true. So, for the following problem: the following clauses will be added: 1 ; 1 = 5 1 ; 2 = 3 1 ; 5 = 7 2 ; 1 = 6 2 ; 4 = 1 2 ; 5 = 9 2 ; 6 = 5 .... This will lead to the generation of one clause per already assigned number, i.e 30 clauses for the example problem above. Putting it all together in a DIMACS file To generate the corresponding DIMACS file, we must indicate the total number of variables and clauses in the prolog line. There are 729 variables and 2997+81+81+81+30=3270 clauses, so the prolog will be p cnf 729 3270 Now, each variable must be associated with a numeric value, from 1 to 729. Let's say that x;y=z is translated as (x-1) * 81 + (y-1) * 9 + z . So, 1;1=1 will be 1 and 9;9=9 will be 729. The complete DIMACS file is available. When fed that problem, gophersat will answer SATISFIABLE -1 -2 -3 -4 5 -6 -7 -8 -9 -10 -11 12 -13 -14 -15 -16 -17 -18 -19 -20 -21 22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 33 -34 -35 -36 -37 -38 -39 -40 -41 -42 43 -44 -45 -46 -47 -48 -49 -50 -51 -52 53 -54 -55 -56 -57 -58 -59 -60 -61 -62 63 64 -65 -66 -67 -68 -69 -70 -71 -72 -73 74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 87 -88 -89 -90 -91 -92 -93 -94 -95 -96 97 -98 -99 -100 101 -102 -103 -104 -105 -106 -107 -108 109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 126 -127 -128 -129 -130 131 -132 -133 -134 -135 -136 -137 138 -139 -140 -141 -142 -143 -144 -145 -146 -147 148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 161 -162 163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 180 -181 -182 -183 -184 -185 -186 -187 188 -189 -190 -191 192 -193 -194 -195 -196 -197 -198 -199 -200 -201 202 -203 -204 -205 -206 -207 -208 209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 221 -222 -223 -224 -225 -226 -227 -228 -229 -230 231 -232 -233 -234 -235 -236 -237 -238 -239 -240 241 -242 -243 -244 -245 -246 -247 -248 -249 -250 251 -252 -253 -254 -255 -256 257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 270 -271 -272 -273 -274 -275 -276 277 -278 -279 -280 -281 -282 -283 -284 285 -286 -287 -288 289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 301 -302 -303 -304 -305 -306 -307 308 -309 -310 -311 -312 -313 -314 -315 -316 -317 318 -319 -320 -321 -322 -323 -324 -325 -326 -327 328 -329 -330 -331 -332 -333 -334 335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 359 -360 -361 -362 -363 -364 365 -366 -367 -368 -369 -370 -371 372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 396 397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 412 -413 -414 415 -416 -417 -418 -419 -420 -421 -422 -423 -424 -425 426 -427 -428 -429 -430 -431 -432 -433 -434 -435 -436 -437 -438 -439 -440 441 -442 443 -444 -445 -446 -447 -448 -449 -450 -451 -452 -453 454 -455 -456 -457 -458 -459 -460 -461 -462 -463 -464 -465 -466 467 -468 -469 -470 -471 -472 473 -474 -475 -476 -477 -478 -479 -480 -481 -482 483 -484 -485 -486 -487 -488 -489 -490 -491 -492 -493 -494 495 -496 -497 -498 -499 -500 501 -502 -503 -504 505 -506 -507 -508 -509 -510 -511 -512 -513 -514 -515 -516 -517 518 -519 -520 -521 -522 -523 -524 525 -526 -527 -528 -529 -530 -531 -532 -533 -534 -535 -536 -537 538 -539 -540 -541 542 -543 -544 -545 -546 -547 -548 -549 -550 -551 -552 -553 -554 -555 -556 557 -558 -559 -560 -561 562 -563 -564 -565 -566 -567 -568 569 -570 -571 -572 -573 -574 -575 -576 -577 -578 -579 -580 -581 -582 -583 584 -585 -586 -587 -588 -589 -590 -591 592 -593 -594 -595 -596 -597 598 -599 -600 -601 -602 -603 604 -605 -606 -607 -608 -609 -610 -611 -612 -613 -614 -615 -616 -617 -618 -619 -620 621 -622 -623 -624 -625 -626 627 -628 -629 -630 -631 -632 633 -634 -635 -636 -637 -638 -639 -640 -641 -642 -643 644 -645 -646 -647 -648 -649 -650 651 -652 -653 -654 -655 -656 -657 -658 -659 -660 661 -662 -663 -664 -665 -666 -667 -668 -669 -670 671 -672 -673 -674 -675 -676 677 -678 -679 -680 -681 -682 -683 -684 -685 -686 -687 -688 -689 -690 -691 692 -693 -694 -695 -696 -697 -698 699 -700 -701 -702 703 -704 -705 -706 -707 -708 -709 -710 -711 -712 -713 -714 -715 -716 -717 718 -719 -720 -721 -722 -723 -724 -725 -726 -727 -728 729 This answer must now be parsed: each positive value indicates the corresponding spot contains the corresponding value. For example, the value 661 is positive. And the variable 661 means 9;2=4 ; so, the value at line 9, column 2 is 4 . Representing a sudoku puzzle can seem tedious, but once it is done, the process can be easily automated and used for any other puzzle. Automated planning Let's say we have a small factory that should be running 24/7. Now, we have a few constraints: an employee should only work 8 hours at most in a given day, an employee should at most work 5 days per week, there must be at least one employee at any given moment, we only want to hire 4 employees. Now, to simplify things, we consider there are 3 working time slots per day: night(12AM - 7AM), morning(7AM - 2PM) and afternoon(2PM - 12AM). How could we generate a timetable for our employees? Variables Let's deal with variables first. There are 7*3=21 time slots and 4 employees, so we will have at least 21*4=84 variables, each variable meaning employee-x-works-on-day-y-timeslot-z , or, as a shortcut x=y;z . Now, that could be enough, but to simplify the writing of our formula, let's add a few variables, to indicate employee-x-works-on-day-y , with no time slot indicated, or, as a shortcut x=dy . There will be 4*7=28 such variables, i.e 112 total variables. Employees work only 8 hours a day This is akin to a unique constraint: given a set of variable, exactly one must be true. But, here, this is not an \"exactly one\" constraint, this is an \"at most one\" constraint: an employee does not necessarily work on a given day, but if he does, he only works during one time slot. So, for employee 1 on day 1, we will have the following set of clauses: not(1=1;1) or not(1=1;2) not(1=1;1) or not(1=1;3) not(1=1;2) or not(1=1;3) And we will do the same for the 7 days, for all 4 employees, leading to the generation of 3*7*4=84 clauses. At least one employee in each timeslot That's an easy one: for each time slot, we indicate that one of the 4 variables representing each employee for that time slot is true. So, for monday night (day 1, time slot 1), this will be: 1 = 1 ; 1 or 2 = 1 ; 1 or 3 = 1 ; 1 or 4 = 1 ; 1 Whether we have one, two, three or all four employees working, this clause will be true. We do the same for all 21 time slots, leading to the generation of 21 clauses. Employees work at most 5 days per week This one is a little trickier. No, we want our workers to have at most five working days, meaning that, for each set of 6 days, at least one must be a day off. For employee 1, this will lead to the generation of these clauses: not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) So, for all 4 employees, we will have 4*7=28 more clauses. Linking x=y;z variables with x=dy ones We must link both types of variables: if an employee works on day 1, that means he either works on day1-slot1, on day1-slot2 or on day1-slot3. For employee 1, that means: 1 = d1 <-> ( 1 = 1 ; 1 or 1 = 1 ; 2 or 1 = 1 ; 3 ) In CNF: not(1=1;1) or 1=d1 not(1=1;2) or 1=d1 not(1=1;3) or 1=d1 not(1=d1) or 1=1;1 or 1=1;2 or 1=1;3 For each day and each employee, we have to generate 4*7*4=112 clauses. Translation to DIMACS We need to associate each variable with an integer identifiant. Let's say x=y;z be associated with (x-1)*21 + (y-1)*3 + z . That leads to the generation of 84 variables. We also need a different identifier for each variable of the kind x=dy . We will associate them with the value 84 + (x-1)*7 + y . The DIMACS file is available for download. When we feed it to gophersat, it answers UNSATISFIABLE Oops! Looks like there is no way to solve our problem. Actually, we could have found that without a solver: there are 4 employees, and each employee works at most during 5 timeslots, meaning only 5*4=20 time slots with an employee at most. But there are 7*3=21 time slots to fill. We need to relax our constraints. Let's say we decide to hire a fifth employee. We rewrite our problem, as described in DIMACS file timetable5.cnf and ask gophersat his advice. The solver answers: SATISFIABLE -1 2 -3 -4 -5 -6 -7 -8 -9 -10 -11 12 13 -14 -15 16 -17 -18 -19 -20 21 -22 -23 -24 25 -26 -27 28 -29 -30 -31 32 -33 -34 -35 -36 -37 38 -39 40 -41 -42 43 -44 -45 -46 -47 48 -49 50 -51 -52 -53 -54 -55 56 -57 -58 -59 -60 -61 62 -63 -64 -65 66 -67 68 -69 -70 -71 72 73 -74 -75 -76 -77 78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 102 -103 -104 -105 106 -107 -108 109 110 111 112 -113 114 115 116 -117 118 119 120 121 122 -123 124 -125 126 127 128 129 130 131 -132 -133 -134 -135 -136 -137 -138 139 -140 Great! Now, we have to translate this answer, by checking what each positive value means. Here, the solver gave us the following timetable: 1 = 1 ; 2 1 = 4 ; 3 1 = 5 ; 1 1 = 6 ; 1 1 = 7 ; 3 2 = 2 ; 1 2 = 3 ; 1 2 = 4 ; 2 2 = 6 ; 2 2 = 7 ; 1 3 = 1 ; 1 3 = 2 ; 3 3 = 3 ; 2 3 = 5 ; 2 3 = 7 ; 2 4 = 1 ; 3 4 = 2 ; 2 4 = 3 ; 3 4 = 4 ; 1 4 = 5 ; 3 5 = 6 ; 3 Everything is okay now. All employees from 1 to 4 work only five days a week, and part-time employee 5 fills the last, unassigned slot.","title":"Sat For Noobs"},{"location":"docs/external/sat-for-noobs/#the-sat-problem-for-noobs","text":"Originally posted at: https://raw.githubusercontent.com/crillab/gophersat/master/examples/sat-for-noobs.md This document gives an overview of the SAT problem, and how to use a SAT solver to solve a given problem. It is intended for users of such solvers. It does not describe strategies, algorithms or implementation of such solvers. The intended audience for this document are developpers, so it assumes the reader understands boolean logic. This document is work in progress. Expect it to be improved over time.","title":"The SAT problem for noobs"},{"location":"docs/external/sat-for-noobs/#what-is-the-sat-problem","text":"SAT is a shortcut for \"boolean satisfiability\". Imagine you have a boolean formula , i.e a formula containing boolean variables . For instance: (a and (b or not(c))) or (not(b) and c) In this formula, a , b and c can either be true or false. The SAT problem is the problem of finding an assignment for these variables so that the whole formula becomes true, if such an assignment exists. This assignment is called a model , and a formula can have zero, one or several models. In the above problem, a=false, b=true, c=false is not a model of the formula, because (false and (true or not(false))) or (not(true) and false) reduces to false . However, the assignment a=true, b=true, c=false is a model, because (true and (true or not(false))) or (not(true) and false) reduces to true . Now, the trivial problem a and not(a) has no model, because there is no way to make this formula true, no matter the value associated with a . This formula is said to be unsatisfiable (UNSAT for short).","title":"What is the SAT problem?"},{"location":"docs/external/sat-for-noobs/#what-is-a-sat-solver","text":"A SAT solver is a piece of software that, when given a formula (more on the input syntax below), returns either one model, if at least one model exists, or the indication that the problem is unsatisfiable . Implementing such a piece of software is rather easy, but there's one little problem: the SAT problem is NP-complete, meaning all known algorithms to solve it take an exponential time (worse-case complexity is O(k^n) , with k > 1 ), and we're not even sure there is a way to make a non-exponential algorithm (this is the famous \"P = NP\" problem). So, the most trivial algorithm to solve the SAT problem (test all possible assignments for all variables, stop when one makes the formula true, return UNSAT once all assignments were unsuccessful), has a worse-case complexity of O(2^n) . That means there are, for instance, more than 1 billion assignments to test for a formula with 30 variables, and about 1.27 * 10^30 for a formula with 100 variables: the time to solve a very simple problem is unacceptable. But all hope is not lost. The first good news is that exponential does not necessarily mean 2^n . It means k^n , with k > 1 . Solving the SAT problem is a whole research field, and algorithms are more and more efficient, trying to bring k as close to 1 as possible. Because, for instance, although an algorithm with a worst-case complexity of O(1.01^n) is still exponential, there are only about 400 million operations to solve a problem with 2000 variables. The second good news is that practical, real-world, industrial problems are generally structured in such a way that worst-case complexity is just a theoretical limit. Those problems are usually easier to solve than theoretical ones. The third good news is that, according to the Cook-Levin theorem, any NP-complete problem can be translated in a SAT problem, meaning all the research effort in emproving the efficiency of SAT solvers also profits all other NP-complete problems. In other words, when you are facing an NP-complete problem, you can either try to develop a specific algorithm to solve it, use a dedicated piece of software (if such a software exists) or try to translate it to SAT and use a SAT solver.","title":"What is a SAT solver?"},{"location":"docs/external/sat-for-noobs/#what-is-the-input-format-of-a-sat-solver-how-do-i-represent-my-problem","text":"","title":"What is the input format of a SAT solver? How do I represent my problem?"},{"location":"docs/external/sat-for-noobs/#conjunctive-normal-form","text":"To be solved by a SAT solver, a problem must be described in CNF , or Conjunctive Normal Form. The CNF is a conjunction of disjunctions. In other words, a CNF formula is a set of clauses , all of which must be true: F = C1 and C2 and C3 and ... and Cn A clause is a set of literals, of which one (at least) must be true: Ci = L1 or L2 or ... or Lm A literal is a variable, potentially negated. Any boolean formula can be translated to an equivalent CNF formula in polynomial time, although the process can sometimes be tricky. For instance, the formula (a and (b or not(c))) or (not(b) and c) is equivalent to the following CNF formula (x1 or x2) and (not(x1) or a) and (not(x1) or b or not(c)) and (not(x2) or not(b)) and (not(x2) or c) Note that a few more variables had to be introduced.","title":"Conjunctive Normal Form"},{"location":"docs/external/sat-for-noobs/#dimacs-format","text":"the standard way of describing a CNF formula is through the DIMACS syntax. A DIMACS file consists in a one-line prolog, and the description of each clause on each following lines. The prolog starts with p cnf and is followed by the number of variables and the number of clauses: p cnf 5 5 Then, on each line, a clause is described. A clause is described as a list of integer values separated by spaces, and ending with th value 0. That means each variable must be translated as an integer value. Negation is represented by the minus sign. For instance, let's say a is 1, b is 2, c is 3, x1 is 4, x2 is 5. The clause not(x2) or c will be translated as -5 3 0 . The above formula will then be written as: p cnf 5 5 4 5 0 -4 1 0 -4 2 -3 0 -5 -2 0 -5 3 0 The SAT solver, when given an input, will then return either the string UNSATISFIABLE or the string SATISFIABLE with an assignment that makes the formula true. For instance, when fed the formula above, Gophersat will answer: SATISFIABLE -1 -2 3 -4 5 It means that, when both c and x2 are true, and all other variables are false, the whole formula becomes true. Since x1 and x2 were dummy variables we introduced to make our original formula a CNF, we can say that our original formula is true when a=false, b=false, c=true . Remember this is not necessarily the only model for this formula, but finding all models (or getting the total number of models) would take a longer time and is not always useful.","title":"DIMACS format"},{"location":"docs/external/sat-for-noobs/#translating-a-general-boolean-formula-to-a-cnf-formula","text":"Formulas need to be in CNF to be used by a SAT solver. However, problems are usually not formulated this way. Translating general boolean formulas to CNF is thus required. This process can be automated, but for the moment Gophersat doesn't include such a translator. Here are a few guidelines to translate general formulas to CNF.","title":"Translating a general boolean formula to a CNF formula"},{"location":"docs/external/sat-for-noobs/#negation","text":"In a CNF formula, negation only applies to literals, not to subformulas. Using DeMorgan's laws, such a transformation is trivial: not(F1 or F2) (where F1 and F2 are subformulas) becomes not(F1) and not(F2) and not(F1 and F2) becomes not(F1) or not(F2) . Such transformations are then applied recursively, until only literals are negated.","title":"Negation"},{"location":"docs/external/sat-for-noobs/#implication-if-then","text":"Implication is easily translated in CNF: a -> b is equivalent to not(a) or b .","title":"Implication (if... then)"},{"location":"docs/external/sat-for-noobs/#equivalence-equality","text":"The formula a <-> b is equivalent to (a -> b) and (b -> a) , and can thus be translated as the set of clauses (not(a) or b) and (not(b) or a) .","title":"Equivalence (equality)"},{"location":"docs/external/sat-for-noobs/#exclusive-or","text":"The formula a xor b is equivalent to a <-> not(b) , so it can be written (a or b) and (not(a) or not(b)) .","title":"Exclusive or"},{"location":"docs/external/sat-for-noobs/#from-disjunction-of-conjunctions-to-conjunctions-of-disjunctions","text":"In a CNF formula, literals are linked by or operators to form clauses, and clauses are linked by and operators. How do you deal with the opposite, i.e a subformula like (F1 and F2) or (F3 and F4) where F1 , F2 , F3 and F4 are subformulas? There are several ways, but the most efficient one requires the introduction of new variables: let's rewrite this formula as ( x1 <-> ( F1 and F2 )) and ( x2 <-> ( F3 and F4 )) and ( x1 or x2 ) According to the rules above, x1 <-> (F1 and F2) can be rewritten as (not(x1) or F1) and (not(x1) or F2) and (not(F1) or not(F2) or x1) So, the original formula can be written as the following set of clauses: not(x1) or F1 not(x1) or F2 x1 or not(F1) or not(F2) not(x2) or F3 not(x2) or F4 x2 or not(F3) or not(F4) x1 or x2 By applying this rule (and all rules above) recursively, you can translate any boolean formula in a CNF equivalent.","title":"From disjunction of conjunctions to conjunctions of disjunctions"},{"location":"docs/external/sat-for-noobs/#uniqueness","text":"Very often, one wants to specify that exactly one boolean variable among several must be true, the others being false. For instance, you may want to state that a device is in one of four states : s1, s2, s3 or s4. It can be written as this set of clauses : s1 or s2 or s3 or s4 not(s1) or not(s2) not(s1) or not(s3) not(s1) or not(s4) not(s2) or not(s3) not(s2) or not(s4) not(s3) or not(s4) The first clause states \"at least one state is true\". Then, for each pair of states, one clause states that at least one of these two states is false. Note that it can lead to the generation of a lot of clauses: there are n*(n-1)/2 pairs of variables. So, when n is big, a huge amount of clauses can be generated. There are other, more efficient encodings, but they are a little more complicated and won't be explained in this document.","title":"Uniqueness"},{"location":"docs/external/sat-for-noobs/#examples","text":"In this section, you will find the translation of a few problems translated as a boolean formula, then as a CNF boolean formula, then as a DIMACS file format.","title":"Examples"},{"location":"docs/external/sat-for-noobs/#sudoku","text":"Let's say we want to solve a sudoku problem. Such a problem has a set of constraints: each spot has exactly one number from 1 to 9, on each line, each number appears exctaly once, on each column, each number appears exactly once, in each 3x3 box, each number appears exactly once, a few spots are already assigned numbers. We must translate this problem in a formalism using only boolean variables, i.e assertions that are either true or false. In this problem, the variables we will use will be: line-1-col-1-is-a-1 line-1-col-1-is-a-2 ... line-1-col-1-is-a-9 line-1-col-2-is-a-1 ... and so on. So, we will have 9*9*9=729 variables to represent this problem, each one indicating line-x-col-y-is-a-z , or, as a shortcut, x;y=z , so we will have 1;1=1 , 1;1=2 and so on. Now, we must represent all our contraints.","title":"Sudoku"},{"location":"docs/external/sat-for-noobs/#each-spot-has-exactly-one-number","text":"For each spot, we must indicate that the associated value is unique: unique(1;1=1, 1;1=2, 1;1=3, 1;1=4, 1;1=5, 1;1=6, 1;1=7, 1;1=8, 1;1=9) and unique(1;2=1, 1;2=2, 1;2=3, 1;2=4, 1;2=5, 1;2=6, 1;2=7, 1;2=8, 1;2=9) and ... and unique(9;9=1, 9;9=2, 9;9=3, 9;9=4, 9;9=5, 9;9=6, 9;9=7, 9;9=8, 9;9=9) This can be translated as a CNF set of clauses (see transformation rules above): 1 ; 1 = 1 or 1 ; 1 = 2 or 1 ; 1 = 3 or 1 ; 1 = 4 or 1 ; 1 = 5 or 1 ; 1 = 6 or 1 ; 1 = 7 or 1 ; 1 = 8 or 1 ; 1 = 9 not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 2 ) not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 3 ) not ( 1 ; 1 = 1 ) or not ( 1 ; 1 = 4 ) ... not ( 1 ; 1 = 8 ) or not ( 1 ; 1 = 9 ) This will lead to the generation of 1 + (9*8)/2 = 37 clauses for each spot, i.e 9*9*37 = 2997 clauses for all spots.","title":"Each spot has exactly one number"},{"location":"docs/external/sat-for-noobs/#each-line-column-box-contains-each-number","text":"Since there are 9 spots in a line and each number from 1 to 9 must appear once, stating that each number must appear at least once is enough. So, we will write: (1;1=1 or 1;2=1 or 1;3=1 or 1;4=1 or 1;5=1 or 1;6=1 or 1;7=1 or 1;8=1 or 1;9=1) and (2;1=1 or 2;2=1 or 2;3=1 or 2;4=1 or 2;5=1 or 2;6=1 or 2;7=1 or 2;8=1 or 2;9=1) and ... and (9;1=1 or 9;2=1 or 9;3=1 or 9;4=1 or 9;5=1 or 9;6=1 or 9;7=1 or 9;8=1 or 9;9=1) and (1;1=2 or 1;2=2 or 1;3=2 or 1;4=2 or 1;5=2 or 1;6=2 or 1;7=2 or 1;8=2 or 1;9=2) and ... This will lead to the generation of 9*9=81 clauses. The same reasoning can be applied for columns and boxes, leading to the generation of 81 clauses each time.","title":"Each line, column, box contains each number"},{"location":"docs/external/sat-for-noobs/#already-assigned-numbers","text":"Now this is easy, we just have to state that a few variables are known to be true. So, for the following problem: the following clauses will be added: 1 ; 1 = 5 1 ; 2 = 3 1 ; 5 = 7 2 ; 1 = 6 2 ; 4 = 1 2 ; 5 = 9 2 ; 6 = 5 .... This will lead to the generation of one clause per already assigned number, i.e 30 clauses for the example problem above.","title":"Already assigned numbers"},{"location":"docs/external/sat-for-noobs/#putting-it-all-together-in-a-dimacs-file","text":"To generate the corresponding DIMACS file, we must indicate the total number of variables and clauses in the prolog line. There are 729 variables and 2997+81+81+81+30=3270 clauses, so the prolog will be p cnf 729 3270 Now, each variable must be associated with a numeric value, from 1 to 729. Let's say that x;y=z is translated as (x-1) * 81 + (y-1) * 9 + z . So, 1;1=1 will be 1 and 9;9=9 will be 729. The complete DIMACS file is available. When fed that problem, gophersat will answer SATISFIABLE -1 -2 -3 -4 5 -6 -7 -8 -9 -10 -11 12 -13 -14 -15 -16 -17 -18 -19 -20 -21 22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 33 -34 -35 -36 -37 -38 -39 -40 -41 -42 43 -44 -45 -46 -47 -48 -49 -50 -51 -52 53 -54 -55 -56 -57 -58 -59 -60 -61 -62 63 64 -65 -66 -67 -68 -69 -70 -71 -72 -73 74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 87 -88 -89 -90 -91 -92 -93 -94 -95 -96 97 -98 -99 -100 101 -102 -103 -104 -105 -106 -107 -108 109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 126 -127 -128 -129 -130 131 -132 -133 -134 -135 -136 -137 138 -139 -140 -141 -142 -143 -144 -145 -146 -147 148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 161 -162 163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 180 -181 -182 -183 -184 -185 -186 -187 188 -189 -190 -191 192 -193 -194 -195 -196 -197 -198 -199 -200 -201 202 -203 -204 -205 -206 -207 -208 209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 221 -222 -223 -224 -225 -226 -227 -228 -229 -230 231 -232 -233 -234 -235 -236 -237 -238 -239 -240 241 -242 -243 -244 -245 -246 -247 -248 -249 -250 251 -252 -253 -254 -255 -256 257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 270 -271 -272 -273 -274 -275 -276 277 -278 -279 -280 -281 -282 -283 -284 285 -286 -287 -288 289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 301 -302 -303 -304 -305 -306 -307 308 -309 -310 -311 -312 -313 -314 -315 -316 -317 318 -319 -320 -321 -322 -323 -324 -325 -326 -327 328 -329 -330 -331 -332 -333 -334 335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 359 -360 -361 -362 -363 -364 365 -366 -367 -368 -369 -370 -371 372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 396 397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 412 -413 -414 415 -416 -417 -418 -419 -420 -421 -422 -423 -424 -425 426 -427 -428 -429 -430 -431 -432 -433 -434 -435 -436 -437 -438 -439 -440 441 -442 443 -444 -445 -446 -447 -448 -449 -450 -451 -452 -453 454 -455 -456 -457 -458 -459 -460 -461 -462 -463 -464 -465 -466 467 -468 -469 -470 -471 -472 473 -474 -475 -476 -477 -478 -479 -480 -481 -482 483 -484 -485 -486 -487 -488 -489 -490 -491 -492 -493 -494 495 -496 -497 -498 -499 -500 501 -502 -503 -504 505 -506 -507 -508 -509 -510 -511 -512 -513 -514 -515 -516 -517 518 -519 -520 -521 -522 -523 -524 525 -526 -527 -528 -529 -530 -531 -532 -533 -534 -535 -536 -537 538 -539 -540 -541 542 -543 -544 -545 -546 -547 -548 -549 -550 -551 -552 -553 -554 -555 -556 557 -558 -559 -560 -561 562 -563 -564 -565 -566 -567 -568 569 -570 -571 -572 -573 -574 -575 -576 -577 -578 -579 -580 -581 -582 -583 584 -585 -586 -587 -588 -589 -590 -591 592 -593 -594 -595 -596 -597 598 -599 -600 -601 -602 -603 604 -605 -606 -607 -608 -609 -610 -611 -612 -613 -614 -615 -616 -617 -618 -619 -620 621 -622 -623 -624 -625 -626 627 -628 -629 -630 -631 -632 633 -634 -635 -636 -637 -638 -639 -640 -641 -642 -643 644 -645 -646 -647 -648 -649 -650 651 -652 -653 -654 -655 -656 -657 -658 -659 -660 661 -662 -663 -664 -665 -666 -667 -668 -669 -670 671 -672 -673 -674 -675 -676 677 -678 -679 -680 -681 -682 -683 -684 -685 -686 -687 -688 -689 -690 -691 692 -693 -694 -695 -696 -697 -698 699 -700 -701 -702 703 -704 -705 -706 -707 -708 -709 -710 -711 -712 -713 -714 -715 -716 -717 718 -719 -720 -721 -722 -723 -724 -725 -726 -727 -728 729 This answer must now be parsed: each positive value indicates the corresponding spot contains the corresponding value. For example, the value 661 is positive. And the variable 661 means 9;2=4 ; so, the value at line 9, column 2 is 4 . Representing a sudoku puzzle can seem tedious, but once it is done, the process can be easily automated and used for any other puzzle.","title":"Putting it all together in a DIMACS file"},{"location":"docs/external/sat-for-noobs/#automated-planning","text":"Let's say we have a small factory that should be running 24/7. Now, we have a few constraints: an employee should only work 8 hours at most in a given day, an employee should at most work 5 days per week, there must be at least one employee at any given moment, we only want to hire 4 employees. Now, to simplify things, we consider there are 3 working time slots per day: night(12AM - 7AM), morning(7AM - 2PM) and afternoon(2PM - 12AM). How could we generate a timetable for our employees?","title":"Automated planning"},{"location":"docs/external/sat-for-noobs/#variables","text":"Let's deal with variables first. There are 7*3=21 time slots and 4 employees, so we will have at least 21*4=84 variables, each variable meaning employee-x-works-on-day-y-timeslot-z , or, as a shortcut x=y;z . Now, that could be enough, but to simplify the writing of our formula, let's add a few variables, to indicate employee-x-works-on-day-y , with no time slot indicated, or, as a shortcut x=dy . There will be 4*7=28 such variables, i.e 112 total variables.","title":"Variables"},{"location":"docs/external/sat-for-noobs/#employees-work-only-8-hours-a-day","text":"This is akin to a unique constraint: given a set of variable, exactly one must be true. But, here, this is not an \"exactly one\" constraint, this is an \"at most one\" constraint: an employee does not necessarily work on a given day, but if he does, he only works during one time slot. So, for employee 1 on day 1, we will have the following set of clauses: not(1=1;1) or not(1=1;2) not(1=1;1) or not(1=1;3) not(1=1;2) or not(1=1;3) And we will do the same for the 7 days, for all 4 employees, leading to the generation of 3*7*4=84 clauses.","title":"Employees work only 8 hours a day"},{"location":"docs/external/sat-for-noobs/#at-least-one-employee-in-each-timeslot","text":"That's an easy one: for each time slot, we indicate that one of the 4 variables representing each employee for that time slot is true. So, for monday night (day 1, time slot 1), this will be: 1 = 1 ; 1 or 2 = 1 ; 1 or 3 = 1 ; 1 or 4 = 1 ; 1 Whether we have one, two, three or all four employees working, this clause will be true. We do the same for all 21 time slots, leading to the generation of 21 clauses.","title":"At least one employee in each timeslot"},{"location":"docs/external/sat-for-noobs/#employees-work-at-most-5-days-per-week","text":"This one is a little trickier. No, we want our workers to have at most five working days, meaning that, for each set of 6 days, at least one must be a day off. For employee 1, this will lead to the generation of these clauses: not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d4) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d3) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d2) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d1) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) not(1=d2) or not(1=d3) or not(1=d4) or not(1=d5) or not(1=d6) or not(1=d7) So, for all 4 employees, we will have 4*7=28 more clauses.","title":"Employees work at most 5 days per week"},{"location":"docs/external/sat-for-noobs/#linking-xyz-variables-with-xdy-ones","text":"We must link both types of variables: if an employee works on day 1, that means he either works on day1-slot1, on day1-slot2 or on day1-slot3. For employee 1, that means: 1 = d1 <-> ( 1 = 1 ; 1 or 1 = 1 ; 2 or 1 = 1 ; 3 ) In CNF: not(1=1;1) or 1=d1 not(1=1;2) or 1=d1 not(1=1;3) or 1=d1 not(1=d1) or 1=1;1 or 1=1;2 or 1=1;3 For each day and each employee, we have to generate 4*7*4=112 clauses.","title":"Linking x=y;z variables with x=dy ones"},{"location":"docs/external/sat-for-noobs/#translation-to-dimacs","text":"We need to associate each variable with an integer identifiant. Let's say x=y;z be associated with (x-1)*21 + (y-1)*3 + z . That leads to the generation of 84 variables. We also need a different identifier for each variable of the kind x=dy . We will associate them with the value 84 + (x-1)*7 + y . The DIMACS file is available for download. When we feed it to gophersat, it answers UNSATISFIABLE Oops! Looks like there is no way to solve our problem. Actually, we could have found that without a solver: there are 4 employees, and each employee works at most during 5 timeslots, meaning only 5*4=20 time slots with an employee at most. But there are 7*3=21 time slots to fill. We need to relax our constraints. Let's say we decide to hire a fifth employee. We rewrite our problem, as described in DIMACS file timetable5.cnf and ask gophersat his advice. The solver answers: SATISFIABLE -1 2 -3 -4 -5 -6 -7 -8 -9 -10 -11 12 13 -14 -15 16 -17 -18 -19 -20 21 -22 -23 -24 25 -26 -27 28 -29 -30 -31 32 -33 -34 -35 -36 -37 38 -39 40 -41 -42 43 -44 -45 -46 -47 48 -49 50 -51 -52 -53 -54 -55 56 -57 -58 -59 -60 -61 62 -63 -64 -65 66 -67 68 -69 -70 -71 72 73 -74 -75 -76 -77 78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 102 -103 -104 -105 106 -107 -108 109 110 111 112 -113 114 115 116 -117 118 119 120 121 122 -123 124 -125 126 127 128 129 130 131 -132 -133 -134 -135 -136 -137 -138 139 -140 Great! Now, we have to translate this answer, by checking what each positive value means. Here, the solver gave us the following timetable: 1 = 1 ; 2 1 = 4 ; 3 1 = 5 ; 1 1 = 6 ; 1 1 = 7 ; 3 2 = 2 ; 1 2 = 3 ; 1 2 = 4 ; 2 2 = 6 ; 2 2 = 7 ; 1 3 = 1 ; 1 3 = 2 ; 3 3 = 3 ; 2 3 = 5 ; 2 3 = 7 ; 2 4 = 1 ; 3 4 = 2 ; 2 4 = 3 ; 3 4 = 4 ; 1 4 = 5 ; 3 5 = 6 ; 3 Everything is okay now. All employees from 1 to 4 work only five days a week, and part-time employee 5 fills the last, unassigned slot.","title":"Translation to DIMACS"},{"location":"docs/external/ukraine_daily_news/","text":"Daily Status Updates (pro-ukranian but mostly objective) - https://twitter.com/DefMon3 - https://twitter.com/HeliosRunner Accurate Account of Vehicle Losses (only confirmed visual loses, both sides) - https://twitter.com/oryxspioenkop - Website: https://www.oryxspioenkop.com/ Analysis (pro-ukranian or neutral, mostly objective) - https://twitter.com/RALee85 - https://twitter.com/ChrisO_wiki (good military historian) - https://twitter.com/Tatarigami_UA (has some very awesome threads) - https://twitter.com/RealCynicalFox - https://twitter.com/Osinttechnical - https://twitter.com/KofmanMichael Translation of Russian Videos - https://twitter.com/wartranslated (pretty much any relevant videos) - https://twitter.com/JuliaDavisNews (mostly Russian Media) Analysis & Updates (very pro ukranian) - https://twitter.com/small10space - https://twitter.com/NOELreports - https://twitter.com/Deepstate_UA (Videos Mostly) - https://twitter.com/WarMonitor3 Official Sources: - https://twitter.com/StratCom_AFU (posts daily status reports) Russian Sources (all telegram) - https://t.me/notes_veterans - https://t.me/grey_zone - https://t.me/milinfolive - https://t.me/rybar","title":"Ukraine Daily News"},{"location":"docs/gpt4/cholesterol_plan/","text":"Here's the revised plan: # Strategy Confidence Specific Actions Main Evidence 1 Modify Diet High Reduce saturated and trans fats. Increase intake of omega-3 fats and dietary fiber. Sacks et al., 2015 2 Regular Exercise High 150 minutes/week of moderate-intensity aerobic exercise and strength training twice a week. Sarzynski et al., 2015 3 Weight Loss High Aim for a 5-10% reduction in body weight if overweight. Wing et al., 2011 4 Plant Sterols and Stanols High Consume foods fortified with plant sterols/stanols like certain margarines or dietary supplements. AbuMweis et al., 2008 5 Avoid Refined Carbohydrates and Sugars High Minimize intake of foods high in refined carbohydrates and sugars. Te Morenga et al., 2014 6 Monounsaturated Fats High Increase intake of foods rich in monounsaturated fats like avocados, nuts, and olives. Kris-Etherton et al., 2018 7 Soluble Fiber Supplements Moderate-High Incorporate soluble fiber supplements into your diet. Brown et al., 1999 8 Polyphenol-rich Foods Moderate Include foods like berries, green tea, and dark chocolate in your diet. Tresserra-Rimbau et al., 2014 9 Adequate Sleep Moderate Ensure 7-9 hours of quality sleep per night. Cappuccio et al., 2010 10 Probiotics Moderate Incorporate fermented foods or probiotic supplements into your diet. Khalesi et al., 2018 11 Time-Restricted Eating/Intermittent Fasting Moderate Limit the window during which you consume food each day or consider periodic fasting. Patterson et al., 2018 12 Stress Management Low-Moderate Incorporate mindfulness activities such as meditation or yoga into your daily routine. Steffen et al., 2017 13 Adequate Hydration Low Maintain regular water intake; guidelines suggest around 2 liters per day. Theoretical, lacks empirical support Confidence levels based on strength of scientific evidence: systematic reviews and meta-analyses of randomized controlled trials (highest), single randomized trials (high), cohort studies (moderate), case-control studies (low), and expert opinion (lowest). === Sure, here's a table summarizing the three supplemental components with recommended daily doses: # Supplement Daily Dose Primary Benefit Main Evidence 1 Psyllium Husk 5 grams (usually in 1 teaspoon) Soluble fiber for lowering LDL cholesterol Brown et al., 1999 2 Berries and Nuts (Whole Foods) Varied. For instance, a handful of nuts (1 oz.) and 1 cup of berries. Rich in polyphenols, fiber, and healthy fats Seeram et al., 2008; Bolling et al., 2010 3 NOW Foods Plant Sterols 1.5 to 2.4 grams Plant sterols/stanols for lowering LDL cholesterol AbuMweis et al., 2008 Ensure to follow the usage instructions on the supplement labels and consult with a healthcare professional before starting any new supplement regimen. Confidence: High, based on randomized trials indicating these substances can help in lowering LDL cholesterol.","title":"Cholesterol Plan"},{"location":"docs/gpt4/cpp_retro_gaming/","text":"I would like to contribute code to c++ open source retro gaming projects, what should I look into? MAME: Arcade machine emulator. RetroArch: Emulation frontend. Dolphin: GameCube/Wii emulator. PCSX2: PlayStation 2 emulator. ScummVM: Adventure games. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: Project topic, goals. - Maintenance: Recent updates, responsiveness. Confidence: 85% (well-known projects, active development, retro gaming focus). (0.7/8192/218) robbintt@gpt-4 27> What else? higan: Multi-system emulator. OpenEmu: Emulation frontend for macOS. DeSmuME: Nintendo DS emulator. PPSSPP: PlayStation Portable emulator. RPCS3: PlayStation 3 emulator. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: Project topic, goals. - Maintenance: Recent updates, responsiveness. Confidence: 80% (popular projects, platform variety, active development). (0.7/8192/332) robbintt@gpt-4 28> what else? Citra: Nintendo 3DS emulator. Cxbx-Reloaded: Xbox emulator. Nestopia: NES emulator. Snes9x: Super Nintendo emulator. VisualBoyAdvance-M: Game Boy Advance emulator. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: Project topic, goals. - Maintenance: Recent updates, responsiveness. Confidence: 75% (variety of consoles, known projects, activity may vary). robbintt@gpt-4 30> is this all c++ Apologies, not all projects are in C++. Here's a revised list of C++ projects: OpenRA: Red Alert, Tiberian Dawn, Dune 2000. OpenTTD: Transport Tycoon Deluxe. OpenMW: Morrowind. 0 A.D.: Real-time strategy game, 90s style. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: 90s game, C++ language. - Maintenance: Recent updates, responsiveness. Confidence: 75% (C++ language, 90s game style, activity may vary). robbintt@gpt-4 31> What else from the 2000s? C++ open-source projects from the 2000s or with 2000s-style gameplay: Rigs of Rods: Vehicle simulation. OpenXcom: X-COM: UFO Defense, X-COM: Terror from the Deep. VCMI: Heroes of Might and Magic III. Pioneer: Space trading and combat, inspired by Frontier: Elite II. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: 2000s game or style, C++ language. - Maintenance: Recent updates, responsiveness. Confidence: 70% (C++ language, 2000s game style, varying activity). (0.7/8192/908) robbintt@gpt-4 32> what else? Additional C++ open-source projects from the 2000s or with 2000s-style gameplay: Stendhal: Multiplayer online adventure game. The Battle for Wesnoth: Turn-based strategy game. Warzone 2100: Real-time strategy game. Spring Engine: Engine for real-time strategy games. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: 2000s game or style, C++ language. - Maintenance: Recent updates, responsiveness. Confidence: 65% (C++ language, 2000s game style, maintenance and activity may vary). (0.7/8192/1056) robbintt@gpt-4 33> what about modern open source c++ games Modern open-source C++ game projects: Godot Engine: Game engine for various genres. OGRE: 3D rendering engine. Urho3D: Cross-platform game engine. OpenRW: Open-source recreation of Grand Theft Auto III. Cataclysm: Dark Days Ahead: Post-apocalyptic roguelike. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: Modern game, C++ language. - Maintenance: Recent updates, responsiveness. Confidence: 70% (C++ language, modern game focus, varying activity). (0.7/8192/1200) robbintt@gpt-4 34> how about 20 more Additional modern open-source C++ game projects: Tesseract: First-person shooter engine. The Powder Toy: Physics sandbox game. Mindustry: Resource management, tower defense. Red Eclipse: First-person shooter. Veloren: Open-world RPG. OpenDungeons: Dungeon management game. ValyriaTear: 2D JRPG. Thrive: Evolution simulation game. Widelands: Real-time strategy game. Naev: Space trading and combat game. OpenClonk: Action, strategy, and skill game. 0k: Real-time strategy game. Voxelands: Sandbox game, Minecraft-like. UFO: Alien Invasion: Strategy game. Megaglest: Real-time strategy game. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: Modern game, C++ language. - Maintenance: Recent updates, responsiveness. Confidence: 60% (C++ language, modern game focus, activity and maintenance may vary). robbintt@gpt-4 35> which are most suitable to an experienced professional developer starting out in cpp who already read a tour of cpp Considering experience and familiarity with A Tour of C++, the following projects are suitable: Godot Engine: Versatile game engine, large community. OGRE: 3D rendering engine, established project. Urho3D: Cross-platform game engine, active development. Tesseract: First-person shooter engine, technical knowledge application. Spring Engine: Real-time strategy game engine, potential for algorithm implementation. Confidence Rubric: - Popularity: GitHub stars, active community. - Relevance: C++ language, project complexity, code quality. - Maintenance: Recent updates, responsiveness. Confidence: 75% (C++ focus, varying complexity, active communities). robbintt@gpt-4 40> list all 40 in a table with their maintenance and responsiveness and any other intersting columns for my use case Here is a table of the 40 open-source C++ roguelike or Diablo-like game projects with columns for maintenance, responsiveness, and project focus. # Project Maintenance Responsiveness Project Focus 1 DevilutionX Active High Diablo 1 reverse-engineered 2 Flare Active High Diablo-like action RPG 3 Cataclysm: Dark Days Ahead Active High Post-apocalyptic roguelike 4 Angband Active High Traditional dungeon-crawl roguelike 5 TomeNET Active Moderate Online multiplayer roguelike 6 KeeperRL Active High Dungeon management, roguelike 7 UnNetHack Active Moderate NetHack variant 8 Infra Arcana Active Moderate Lovecraftian horror roguelike 9 ADOM Active Moderate Classic roguelike 10 DCSS Active High Dungeon-crawl roguelike 11 LambdaHack Active Moderate Roguelike game engine 12 GearHead Active Moderate Mecha roguelike RPG 13 Freeablo Active Moderate Diablo 1 engine reimplementation 14 Rogue Survivor Revived Active Moderate Zombie apocalypse roguelike 15 RogueBox Adventures Active Moderate Roguelike sandbox 16 X@COM Active Moderate Turn-based strategy, roguelike 17 Empyrean Active Moderate Diablo-like action RPG 18 T-Engine4 Active Moderate Roguelike game engine 19 POWDER Inactive Low Classic roguelike 20 BrogueCE Active Moderate Dungeon-crawl roguelike 21 IvAN Active Moderate Violent roguelike 22 PosChengband Active Moderate Angband variant 23 Tales of Maj'Eyal Active High Fantasy RPG, roguelike elements 24 Slash'EM Extended Active Moderate NetHack variant 25 Dungeon Mercenary Inactive Low Dungeon-crawl roguelike 26 NPPAngband Active Moderate Angband variant 27 Sil-Q Active Moderate Angband variant, Tolkien lore 28 Deliantra Inactive Low Online RPG, roguelike elements 29 Armoured Commander II Active Moderate WWII tank roguelike 30 Zorbus Active Moderate Dungeon-crawl roguelike 31 Incursion Inactive Low D&D-inspired roguelike 32 The Veins of the Earth Inactive Low D&D-based roguelike 33 Steamband Inactive Low Angband variant, steampunk 34 Sil Inactive Low Angband variant, Tolkien's First Age 35 Crawl Light Inactive Low DCSS variant, simplified 36 Halls of Mist Inactive Low Angband variant, unique dungeons 37 S.C.O.U.R.G.E. Inactive Low Diablo-like action RPG 38 FAangband Inactive Low Angband variant, Tolkien's First Age 39 DaJAngband Inactive Low Angband variant, diverse gameplay 40 Demon Active Moderate Monster-catching roguelike Please note that maintenance and responsiveness are subject to change over time, and the table provides an overview at the time of writing. It is recommended to visit each project's repository to evaluate its current status. robbintt@gpt-4 45> let's take a step back, what categories of open source linux games should i look at to contribute c++ code to Here is a list of categories of open-source Linux games to consider contributing C++ code: Game Engines: Develop or improve game engines that support various game genres, e.g., Godot Engine, OGRE, Urho3D, Spring Engine. Emulators: Contribute to projects that emulate gaming consoles or arcade machines, e.g., MAME, Dolphin, PCSX2, RetroArch, Citra. Remakes/Recreations: Work on projects that recreate or enhance classic games from different eras, e.g., OpenRA, OpenTTD, OpenMW, CorsixTH, FreeCiv, DevilutionX. Roguelike/Diablo-like: Contribute to projects focused on roguelike or Diablo-like gameplay, e.g., Flare, Cataclysm: Dark Days Ahead, Angband, KeeperRL, TomeNET. Real-time Strategy: Work on projects in the real-time strategy genre, e.g., 0 A.D., Widelands, Warzone 2100, Megaglest. First-person Shooters: Contribute to projects focused on first-person shooter gameplay, e.g., Tesseract, Red Eclipse, DarkPlaces (Quake-related). Role-playing Games: Work on projects in the role-playing game genre, e.g., ValyriaTear, Cataclysm: Dark Days Ahead, OpenMW. Puzzle/Physics: Contribute to projects with puzzle or physics-based gameplay, e.g., The Powder Toy, Mindustry. Sandbox/Crafting: Work on projects focusing on sandbox or crafting elements, e.g., Voxelands, Minetest. Before contributing to a project, ensure it aligns with your interests and expertise. Visit the project repository, read the documentation, and familiarize yourself with the project's goals, guidelines, and community. robbintt@gpt-4 46> how is minetest doing Minetest is an open-source voxel game engine and game with Minecraft-inspired gameplay. The project is active and well-maintained. As of February 2022, the latest stable version is 5.4.1, released in June 2021. The project has an active community, with contributors continuing to work on new features, bug fixes, and improvements. Minetest has an official forum where users and contributors can discuss the game, development, mods, and other related topics. The project's GitHub repository has over 3,000 stars, and the development team is responsive to issues and pull requests. Overall, Minetest is in a healthy state, with ongoing development and an engaged community. If you are interested in contributing to a sandbox/voxel game, Minetest is a good choice. (0.7/8192/5159) robbintt@gpt-4 47> is it all c++ Minetest's core game engine is primarily written in C++. This includes the rendering engine, networking, and various game systems. However, it also uses the Lua programming language for modding and scripting, allowing users to create custom game modes, items, and functionality using Lua scripts. If you are looking to contribute to the core engine or game systems, your C++ skills will be applicable. If you are interested in creating mods or extending the game's functionality, you will need to work with Lua scripts.","title":"Cpp Retro Gaming"},{"location":"docs/gpt4/increasing-happiness-praxis/","text":"Praxis: Increasing Happiness Put simply, your reactions and emotions don't change your baseline happiness. The techniques in this document do. Explanation of \"Happiness Set Point\" AKA \"Hedonic Treadmill\" This section is not by GPT-4. Most of the document is. It's not really a more or less reliable narrator than me. From wikipedia: Hedonic Treadmill Note that \"happiness set point\" and \"hedonic treadmill\" are the same concept. Importantly, the \"happiness set point\" can easily be changed. Things that bring you immediate feelings, e.g. joy or sadness, do not change your overall happiness. Note that circumstances, e.g. \"life events\" can change your happiness, and need managed differently, although generally as humans our most important skills for these events are are coping with things we cannot control and controlling things we should. The hedonic treadmill, also known as hedonic adaptation, is the observed tendency of humans to quickly return to a relatively stable level of happiness despite major positive or negative events or life changes. Headey (2008) concluded that an internal locus of control (https://en.m.wikipedia.org/wiki/Locus_of_control) and having \"positive\" personality traits (notably low neuroticism (https://en.m.wikipedia.org/wiki/Neuroticism)) are the two most significant factors affecting one's subjective well-being. Headey also found that adopting \"non-zero sum\" goals, those which enrich one's relationships with others and with society as a whole (i.e. family-oriented and altruistic goals), increase the level of subjective well-being. Conversely, attaching importance to zero-sum life goals (career success, wealth, and social status) will have a small but nevertheless statistically significant negative impact on people's overall subjective well-being (even though the size of a household's disposable income (https://en.m.wikipedia.org/wiki/Disposable_income) does have a small, positive impact on subjective well-being). Duration of one's education seems to have no direct bearing on life satisfaction. Daily Happiness Checklist This checklist came from combining the suggestions from: - \"reducing neuroticism\" - \"increasing locus of control\" - \"improving your happiness set point\" Daily Happiness Checklist (Revised Order by Effectiveness) Sleep Hygiene (7-9 hours) Prioritize getting sufficient, quality sleep each night, as sleep is crucial for overall well-being and happiness. Maintain a consistent sleep schedule and establish a relaxing bedtime routine. Physical Activity (30 minutes) Engage in your preferred form of exercise (e.g., walking, jogging, yoga, or swimming) to boost mood and reduce stress. Cognitive Behavioral Therapy (CBT) (variable time) Use CBT techniques, such as challenging negative thoughts and restructuring cognitive distortions, to improve mood and overall well-being. Consider working with a therapist or using self-help resources. Morning Mindfulness Meditation (10-15 minutes) Find a quiet space and spend time focusing on your breath or a mantra to start your day with a calm mind. Social Connection (variable time) Reach out to friends or family members through a phone call, text, or in-person visit to maintain and strengthen relationships. Acts of Kindness (variable time) Perform small acts of kindness for others, such as helping a neighbor, complimenting someone, or volunteering. This can boost happiness by promoting positive emotions and fostering social connections. Time in Nature (15-30 minutes) Spend time outdoors in natural settings, such as a park, forest, or beach. Exposure to nature has been shown to reduce stress, improve mood, and increase well-being. Problem-Solving Practice (10-15 minutes) Identify a challenge you are currently facing, brainstorm possible solutions, and take a small step toward resolving the issue. Goal Review and Progress (5-10 minutes) Reflect on your long-term goals, review the short-term actionable steps you've outlined, and track your progress. Positive Affirmations (5 minutes) Recite affirmations that emphasize control over personal choices and behaviors, promoting self-confidence and an internal locus of control. Gratitude Journaling (10 minutes) Write down three things you are grateful for each day to cultivate a positive mindset and increase happiness. Laughter and Humor (variable time) Make time to watch a funny movie, read a humorous book, or share jokes with friends. Laughter can reduce stress, improve mood, and promote feelings of happiness. Deep Breathing Exercises (5-10 minutes) Practice deep breathing exercises throughout the day to help manage stress and maintain a sense of calm. Nurturing Hobbies (variable time) Engage in hobbies or activities that bring you joy and fulfillment, such as painting, playing a musical instrument, gardening, or cooking. Evening Mindfulness Meditation (10-15 minutes) Wind down with another session of mindfulness meditation, focusing on releasing any stress or tension from the day. Please note that the effectiveness of each activity may vary depending on individual preferences and experiences. The revised order provided above takes into consideration the importance of certain items, but you should still adjust the checklist according to your personal needs and priorities. Reducing your \"Neuroticism\" To reduce neuroticism: Cognitive-Behavioral Therapy (CBT): Alters thought patterns, reducing negative thinking associated with neuroticism. Mindfulness: Reduces anxiety, promotes self-acceptance. Physical Activity: Reduces stress, promotes mood stability. Develop Coping Skills: Strategies to manage stress help mitigate neurotic reactions. Increase Your \"Locus of Control\" Problem-Solving: Identify challenges, generate solutions, take action, reflect on the outcome. Affirmations: Positive self-statements that emphasize control over personal choices and behaviors. Goal Setting: Long-term vision with short-term actionable steps promotes a sense of control. Mindfulness: Practice staying present-focused rather than worrying about uncontrollable future events. Improving happiness set point involves psychological interventions Cognitive Behavioral Therapy (CBT): It focuses on changing thought patterns. Negative thoughts can drag down your happiness set point. Mindfulness Meditation: Regular practice can increase baseline happiness, as it helps reduce stress and promote relaxation. Regular Exercise: It can release chemicals called endorphins which can make you feel happier. Maintain Social Connections: Strong, positive relationships are essential for happiness. Practice Gratitude: Reflecting on positive experiences can boost happiness levels. Rubric: Evidence based (1-3 points), applicability (1-3 points), detail level (1-3 points). Confidence: CBT: Evidence (3/3), Applicability (2/3), Detail (2/3) Mindfulness: Evidence (3/3), Applicability (3/3), Detail (2/3) Exercise: Evidence (3/3), Applicability (3/3), Detail (2/3) Social Connections: Evidence (3/3), Applicability (3/3), Detail (2/3) Gratitude: Evidence (3/3), Applicability (2/3), Detail (2/3) Overall, I am fairly confident in these recommendations based on scientific literature. However, individual experiences can vary. Detailed Activities Solo CBT robbintt@gpt-4 12> Is CBT a solo activity CBT, or Cognitive Behavioral Therapy, is traditionally a form of psychotherapy conducted with a licensed therapist. In this setting, it is not a solo activity, as you work together with the therapist to identify and address negative thought patterns and cognitive distortions. However, there are also self-help resources and books available that teach CBT techniques that can be practiced individually. In this case, CBT can be considered a solo activity. Keep in mind that practicing CBT on your own may not be as effective as working with a trained professional, especially when addressing more severe mental health concerns. In summary, CBT can be both a solo activity (using self-help resources) and a collaborative activity (working with a therapist). The choice depends on individual needs, preferences, and the severity of the issues being addressed. (0.7/8192/5345) robbintt@gpt-4 13> What is the research around solo cbt Research on self-guided or solo Cognitive Behavioral Therapy (CBT) has shown promising results. Several studies have found that self-help CBT interventions can be effective for treating various mental health conditions, particularly mild to moderate anxiety and depression. A meta-analysis of 40 studies on self-help CBT interventions (Andersson & Cuijpers, 2009) showed that these interventions had a moderate effect size in reducing symptoms of anxiety and depression. Another meta-analysis of 15 studies (Cuijpers et al., 2009) examining self-help interventions for depression found a moderate effect size as well. It is important to note, however, that self-guided CBT may not be as effective as therapist-guided CBT for more severe mental health issues or complex cases. Additionally, self-help interventions may not provide the same level of support, personalization, and feedback as working with a trained professional. Despite these limitations, self-guided CBT can be a useful option for individuals who may not have access to a therapist, cannot afford therapy, or prefer to work independently. It can be an accessible starting point for those seeking to improve their mental well-being. References: Andersson, G., & Cuijpers, P. (2009). Internet-based and other computerized psychological treatments for adult depression: a meta-analysis. Cognitive Behaviour Therapy, 38(4), 196-205. https://pubmed.ncbi.nlm.nih.gov/20183695/ Cuijpers, P., Donker, T., van Straten, A., Li, J., & Andersson, G. (2009). Is guided self-help as effective as face-to-face psychotherapy for depression and anxiety disorders? A systematic review and meta-analysis of comparative outcome studies. Psychological Medicine, 40(12), 1943-1957. https://pubmed.ncbi.nlm.nih.gov/20406528/ Solo CBT: Overview from GPT-4 robbintt@gpt-4 15> ok, how do I do solo cbt To practice solo Cognitive Behavioral Therapy (CBT), follow these steps: Understand the basics of CBT: Familiarize yourself with the principles of CBT, which aims to identify and change negative thought patterns and cognitive distortions that contribute to emotional distress. Learn CBT techniques: Study various CBT techniques, such as thought records, cognitive restructuring, and behavioral activation. You can find these techniques in self-help books, online resources, or mobile apps designed for CBT practice. Identify your negative thoughts and cognitive distortions: Start by observing your thoughts, especially when you experience strong emotions. Recognize common cognitive distortions, such as all-or-nothing thinking, magnification, and personalization. Keep a thought journal: Record your thoughts, emotions, and situations that trigger negative thinking patterns. Note any cognitive distortions and their intensity. Challenge negative thoughts: Question the accuracy and validity of your negative thoughts. Analyze the evidence supporting and contradicting these thoughts and consider alternative explanations. Cognitive restructuring: Replace negative thoughts with more balanced and rational alternatives. Practice this by reframing your thoughts to be more objective and less emotionally charged. Set behavioral goals: Identify and set small, achievable goals that promote positive behaviors and experiences. These goals could include engaging in enjoyable activities, overcoming procrastination, or improving social connections. Monitor your progress: Regularly review your thought journal and progress towards your behavioral goals. Make adjustments as needed and celebrate your successes. Practice mindfulness: Incorporate mindfulness meditation or other mindfulness techniques into your daily routine to enhance self-awareness and emotional regulation. Seek support if needed: If you find solo CBT challenging or feel that your mental health concerns are too complex to address on your own, consider seeking professional guidance from a therapist or counselor. Remember that self-guided CBT may not be as effective as working with a trained professional, especially for more severe mental health concerns. However, it can be a helpful starting point for those seeking to improve their well-being and manage mild to moderate symptoms of anxiety or depression. Creating & Reciting Affirmations robbintt@gpt-4 16> How do I do the affirmations one? To practice positive affirmations, follow these steps: Identify areas for improvement: Reflect on aspects of your life where you'd like to boost self-confidence, build motivation, or change negative thought patterns. Examples could include self-worth, relationships, career, or personal growth. Create your affirmations: Write positive, present-tense statements that directly address the areas you want to improve. Make sure they are specific, concise, and self-affirming. For example, \"I am capable of achieving my goals,\" \"I deserve love and respect,\" or \"I handle challenges with resilience and confidence.\" Personalize your affirmations: Ensure that your affirmations resonate with you and feel genuine. Use language that reflects your values and beliefs. Make a list: Compile a list of your chosen affirmations. You can start with a few and gradually expand your list as you become more comfortable with the practice. Practice regularly: Set aside time each day to recite your affirmations. You can do this in the morning as part of your daily routine or throughout the day whenever you need a boost of confidence or positivity. Speak with conviction: Recite your affirmations out loud, with confidence and conviction. You can also say them silently or write them down if you prefer. Visualization: As you recite your affirmations, visualize yourself embodying the positive qualities and emotions they represent. This mental imagery can help reinforce the affirmations and create a stronger emotional connection. Repetition: Repeat your affirmations multiple times during each session to help solidify them in your mind. Be consistent and patient: Practice affirmations consistently over time to experience their full benefits. Change takes time, so be patient and trust the process. Monitor your progress: Periodically review your affirmations to ensure they still align with your goals and values. Update or modify them as needed to reflect your personal growth and development. Remember, the effectiveness of affirmations may vary for individuals, and it's essential to find an approach that works best for you. Consistency and repetition are key to reaping the benefits of positive affirmations. Example Affirmations Here's a list of example affirmations covering various aspects of life. Feel free to use these as inspiration or modify them to better suit your personal needs and preferences: Self-worth: \"I am worthy of love, success, and happiness.\" Confidence: \"I believe in my abilities and trust myself to handle any situation.\" Resilience: \"I am strong and adaptable, and I can overcome any challenges that come my way.\" Positive mindset: \"I choose to focus on the positive aspects of my life and embrace gratitude.\" Health and well-being: \"I am committed to taking care of my body and mind, and I prioritize my health every day.\" Relationships: \"I attract positive, supportive, and loving relationships into my life.\" Career success: \"I am capable of achieving my career goals and continue to grow professionally.\" Personal growth: \"I embrace new experiences and opportunities for growth and self-improvement.\" Financial abundance: \"I am financially secure and attract wealth and prosperity.\" Inner peace: \"I cultivate inner peace and balance through mindfulness and self-awareness.\" Remember, when using affirmations, it's important to tailor them to your unique needs, values, and beliefs. Personalize these examples or create your own affirmations that resonate with you and reflect your personal goals. Practicing Gratitude robbintt@gpt-4 19> how do i practice gratitude? Practicing gratitude involves cultivating a mindset of appreciation and thankfulness for the positive aspects of your life. Here are some ways to practice gratitude: Gratitude journal: Dedicate a notebook or journal specifically for gratitude. Each day, write down three things you're grateful for. They can be small, like a delicious meal, or more significant, like a supportive friend. Over time, this practice will help you focus more on the positive aspects of your life. Express gratitude to others: When someone helps or supports you, make a conscious effort to express your appreciation. This can be as simple as saying \"thank you\" or writing a heartfelt note or message. Gratitude meditation: Spend a few minutes each day in quiet reflection, focusing on the things you're grateful for. Visualize the people, experiences, and circumstances that bring you joy and contentment. Gratitude jar: Set up a jar in a visible location in your home and keep small slips of paper nearby. Whenever you feel grateful for something, write it down and place it in the jar. Over time, you'll accumulate a collection of positive memories and experiences. Share gratitude with others: During casual conversations or at the dinner table, take turns sharing something you're grateful for. This practice can help create a positive atmosphere and strengthen relationships. Mindful moments: Throughout the day, pause and take a moment to appreciate the present moment and your surroundings. This can help you cultivate gratitude for the small, everyday pleasures in life. Reflect on challenges: Consider how past challenges have helped you grow and learn. By finding the silver lining in difficult situations, you can develop a deeper sense of gratitude for your life experiences. Volunteer or help others: Giving back to your community or helping someone in need can foster a sense of gratitude for your own circumstances and the opportunity to make a difference in others' lives. Create gratitude reminders: Set up reminders in your phone, on sticky notes, or through a visual cue to prompt you to pause and reflect on something you're grateful for. Practice gratitude before bedtime: As you wind down for the night, spend a few moments reflecting on the positive aspects of your day. This can help shift your mindset and promote better sleep. Remember, practicing gratitude is a habit that takes time to develop. Be patient with yourself and try different methods to find what works best for you. Consistency is key to experiencing the benefits of gratitude practice. Mindfulness Meditation Q: how do I do mindfulness meditation? Mindfulness meditation is a practice that focuses on building awareness of the present moment and accepting it without judgment. Here's a step-by-step guide to help you get started with mindfulness meditation: Find a quiet space: Choose a location where you can sit or lie down comfortably without distractions or interruptions. Set a timer: Decide on the duration of your meditation session, especially if you're a beginner. You can start with 5-10 minutes and gradually increase the duration as you become more comfortable with the practice. Choose a comfortable position: Sit or lie down in a comfortable position, maintaining a relaxed but upright posture. You can sit cross-legged on the floor, on a cushion, or in a chair with your feet flat on the ground. Close your eyes: Gently close your eyes or, if you prefer, maintain a soft gaze a few feet in front of you. Focus on your breath: Pay attention to your natural breathing pattern. Observe the sensation of the air entering and leaving your nostrils or the rise and fall of your chest or abdomen. You don't need to change your breath, just be aware of it. Accept wandering thoughts: It's normal for your mind to wander during meditation. When you notice your thoughts drifting, gently acknowledge them and bring your focus back to your breath without judgment. This process of noticing and refocusing is a key part of mindfulness meditation. Use an anchor: If you find it difficult to focus on your breath, you can use an alternative anchor for your attention, such as a word, phrase, or mantra that you silently repeat to yourself. Expand your awareness: As you become more comfortable with the practice, you can expand your focus to include other sensations or experiences in the present moment, such as sounds, bodily sensations, or emotions. End your meditation: When your timer goes off or you feel ready to end your session, take a few moments to notice your surroundings and gradually bring your awareness back to the room. Gently open your eyes and take a few deep breaths before returning to your daily activities. Remember, mindfulness meditation is a skill that takes time and practice to develop. Be patient with yourself and try to maintain a non-judgmental attitude towards your thoughts and experiences. Q: Isn't there research about focusing on your breath? Yes, there is research on the benefits of focusing on your breath during mindfulness meditation and other relaxation practices. Focusing on your breath is a fundamental technique in mindfulness meditation that helps anchor your attention in the present moment and develop greater self-awareness. Research has shown that focusing on your breath during mindfulness meditation can lead to various positive outcomes, such as: Reduced stress: Mindfulness meditation, including breath-focused practices, has been shown to reduce stress by activating the body's relaxation response and decreasing the production of stress hormones. Improved emotional regulation: Focusing on your breath can help you develop greater awareness of your emotions and improve your ability to regulate them, leading to better emotional well-being. Enhanced attention and focus: Breath-focused meditation has been found to improve attention and focus by promoting mental clarity and reducing distractions. Reduced symptoms of anxiety and depression: Studies have shown that mindfulness meditation, including breath-focused techniques, can help alleviate symptoms of anxiety and depression by promoting a more balanced and positive mindset. Improved overall well-being: Regular practice of mindfulness meditation that includes breath focus can lead to an increased sense of well-being and life satisfaction. In summary, focusing on your breath during mindfulness meditation is a well-researched technique that has been shown to provide numerous psychological benefits, including stress reduction, improved emotional regulation, enhanced attention, and overall well-being.","title":"Increasing Happiness Praxis"},{"location":"docs/gpt4/increasing-happiness-praxis/#praxis-increasing-happiness","text":"Put simply, your reactions and emotions don't change your baseline happiness. The techniques in this document do.","title":"Praxis: Increasing Happiness"},{"location":"docs/gpt4/increasing-happiness-praxis/#explanation-of-happiness-set-point-aka-hedonic-treadmill","text":"This section is not by GPT-4. Most of the document is. It's not really a more or less reliable narrator than me. From wikipedia: Hedonic Treadmill Note that \"happiness set point\" and \"hedonic treadmill\" are the same concept. Importantly, the \"happiness set point\" can easily be changed. Things that bring you immediate feelings, e.g. joy or sadness, do not change your overall happiness. Note that circumstances, e.g. \"life events\" can change your happiness, and need managed differently, although generally as humans our most important skills for these events are are coping with things we cannot control and controlling things we should. The hedonic treadmill, also known as hedonic adaptation, is the observed tendency of humans to quickly return to a relatively stable level of happiness despite major positive or negative events or life changes. Headey (2008) concluded that an internal locus of control (https://en.m.wikipedia.org/wiki/Locus_of_control) and having \"positive\" personality traits (notably low neuroticism (https://en.m.wikipedia.org/wiki/Neuroticism)) are the two most significant factors affecting one's subjective well-being. Headey also found that adopting \"non-zero sum\" goals, those which enrich one's relationships with others and with society as a whole (i.e. family-oriented and altruistic goals), increase the level of subjective well-being. Conversely, attaching importance to zero-sum life goals (career success, wealth, and social status) will have a small but nevertheless statistically significant negative impact on people's overall subjective well-being (even though the size of a household's disposable income (https://en.m.wikipedia.org/wiki/Disposable_income) does have a small, positive impact on subjective well-being). Duration of one's education seems to have no direct bearing on life satisfaction.","title":"Explanation of \"Happiness Set Point\" AKA \"Hedonic Treadmill\""},{"location":"docs/gpt4/increasing-happiness-praxis/#daily-happiness-checklist","text":"This checklist came from combining the suggestions from: - \"reducing neuroticism\" - \"increasing locus of control\" - \"improving your happiness set point\" Daily Happiness Checklist (Revised Order by Effectiveness) Sleep Hygiene (7-9 hours) Prioritize getting sufficient, quality sleep each night, as sleep is crucial for overall well-being and happiness. Maintain a consistent sleep schedule and establish a relaxing bedtime routine. Physical Activity (30 minutes) Engage in your preferred form of exercise (e.g., walking, jogging, yoga, or swimming) to boost mood and reduce stress. Cognitive Behavioral Therapy (CBT) (variable time) Use CBT techniques, such as challenging negative thoughts and restructuring cognitive distortions, to improve mood and overall well-being. Consider working with a therapist or using self-help resources. Morning Mindfulness Meditation (10-15 minutes) Find a quiet space and spend time focusing on your breath or a mantra to start your day with a calm mind. Social Connection (variable time) Reach out to friends or family members through a phone call, text, or in-person visit to maintain and strengthen relationships. Acts of Kindness (variable time) Perform small acts of kindness for others, such as helping a neighbor, complimenting someone, or volunteering. This can boost happiness by promoting positive emotions and fostering social connections. Time in Nature (15-30 minutes) Spend time outdoors in natural settings, such as a park, forest, or beach. Exposure to nature has been shown to reduce stress, improve mood, and increase well-being. Problem-Solving Practice (10-15 minutes) Identify a challenge you are currently facing, brainstorm possible solutions, and take a small step toward resolving the issue. Goal Review and Progress (5-10 minutes) Reflect on your long-term goals, review the short-term actionable steps you've outlined, and track your progress. Positive Affirmations (5 minutes) Recite affirmations that emphasize control over personal choices and behaviors, promoting self-confidence and an internal locus of control. Gratitude Journaling (10 minutes) Write down three things you are grateful for each day to cultivate a positive mindset and increase happiness. Laughter and Humor (variable time) Make time to watch a funny movie, read a humorous book, or share jokes with friends. Laughter can reduce stress, improve mood, and promote feelings of happiness. Deep Breathing Exercises (5-10 minutes) Practice deep breathing exercises throughout the day to help manage stress and maintain a sense of calm. Nurturing Hobbies (variable time) Engage in hobbies or activities that bring you joy and fulfillment, such as painting, playing a musical instrument, gardening, or cooking. Evening Mindfulness Meditation (10-15 minutes) Wind down with another session of mindfulness meditation, focusing on releasing any stress or tension from the day. Please note that the effectiveness of each activity may vary depending on individual preferences and experiences. The revised order provided above takes into consideration the importance of certain items, but you should still adjust the checklist according to your personal needs and priorities.","title":"Daily Happiness Checklist"},{"location":"docs/gpt4/increasing-happiness-praxis/#reducing-your-neuroticism","text":"To reduce neuroticism: Cognitive-Behavioral Therapy (CBT): Alters thought patterns, reducing negative thinking associated with neuroticism. Mindfulness: Reduces anxiety, promotes self-acceptance. Physical Activity: Reduces stress, promotes mood stability. Develop Coping Skills: Strategies to manage stress help mitigate neurotic reactions.","title":"Reducing your \"Neuroticism\""},{"location":"docs/gpt4/increasing-happiness-praxis/#increase-your-locus-of-control","text":"Problem-Solving: Identify challenges, generate solutions, take action, reflect on the outcome. Affirmations: Positive self-statements that emphasize control over personal choices and behaviors. Goal Setting: Long-term vision with short-term actionable steps promotes a sense of control. Mindfulness: Practice staying present-focused rather than worrying about uncontrollable future events.","title":"Increase Your \"Locus of Control\""},{"location":"docs/gpt4/increasing-happiness-praxis/#improving-happiness-set-point-involves-psychological-interventions","text":"Cognitive Behavioral Therapy (CBT): It focuses on changing thought patterns. Negative thoughts can drag down your happiness set point. Mindfulness Meditation: Regular practice can increase baseline happiness, as it helps reduce stress and promote relaxation. Regular Exercise: It can release chemicals called endorphins which can make you feel happier. Maintain Social Connections: Strong, positive relationships are essential for happiness. Practice Gratitude: Reflecting on positive experiences can boost happiness levels. Rubric: Evidence based (1-3 points), applicability (1-3 points), detail level (1-3 points). Confidence: CBT: Evidence (3/3), Applicability (2/3), Detail (2/3) Mindfulness: Evidence (3/3), Applicability (3/3), Detail (2/3) Exercise: Evidence (3/3), Applicability (3/3), Detail (2/3) Social Connections: Evidence (3/3), Applicability (3/3), Detail (2/3) Gratitude: Evidence (3/3), Applicability (2/3), Detail (2/3) Overall, I am fairly confident in these recommendations based on scientific literature. However, individual experiences can vary.","title":"Improving happiness set point involves psychological interventions"},{"location":"docs/gpt4/increasing-happiness-praxis/#detailed-activities","text":"","title":"Detailed Activities"},{"location":"docs/gpt4/increasing-happiness-praxis/#solo-cbt","text":"robbintt@gpt-4 12> Is CBT a solo activity CBT, or Cognitive Behavioral Therapy, is traditionally a form of psychotherapy conducted with a licensed therapist. In this setting, it is not a solo activity, as you work together with the therapist to identify and address negative thought patterns and cognitive distortions. However, there are also self-help resources and books available that teach CBT techniques that can be practiced individually. In this case, CBT can be considered a solo activity. Keep in mind that practicing CBT on your own may not be as effective as working with a trained professional, especially when addressing more severe mental health concerns. In summary, CBT can be both a solo activity (using self-help resources) and a collaborative activity (working with a therapist). The choice depends on individual needs, preferences, and the severity of the issues being addressed. (0.7/8192/5345) robbintt@gpt-4 13> What is the research around solo cbt Research on self-guided or solo Cognitive Behavioral Therapy (CBT) has shown promising results. Several studies have found that self-help CBT interventions can be effective for treating various mental health conditions, particularly mild to moderate anxiety and depression. A meta-analysis of 40 studies on self-help CBT interventions (Andersson & Cuijpers, 2009) showed that these interventions had a moderate effect size in reducing symptoms of anxiety and depression. Another meta-analysis of 15 studies (Cuijpers et al., 2009) examining self-help interventions for depression found a moderate effect size as well. It is important to note, however, that self-guided CBT may not be as effective as therapist-guided CBT for more severe mental health issues or complex cases. Additionally, self-help interventions may not provide the same level of support, personalization, and feedback as working with a trained professional. Despite these limitations, self-guided CBT can be a useful option for individuals who may not have access to a therapist, cannot afford therapy, or prefer to work independently. It can be an accessible starting point for those seeking to improve their mental well-being. References: Andersson, G., & Cuijpers, P. (2009). Internet-based and other computerized psychological treatments for adult depression: a meta-analysis. Cognitive Behaviour Therapy, 38(4), 196-205. https://pubmed.ncbi.nlm.nih.gov/20183695/ Cuijpers, P., Donker, T., van Straten, A., Li, J., & Andersson, G. (2009). Is guided self-help as effective as face-to-face psychotherapy for depression and anxiety disorders? A systematic review and meta-analysis of comparative outcome studies. Psychological Medicine, 40(12), 1943-1957. https://pubmed.ncbi.nlm.nih.gov/20406528/","title":"Solo CBT"},{"location":"docs/gpt4/increasing-happiness-praxis/#solo-cbt-overview-from-gpt-4","text":"robbintt@gpt-4 15> ok, how do I do solo cbt To practice solo Cognitive Behavioral Therapy (CBT), follow these steps: Understand the basics of CBT: Familiarize yourself with the principles of CBT, which aims to identify and change negative thought patterns and cognitive distortions that contribute to emotional distress. Learn CBT techniques: Study various CBT techniques, such as thought records, cognitive restructuring, and behavioral activation. You can find these techniques in self-help books, online resources, or mobile apps designed for CBT practice. Identify your negative thoughts and cognitive distortions: Start by observing your thoughts, especially when you experience strong emotions. Recognize common cognitive distortions, such as all-or-nothing thinking, magnification, and personalization. Keep a thought journal: Record your thoughts, emotions, and situations that trigger negative thinking patterns. Note any cognitive distortions and their intensity. Challenge negative thoughts: Question the accuracy and validity of your negative thoughts. Analyze the evidence supporting and contradicting these thoughts and consider alternative explanations. Cognitive restructuring: Replace negative thoughts with more balanced and rational alternatives. Practice this by reframing your thoughts to be more objective and less emotionally charged. Set behavioral goals: Identify and set small, achievable goals that promote positive behaviors and experiences. These goals could include engaging in enjoyable activities, overcoming procrastination, or improving social connections. Monitor your progress: Regularly review your thought journal and progress towards your behavioral goals. Make adjustments as needed and celebrate your successes. Practice mindfulness: Incorporate mindfulness meditation or other mindfulness techniques into your daily routine to enhance self-awareness and emotional regulation. Seek support if needed: If you find solo CBT challenging or feel that your mental health concerns are too complex to address on your own, consider seeking professional guidance from a therapist or counselor. Remember that self-guided CBT may not be as effective as working with a trained professional, especially for more severe mental health concerns. However, it can be a helpful starting point for those seeking to improve their well-being and manage mild to moderate symptoms of anxiety or depression.","title":"Solo CBT: Overview from GPT-4"},{"location":"docs/gpt4/increasing-happiness-praxis/#creating-reciting-affirmations","text":"robbintt@gpt-4 16> How do I do the affirmations one? To practice positive affirmations, follow these steps: Identify areas for improvement: Reflect on aspects of your life where you'd like to boost self-confidence, build motivation, or change negative thought patterns. Examples could include self-worth, relationships, career, or personal growth. Create your affirmations: Write positive, present-tense statements that directly address the areas you want to improve. Make sure they are specific, concise, and self-affirming. For example, \"I am capable of achieving my goals,\" \"I deserve love and respect,\" or \"I handle challenges with resilience and confidence.\" Personalize your affirmations: Ensure that your affirmations resonate with you and feel genuine. Use language that reflects your values and beliefs. Make a list: Compile a list of your chosen affirmations. You can start with a few and gradually expand your list as you become more comfortable with the practice. Practice regularly: Set aside time each day to recite your affirmations. You can do this in the morning as part of your daily routine or throughout the day whenever you need a boost of confidence or positivity. Speak with conviction: Recite your affirmations out loud, with confidence and conviction. You can also say them silently or write them down if you prefer. Visualization: As you recite your affirmations, visualize yourself embodying the positive qualities and emotions they represent. This mental imagery can help reinforce the affirmations and create a stronger emotional connection. Repetition: Repeat your affirmations multiple times during each session to help solidify them in your mind. Be consistent and patient: Practice affirmations consistently over time to experience their full benefits. Change takes time, so be patient and trust the process. Monitor your progress: Periodically review your affirmations to ensure they still align with your goals and values. Update or modify them as needed to reflect your personal growth and development. Remember, the effectiveness of affirmations may vary for individuals, and it's essential to find an approach that works best for you. Consistency and repetition are key to reaping the benefits of positive affirmations.","title":"Creating & Reciting Affirmations"},{"location":"docs/gpt4/increasing-happiness-praxis/#example-affirmations","text":"Here's a list of example affirmations covering various aspects of life. Feel free to use these as inspiration or modify them to better suit your personal needs and preferences: Self-worth: \"I am worthy of love, success, and happiness.\" Confidence: \"I believe in my abilities and trust myself to handle any situation.\" Resilience: \"I am strong and adaptable, and I can overcome any challenges that come my way.\" Positive mindset: \"I choose to focus on the positive aspects of my life and embrace gratitude.\" Health and well-being: \"I am committed to taking care of my body and mind, and I prioritize my health every day.\" Relationships: \"I attract positive, supportive, and loving relationships into my life.\" Career success: \"I am capable of achieving my career goals and continue to grow professionally.\" Personal growth: \"I embrace new experiences and opportunities for growth and self-improvement.\" Financial abundance: \"I am financially secure and attract wealth and prosperity.\" Inner peace: \"I cultivate inner peace and balance through mindfulness and self-awareness.\" Remember, when using affirmations, it's important to tailor them to your unique needs, values, and beliefs. Personalize these examples or create your own affirmations that resonate with you and reflect your personal goals.","title":"Example Affirmations"},{"location":"docs/gpt4/increasing-happiness-praxis/#practicing-gratitude","text":"robbintt@gpt-4 19> how do i practice gratitude? Practicing gratitude involves cultivating a mindset of appreciation and thankfulness for the positive aspects of your life. Here are some ways to practice gratitude: Gratitude journal: Dedicate a notebook or journal specifically for gratitude. Each day, write down three things you're grateful for. They can be small, like a delicious meal, or more significant, like a supportive friend. Over time, this practice will help you focus more on the positive aspects of your life. Express gratitude to others: When someone helps or supports you, make a conscious effort to express your appreciation. This can be as simple as saying \"thank you\" or writing a heartfelt note or message. Gratitude meditation: Spend a few minutes each day in quiet reflection, focusing on the things you're grateful for. Visualize the people, experiences, and circumstances that bring you joy and contentment. Gratitude jar: Set up a jar in a visible location in your home and keep small slips of paper nearby. Whenever you feel grateful for something, write it down and place it in the jar. Over time, you'll accumulate a collection of positive memories and experiences. Share gratitude with others: During casual conversations or at the dinner table, take turns sharing something you're grateful for. This practice can help create a positive atmosphere and strengthen relationships. Mindful moments: Throughout the day, pause and take a moment to appreciate the present moment and your surroundings. This can help you cultivate gratitude for the small, everyday pleasures in life. Reflect on challenges: Consider how past challenges have helped you grow and learn. By finding the silver lining in difficult situations, you can develop a deeper sense of gratitude for your life experiences. Volunteer or help others: Giving back to your community or helping someone in need can foster a sense of gratitude for your own circumstances and the opportunity to make a difference in others' lives. Create gratitude reminders: Set up reminders in your phone, on sticky notes, or through a visual cue to prompt you to pause and reflect on something you're grateful for. Practice gratitude before bedtime: As you wind down for the night, spend a few moments reflecting on the positive aspects of your day. This can help shift your mindset and promote better sleep. Remember, practicing gratitude is a habit that takes time to develop. Be patient with yourself and try different methods to find what works best for you. Consistency is key to experiencing the benefits of gratitude practice.","title":"Practicing Gratitude"},{"location":"docs/gpt4/increasing-happiness-praxis/#mindfulness-meditation","text":"Q: how do I do mindfulness meditation? Mindfulness meditation is a practice that focuses on building awareness of the present moment and accepting it without judgment. Here's a step-by-step guide to help you get started with mindfulness meditation: Find a quiet space: Choose a location where you can sit or lie down comfortably without distractions or interruptions. Set a timer: Decide on the duration of your meditation session, especially if you're a beginner. You can start with 5-10 minutes and gradually increase the duration as you become more comfortable with the practice. Choose a comfortable position: Sit or lie down in a comfortable position, maintaining a relaxed but upright posture. You can sit cross-legged on the floor, on a cushion, or in a chair with your feet flat on the ground. Close your eyes: Gently close your eyes or, if you prefer, maintain a soft gaze a few feet in front of you. Focus on your breath: Pay attention to your natural breathing pattern. Observe the sensation of the air entering and leaving your nostrils or the rise and fall of your chest or abdomen. You don't need to change your breath, just be aware of it. Accept wandering thoughts: It's normal for your mind to wander during meditation. When you notice your thoughts drifting, gently acknowledge them and bring your focus back to your breath without judgment. This process of noticing and refocusing is a key part of mindfulness meditation. Use an anchor: If you find it difficult to focus on your breath, you can use an alternative anchor for your attention, such as a word, phrase, or mantra that you silently repeat to yourself. Expand your awareness: As you become more comfortable with the practice, you can expand your focus to include other sensations or experiences in the present moment, such as sounds, bodily sensations, or emotions. End your meditation: When your timer goes off or you feel ready to end your session, take a few moments to notice your surroundings and gradually bring your awareness back to the room. Gently open your eyes and take a few deep breaths before returning to your daily activities. Remember, mindfulness meditation is a skill that takes time and practice to develop. Be patient with yourself and try to maintain a non-judgmental attitude towards your thoughts and experiences. Q: Isn't there research about focusing on your breath? Yes, there is research on the benefits of focusing on your breath during mindfulness meditation and other relaxation practices. Focusing on your breath is a fundamental technique in mindfulness meditation that helps anchor your attention in the present moment and develop greater self-awareness. Research has shown that focusing on your breath during mindfulness meditation can lead to various positive outcomes, such as: Reduced stress: Mindfulness meditation, including breath-focused practices, has been shown to reduce stress by activating the body's relaxation response and decreasing the production of stress hormones. Improved emotional regulation: Focusing on your breath can help you develop greater awareness of your emotions and improve your ability to regulate them, leading to better emotional well-being. Enhanced attention and focus: Breath-focused meditation has been found to improve attention and focus by promoting mental clarity and reducing distractions. Reduced symptoms of anxiety and depression: Studies have shown that mindfulness meditation, including breath-focused techniques, can help alleviate symptoms of anxiety and depression by promoting a more balanced and positive mindset. Improved overall well-being: Regular practice of mindfulness meditation that includes breath focus can lead to an increased sense of well-being and life satisfaction. In summary, focusing on your breath during mindfulness meditation is a well-researched technique that has been shown to provide numerous psychological benefits, including stress reduction, improved emotional regulation, enhanced attention, and overall well-being.","title":"Mindfulness Meditation"},{"location":"docs/gpt4/learning-how-to-learn-summary/","text":"Learning How to Learn I would like to condense this to a format for chatgpt to provide information. Then I can directly ask for anki cards, outlines, and quizzes for specific chunks and other techniques. Key Takeaways Can you provide the key points of the book \"learning how to learn\" I'm sorry for any confusion, but as of my last training cut-off in September 2021, there is no book titled \"Learning How to Learn\". However, there is a popular online course with the same title offered by Coursera, taught by Dr. Barbara Oakley and Dr. Terrence Sejnowski. This course provides key insights into the learning process, based on scientific research. Here are some key takeaways from the course, which could also be presented as principles in a hypothetical \"Learning How to Learn\" book: Focused and Diffuse Modes of Thinking : Our brain operates in two modes. The focused mode involves a direct approach to solving problems using logical, sequential, analytical thought. The diffuse mode is more relaxed and is associated with \"big-picture\" thinking. Both modes are necessary for learning. Active Recall and Spaced Repetition : Repeatedly testing oneself and recalling information over spaced intervals are effective techniques for strengthening memory. This is often more effective than simply rereading or highlighting text. Chunking : This involves breaking down complex information into smaller, manageable chunks. Over time, these chunks can be linked together to understand and recall large amounts of information. Procrastination and Memory : The course discusses the science of procrastination and suggests methods to overcome it, such as the Pomodoro Technique (working for 25 minutes, then taking a five-minute break). It also delves into how sleep affects memory and why it's crucial for learning. Interleaving : This technique involves mixing different types of problems or learning materials in one study session. This contrasts with blocked practice (doing a lot of the same type of problem at once), and it's generally more effective for long-term learning. Metaphors and Analogies : These can help in understanding and remembering difficult concepts by linking new information to something you already know. Mindset : The course emphasizes the importance of a \"growth mindset\", the belief that intelligence and talent can be developed over time through effort, as opposed to a \"fixed mindset\", the belief that these qualities are inborn and unchangeable. This is just a summary, and the course goes into much more detail about the science behind these principles and how to apply them effectively. For a comprehensive understanding, I'd recommend either taking the course or reading a book that elaborates on these principles. Dr. Barbara Oakley also has a book called \"A Mind for Numbers: How to Excel at Math and Science (Even If You Flunked Algebra)\" which talks about similar concepts in the context of learning math and science. Chunking Can you provide a practical outline tot ry chunking and also an outline for interleaving? I am a programmer if that context helps. Absolutely, chunking and interleaving can be extremely beneficial techniques for learning programming. Here's how you can apply them: Chunking Chunking refers to the process of breaking down larger pieces of information into smaller, manageable \"chunks\". In the context of programming, these chunks could be individual skills, concepts, or sections of code. Identify a Topic or Task : Start by identifying what you need to learn. For example, if you are learning a new programming language or framework, the whole topic might seem overwhelming at first. Break It Down : Next, break this topic down into smaller, manageable parts or \"chunks\". These could be individual functions, classes, or methods in the language or framework you're trying to learn. Focus on One Chunk : Concentrate on learning one chunk at a time. For instance, if you're learning Python, you might start with basic syntax, then move on to data types, and then to control flow structures like loops and conditionals. Practice and Repeat : After you've understood one chunk, practice it. Write code using the function or feature you've just learned. Repeat this process until you feel comfortable with it. Link Chunks : Once you're comfortable with individual chunks, start linking them together. Write code that uses multiple functions or features that you've learned. This will help you understand how these chunks fit together to create a larger program. Interleaving Interleaving involves switching between different types of problems or learning materials in one study session. In programming, this could mean working on different types of coding tasks or switching between different coding languages or concepts. Identify Different Topics or Tasks : Just like with chunking, start by identifying what you need to learn. Then, find several different types of tasks or topics within this larger topic. Mix Your Practice : Instead of practicing one type of task or topic until you've mastered it (which is called \"blocked practice\"), mix up your practice. Work on one type of task for a while, then switch to a different type. Apply to Different Contexts : For instance, if you are learning web development, you could practice JavaScript for a while, then switch to CSS, and then to HTML. This will help you understand how these different languages work together to create a website. Use Different Resources : Use a mix of tutorials, documentation, and practical projects. This way, you are not only switching between different topics but also between different learning modalities. Revisit Previous Topics : Regularly revisit previously learned concepts and try to apply them to new problems. This helps strengthen your understanding and enhance recall. Remember that both chunking and interleaving should be combined with active recall (practicing retrieving information or performing a task) and spaced repetition (revisiting information after increasing intervals of time) for effective learning.","title":"Learning How To Learn Summary"},{"location":"docs/gpt4/learning-how-to-learn-summary/#learning-how-to-learn","text":"I would like to condense this to a format for chatgpt to provide information. Then I can directly ask for anki cards, outlines, and quizzes for specific chunks and other techniques.","title":"Learning How to Learn"},{"location":"docs/gpt4/learning-how-to-learn-summary/#key-takeaways","text":"Can you provide the key points of the book \"learning how to learn\" I'm sorry for any confusion, but as of my last training cut-off in September 2021, there is no book titled \"Learning How to Learn\". However, there is a popular online course with the same title offered by Coursera, taught by Dr. Barbara Oakley and Dr. Terrence Sejnowski. This course provides key insights into the learning process, based on scientific research. Here are some key takeaways from the course, which could also be presented as principles in a hypothetical \"Learning How to Learn\" book: Focused and Diffuse Modes of Thinking : Our brain operates in two modes. The focused mode involves a direct approach to solving problems using logical, sequential, analytical thought. The diffuse mode is more relaxed and is associated with \"big-picture\" thinking. Both modes are necessary for learning. Active Recall and Spaced Repetition : Repeatedly testing oneself and recalling information over spaced intervals are effective techniques for strengthening memory. This is often more effective than simply rereading or highlighting text. Chunking : This involves breaking down complex information into smaller, manageable chunks. Over time, these chunks can be linked together to understand and recall large amounts of information. Procrastination and Memory : The course discusses the science of procrastination and suggests methods to overcome it, such as the Pomodoro Technique (working for 25 minutes, then taking a five-minute break). It also delves into how sleep affects memory and why it's crucial for learning. Interleaving : This technique involves mixing different types of problems or learning materials in one study session. This contrasts with blocked practice (doing a lot of the same type of problem at once), and it's generally more effective for long-term learning. Metaphors and Analogies : These can help in understanding and remembering difficult concepts by linking new information to something you already know. Mindset : The course emphasizes the importance of a \"growth mindset\", the belief that intelligence and talent can be developed over time through effort, as opposed to a \"fixed mindset\", the belief that these qualities are inborn and unchangeable. This is just a summary, and the course goes into much more detail about the science behind these principles and how to apply them effectively. For a comprehensive understanding, I'd recommend either taking the course or reading a book that elaborates on these principles. Dr. Barbara Oakley also has a book called \"A Mind for Numbers: How to Excel at Math and Science (Even If You Flunked Algebra)\" which talks about similar concepts in the context of learning math and science.","title":"Key Takeaways"},{"location":"docs/gpt4/learning-how-to-learn-summary/#chunking","text":"Can you provide a practical outline tot ry chunking and also an outline for interleaving? I am a programmer if that context helps. Absolutely, chunking and interleaving can be extremely beneficial techniques for learning programming. Here's how you can apply them: Chunking Chunking refers to the process of breaking down larger pieces of information into smaller, manageable \"chunks\". In the context of programming, these chunks could be individual skills, concepts, or sections of code. Identify a Topic or Task : Start by identifying what you need to learn. For example, if you are learning a new programming language or framework, the whole topic might seem overwhelming at first. Break It Down : Next, break this topic down into smaller, manageable parts or \"chunks\". These could be individual functions, classes, or methods in the language or framework you're trying to learn. Focus on One Chunk : Concentrate on learning one chunk at a time. For instance, if you're learning Python, you might start with basic syntax, then move on to data types, and then to control flow structures like loops and conditionals. Practice and Repeat : After you've understood one chunk, practice it. Write code using the function or feature you've just learned. Repeat this process until you feel comfortable with it. Link Chunks : Once you're comfortable with individual chunks, start linking them together. Write code that uses multiple functions or features that you've learned. This will help you understand how these chunks fit together to create a larger program. Interleaving Interleaving involves switching between different types of problems or learning materials in one study session. In programming, this could mean working on different types of coding tasks or switching between different coding languages or concepts. Identify Different Topics or Tasks : Just like with chunking, start by identifying what you need to learn. Then, find several different types of tasks or topics within this larger topic. Mix Your Practice : Instead of practicing one type of task or topic until you've mastered it (which is called \"blocked practice\"), mix up your practice. Work on one type of task for a while, then switch to a different type. Apply to Different Contexts : For instance, if you are learning web development, you could practice JavaScript for a while, then switch to CSS, and then to HTML. This will help you understand how these different languages work together to create a website. Use Different Resources : Use a mix of tutorials, documentation, and practical projects. This way, you are not only switching between different topics but also between different learning modalities. Revisit Previous Topics : Regularly revisit previously learned concepts and try to apply them to new problems. This helps strengthen your understanding and enhance recall. Remember that both chunking and interleaving should be combined with active recall (practicing retrieving information or performing a task) and spaced repetition (revisiting information after increasing intervals of time) for effective learning.","title":"Chunking"},{"location":"docs/gpt4/skin_health_drives_all_health/","text":"Skin Health Drives All Health Prolonged exposure to UV radiation, including UVA and UVB rays, can cause systemic inflammation, leading to age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's. UV damage drives 80% of skin health reduction, not aging. This is not referring to skin visual condition (wrinkling), which apparently had no difference, at least in UV vs control group. The appearance of the skin can also serve as a predictive marker for various health conditions, emphasizing the importance of proper skin care and sun protection as integral parts of overall physical well-being. Source Article https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health archive: https://archive.is/2023.08.24-114321/https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health hacker news discussion: https://news.ycombinator.com/item?id=37248882 Especially see humectants and occlusives (moisturizers vs moisture trappers on the skin), you need BOTH GPT-4 executive summary The risks associated with neglecting skin health extend beyond mere cosmetic concerns and are linked to serious systemic health issues. Prolonged exposure to UV radiation, particularly UVA and UVB rays, can cause damage to the skin, leading to systemic inflammation. This inflammation is not confined to the skin but affects other organs, including the heart and brain. The concept of \"inflammaging\" highlights how chronic inflammation, often stemming from skin damage, can be a significant risk factor for age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's. Furthermore, the appearance of the skin can be an early indicator of underlying health conditions. Research, such as the Baltimore Longitudinal Study, has found correlations between skin appearance and inner health, making skin a potential predictive marker for various diseases. The failure to protect and maintain skin health through proper care and sun protection can exacerbate these risks, making the skin not just a reflection of our lifestyle but an active participant in our overall well-being. The connection between skin health and systemic health underscores the importance of a comprehensive approach to skincare, recognizing its vital role in overall physical wellness. GPT-4 Checklists Daily Runbook Checklist: Morning : Cleanse, moisturize, apply suncream (SPF15 or higher), wear SPF clothing. Afternoon : Reapply suncream if exposed to sun, stay hydrated. Evening : Cleanse, apply nourishing moisturizer. Special Considerations : Use sunglasses, wide-brimmed hat, seek shade, use sun umbrella if outdoors. Best Practices Checklist: Understand Skin : Know your skin type and needs. UV Protection : Use suncream with UVA/UVB protection. Wear Protection : Utilize protective clothing and accessories. Moisturize : Apply moisturizer regularly. Avoid Sun Overexposure : Limit sun exposure during peak hours. Monitor Skin : Regularly check for changes and consult professionals if needed. Holistic Approach : Recognize skin's role in overall well-being. Stay Informed : Keep updated on skin health research and consult healthcare professionals. These checklists encapsulate the essential daily routines and best practices for maintaining skin health, reflecting the information provided in the article. Experimental Ideas DIY 20% ascorbic acid for the face (vitamin c): https://news.ycombinator.com/item?id=37254602 humectants AND emollients AND occlusives required: https://news.ycombinator.com/item?id=37253270 I think aquaphor is just an occlusive and emollient? Although I thought at one point it had water as well...","title":"Skin Health Drives All Health"},{"location":"docs/gpt4/skin_health_drives_all_health/#skin-health-drives-all-health","text":"Prolonged exposure to UV radiation, including UVA and UVB rays, can cause systemic inflammation, leading to age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's. UV damage drives 80% of skin health reduction, not aging. This is not referring to skin visual condition (wrinkling), which apparently had no difference, at least in UV vs control group. The appearance of the skin can also serve as a predictive marker for various health conditions, emphasizing the importance of proper skin care and sun protection as integral parts of overall physical well-being.","title":"Skin Health Drives All Health"},{"location":"docs/gpt4/skin_health_drives_all_health/#source-article","text":"https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health archive: https://archive.is/2023.08.24-114321/https://www.bbc.com/future/article/20230823-the-curious-ways-your-skin-shapes-your-health hacker news discussion: https://news.ycombinator.com/item?id=37248882 Especially see humectants and occlusives (moisturizers vs moisture trappers on the skin), you need BOTH","title":"Source Article"},{"location":"docs/gpt4/skin_health_drives_all_health/#gpt-4-executive-summary","text":"The risks associated with neglecting skin health extend beyond mere cosmetic concerns and are linked to serious systemic health issues. Prolonged exposure to UV radiation, particularly UVA and UVB rays, can cause damage to the skin, leading to systemic inflammation. This inflammation is not confined to the skin but affects other organs, including the heart and brain. The concept of \"inflammaging\" highlights how chronic inflammation, often stemming from skin damage, can be a significant risk factor for age-related diseases such as cardiovascular disease, type 2 diabetes, Alzheimer's, and Parkinson's. Furthermore, the appearance of the skin can be an early indicator of underlying health conditions. Research, such as the Baltimore Longitudinal Study, has found correlations between skin appearance and inner health, making skin a potential predictive marker for various diseases. The failure to protect and maintain skin health through proper care and sun protection can exacerbate these risks, making the skin not just a reflection of our lifestyle but an active participant in our overall well-being. The connection between skin health and systemic health underscores the importance of a comprehensive approach to skincare, recognizing its vital role in overall physical wellness.","title":"GPT-4 executive summary"},{"location":"docs/gpt4/skin_health_drives_all_health/#gpt-4-checklists","text":"","title":"GPT-4 Checklists"},{"location":"docs/gpt4/skin_health_drives_all_health/#daily-runbook-checklist","text":"Morning : Cleanse, moisturize, apply suncream (SPF15 or higher), wear SPF clothing. Afternoon : Reapply suncream if exposed to sun, stay hydrated. Evening : Cleanse, apply nourishing moisturizer. Special Considerations : Use sunglasses, wide-brimmed hat, seek shade, use sun umbrella if outdoors.","title":"Daily Runbook Checklist:"},{"location":"docs/gpt4/skin_health_drives_all_health/#best-practices-checklist","text":"Understand Skin : Know your skin type and needs. UV Protection : Use suncream with UVA/UVB protection. Wear Protection : Utilize protective clothing and accessories. Moisturize : Apply moisturizer regularly. Avoid Sun Overexposure : Limit sun exposure during peak hours. Monitor Skin : Regularly check for changes and consult professionals if needed. Holistic Approach : Recognize skin's role in overall well-being. Stay Informed : Keep updated on skin health research and consult healthcare professionals. These checklists encapsulate the essential daily routines and best practices for maintaining skin health, reflecting the information provided in the article.","title":"Best Practices Checklist:"},{"location":"docs/gpt4/skin_health_drives_all_health/#experimental-ideas","text":"DIY 20% ascorbic acid for the face (vitamin c): https://news.ycombinator.com/item?id=37254602 humectants AND emollients AND occlusives required: https://news.ycombinator.com/item?id=37253270 I think aquaphor is just an occlusive and emollient? Although I thought at one point it had water as well...","title":"Experimental Ideas"},{"location":"docs/logs/creativity_2023123/","text":"Creativity ref: https://www.henrikkarlsson.xyz/p/good-ideas Notes on \"Cultivating a state of mind where new ideas are born\" This is an insight that has been repeated by artists, too. Pablo Picasso: \u201cWithout great solitude, no serious work is possible.\u201d James Baldwin: \u201cPerhaps the primary distinction of the artist is that he must actively cultivate that state which most men, necessarily, must avoid: the state of being alone.\u201d Bob Dylan: \u201cTo be creative you\u2019ve got to be unsociable and tight-assed.\u201d Solitude is not being alone, it is a state of mind where \"the opinions of others do not bother them and where they reach a heightened sensitivity for the larval ideas and great questions in them\". Insights from the notes of 2 creatives \"Alexander Grothendieck\" and \"Ingmar Bergman\". Alexander Grothendieck be uncommonly willing to linger in confusion, and be curious about \"what confuses\" wait for a more powerful and subtle question to arise from loose and open attention capacity to surface questions set Grothendieck apart Paul Graham: People who'd never dream of being fashionable in any other way get sucked into working on fashionable problems Working with others without losing yourself didn't find this section too useful Ingmar Bergman admonishes self to create a personality resistant to outside world and protect creativity i often correct myself with such a phrase, and i thought of it as propping myself up or giving myself confidence of sorts, but i guess it is also an admonition of a past experience or behavior that i am committing not to allow to replicate bergman used the journal as a safe place for ideas we have such safe places, even at work as team collaborative private channels bergman develops strict routine of writing in workbook from 9-noon for 3 hours, stopping mid sentence at the strike of the clock! journal is main technique to induce the creative state where his works are born non judgmental zone This is a fairly common practice, crafting a ritual where you sit down at the same time every day, in the same chair, writing in the same kind of notebook, creating a repetitiveness that borders on self-hypnosis. This is what Hemingway did, it is what Mario Vargas Llosa does. I tried to replace this with digital, but I think I will bring back paper, tried and true. Similarities between the two both kept creative/work journals journals veered off without warning, to whatever comes to the author's focus, not trying for a structure, but just freely journaling. More Techniques This is pretty useful, putting the excerpt here: More techniques Here are some other techniques people use to access and maintain the zone : Introducing a long delay between when you do the work and when it is shown to the world . Annie Ernaux writes about this in A Simple Passion , a memoir about how she becomes obsessed in a banal way with a man who is having an affair with her \u2014 the thought that others will read these notes about the tacky sex life of a middle - aged woman feels , to her , almost fictional . She will be far away when it happens . Therefore , she doesn \u2019 t feel a need to protect herself . Thinking of the work in religious terms , as a service to , or a search for , God . Bergman , Grothendieck , and Pascal all do this . It might be easier to summon the awe and daring necessary to push out into the unknown and against social pressure if the alternative is failing God . Or a fiendish muse . Working with talented and open - minded collaborators , if you have the chance , can be a way to enter the zone . Nick Cave , when asked how he \u2019 s been able to reinvent himself so many times as a musician , says that his bandmates , especially Warren Ellis , simply will not play anything that sounds like what he \u2019 s done before . He has surrounded himself with people whose influence is the inverse of the social pressure of normal society and his audience . Another idea if you want to push against the mental pressure that kills good ideas , from Paul Graham \u2019 s recent essay on how to do good work : \u201c One way to do that is to ask what would be good ideas for someone else to explore . Then your subconscious won 't shoot them down to protect you.\u201d I don\u2019t know of anyone using this technique, but it might work. Actively subvert expectations . Kristian Mattsson , who performs under the moniker Tallest Man on Earth , says he pays close attention to his emotions as he \u2019 s writing new songs . If he gets excited , purely , he immediately puts the guitar down \u2014 excitement means what he is playing something he knows others will like , something that retreads paths he has already explored and been socially validated for . The songs he \u2019 s looking for are the ones that he \u2019 s ashamed of liking . Noticing these subtle differences in creative excitement requires subtle introspection . But you can be even more subtle . If we think of creative introspection as having three levels , Mattsson is on level two . ( Level one is just noticing that you find an idea interesting or exciting . ) Level two is noticing that your longing to be accepted can fool you to get excited about an idea that you are not actually excited about . Level three is Andrei Tarkovsky . In his diary , during preproduction of his masterpiece Solaris , the Soviet filmmaker writes that he has met a sound engineer that he considers brilliant . The sound engineer told Tarkovsky that they shouldn \u2019 t use Bach in the film because \u201c everyone is using Bach in their films at the moment . \u201d In the diary , Tarkovsky makes no further note , but in the film , the music is \u2014 Bach . Tarkovsky realized it didn \u2019 t matter that Bach was a popular choice that people would praise him for . It was just the right thing . This is very hard to do , so most creatives stay on level 2 and learn that what is popular is a trap . This does lead to good ideas being needlessly killed . But likely more would die if they had let what is popular kill unpopular ideas . Work so fast that you don \u2019 t have time to self - censor . While writing the intensely confessional My Struggle , Knausgaard forced himself to write five pages a day to overcome his tendency to freeze up in shame . Every time he acclimated to the pace of his writing , he increased the quota so he would always be overwhelmed \u2014 at one point he forced himself to write 25 , 000 words in 24 hours , about a third of a normal - sized novel . It is not the best writing he has done ; it kind of melts at the edges . But it is true literature and , like R\u00e9coltes et Semailles and Bergman \u2019 s workbooks , it is a rare opportunity to observe an uncommon and fertile mind in real - time . The mental states where new ideas can be born are hard to open up . And they are continually collapsing . The things you have to do to keep them from caving in will make people frown upon you \u2014 your tendency for isolation , working deep in the night , breaking norms . The zone is a place at the margin of society . But strangely enough , this fragile margin is where the ideas that make our society possible come from . Almost everything that makes up our world first appeared in a solitary head \u2014 the innovations , the tools , the images , the stories , the prophecies , and religions \u2014 it did not come from the center , it came from those who ran from it . Refs https://news.ycombinator.com/item?id=36883436 https://www.henrikkarlsson.xyz/p/good-ideas","title":"Creativity 2023123"},{"location":"docs/logs/creativity_2023123/#creativity","text":"ref: https://www.henrikkarlsson.xyz/p/good-ideas","title":"Creativity"},{"location":"docs/logs/creativity_2023123/#notes-on-cultivating-a-state-of-mind-where-new-ideas-are-born","text":"This is an insight that has been repeated by artists, too. Pablo Picasso: \u201cWithout great solitude, no serious work is possible.\u201d James Baldwin: \u201cPerhaps the primary distinction of the artist is that he must actively cultivate that state which most men, necessarily, must avoid: the state of being alone.\u201d Bob Dylan: \u201cTo be creative you\u2019ve got to be unsociable and tight-assed.\u201d Solitude is not being alone, it is a state of mind where \"the opinions of others do not bother them and where they reach a heightened sensitivity for the larval ideas and great questions in them\". Insights from the notes of 2 creatives \"Alexander Grothendieck\" and \"Ingmar Bergman\".","title":"Notes on \"Cultivating a state of mind where new ideas are born\""},{"location":"docs/logs/creativity_2023123/#alexander-grothendieck","text":"be uncommonly willing to linger in confusion, and be curious about \"what confuses\" wait for a more powerful and subtle question to arise from loose and open attention capacity to surface questions set Grothendieck apart Paul Graham: People who'd never dream of being fashionable in any other way get sucked into working on fashionable problems","title":"Alexander Grothendieck"},{"location":"docs/logs/creativity_2023123/#working-with-others-without-losing-yourself","text":"didn't find this section too useful","title":"Working with others without losing yourself"},{"location":"docs/logs/creativity_2023123/#ingmar-bergman","text":"admonishes self to create a personality resistant to outside world and protect creativity i often correct myself with such a phrase, and i thought of it as propping myself up or giving myself confidence of sorts, but i guess it is also an admonition of a past experience or behavior that i am committing not to allow to replicate bergman used the journal as a safe place for ideas we have such safe places, even at work as team collaborative private channels bergman develops strict routine of writing in workbook from 9-noon for 3 hours, stopping mid sentence at the strike of the clock! journal is main technique to induce the creative state where his works are born non judgmental zone This is a fairly common practice, crafting a ritual where you sit down at the same time every day, in the same chair, writing in the same kind of notebook, creating a repetitiveness that borders on self-hypnosis. This is what Hemingway did, it is what Mario Vargas Llosa does. I tried to replace this with digital, but I think I will bring back paper, tried and true.","title":"Ingmar Bergman"},{"location":"docs/logs/creativity_2023123/#similarities-between-the-two","text":"both kept creative/work journals journals veered off without warning, to whatever comes to the author's focus, not trying for a structure, but just freely journaling.","title":"Similarities between the two"},{"location":"docs/logs/creativity_2023123/#more-techniques","text":"This is pretty useful, putting the excerpt here: More techniques Here are some other techniques people use to access and maintain the zone : Introducing a long delay between when you do the work and when it is shown to the world . Annie Ernaux writes about this in A Simple Passion , a memoir about how she becomes obsessed in a banal way with a man who is having an affair with her \u2014 the thought that others will read these notes about the tacky sex life of a middle - aged woman feels , to her , almost fictional . She will be far away when it happens . Therefore , she doesn \u2019 t feel a need to protect herself . Thinking of the work in religious terms , as a service to , or a search for , God . Bergman , Grothendieck , and Pascal all do this . It might be easier to summon the awe and daring necessary to push out into the unknown and against social pressure if the alternative is failing God . Or a fiendish muse . Working with talented and open - minded collaborators , if you have the chance , can be a way to enter the zone . Nick Cave , when asked how he \u2019 s been able to reinvent himself so many times as a musician , says that his bandmates , especially Warren Ellis , simply will not play anything that sounds like what he \u2019 s done before . He has surrounded himself with people whose influence is the inverse of the social pressure of normal society and his audience . Another idea if you want to push against the mental pressure that kills good ideas , from Paul Graham \u2019 s recent essay on how to do good work : \u201c One way to do that is to ask what would be good ideas for someone else to explore . Then your subconscious won 't shoot them down to protect you.\u201d I don\u2019t know of anyone using this technique, but it might work. Actively subvert expectations . Kristian Mattsson , who performs under the moniker Tallest Man on Earth , says he pays close attention to his emotions as he \u2019 s writing new songs . If he gets excited , purely , he immediately puts the guitar down \u2014 excitement means what he is playing something he knows others will like , something that retreads paths he has already explored and been socially validated for . The songs he \u2019 s looking for are the ones that he \u2019 s ashamed of liking . Noticing these subtle differences in creative excitement requires subtle introspection . But you can be even more subtle . If we think of creative introspection as having three levels , Mattsson is on level two . ( Level one is just noticing that you find an idea interesting or exciting . ) Level two is noticing that your longing to be accepted can fool you to get excited about an idea that you are not actually excited about . Level three is Andrei Tarkovsky . In his diary , during preproduction of his masterpiece Solaris , the Soviet filmmaker writes that he has met a sound engineer that he considers brilliant . The sound engineer told Tarkovsky that they shouldn \u2019 t use Bach in the film because \u201c everyone is using Bach in their films at the moment . \u201d In the diary , Tarkovsky makes no further note , but in the film , the music is \u2014 Bach . Tarkovsky realized it didn \u2019 t matter that Bach was a popular choice that people would praise him for . It was just the right thing . This is very hard to do , so most creatives stay on level 2 and learn that what is popular is a trap . This does lead to good ideas being needlessly killed . But likely more would die if they had let what is popular kill unpopular ideas . Work so fast that you don \u2019 t have time to self - censor . While writing the intensely confessional My Struggle , Knausgaard forced himself to write five pages a day to overcome his tendency to freeze up in shame . Every time he acclimated to the pace of his writing , he increased the quota so he would always be overwhelmed \u2014 at one point he forced himself to write 25 , 000 words in 24 hours , about a third of a normal - sized novel . It is not the best writing he has done ; it kind of melts at the edges . But it is true literature and , like R\u00e9coltes et Semailles and Bergman \u2019 s workbooks , it is a rare opportunity to observe an uncommon and fertile mind in real - time . The mental states where new ideas can be born are hard to open up . And they are continually collapsing . The things you have to do to keep them from caving in will make people frown upon you \u2014 your tendency for isolation , working deep in the night , breaking norms . The zone is a place at the margin of society . But strangely enough , this fragile margin is where the ideas that make our society possible come from . Almost everything that makes up our world first appeared in a solitary head \u2014 the innovations , the tools , the images , the stories , the prophecies , and religions \u2014 it did not come from the center , it came from those who ran from it .","title":"More Techniques"},{"location":"docs/logs/creativity_2023123/#refs","text":"https://news.ycombinator.com/item?id=36883436 https://www.henrikkarlsson.xyz/p/good-ideas","title":"Refs"},{"location":"docs/monographs/account_traversal/","text":"Account Traversal Disclaimer: This document does not include a strict howto. Can someone who has gained control of your phone number take over all your online accounts? What if someone controls one of these: 1. Primary Email 2. Recovery Email for the Primary Email 3. Domain Name Registrar - for the Domain Name of your Primary Email Can I Trust my phone company? No, that's how the CIA Director got hacked . If you need more fear, watch this exploit demo video . Not convinced? This reporter lost it all (and got some back ). Should I turn off phone number recovery ? I don't know, should you? This whole document is dedicated to convincing you that you should, unless you don't have the bandwidth to do so. Removing Phone Number Recovery from primary accounts will help a lot, but it's also the default way that you recover your account if you lose your password. It is not the only way though, and we will explore better alternatives. Most accounts are dependent on one of the following accounts: - Google Account (parent account of gmail service) - iCloud Account (Apple) - Facebook Profile - Phone Number (Provider Managed Account) But I'm in a hurry! First of all, if you aren't really thinking about these problems and how they affect your online presence, you should just leave phone recovery on. Turning it off requires attention, consideration, and light maintenance. If you are in a position that could compromise your salary , business , community , or family , think carefully about whether you govern your information in a way that impacts those relationships fairly. Determine if you have what it takes! If you are disorganized, lose your keys often, or have things stolen often, the recovery phone number may be safer for you. Clarifying 2FA and FIDO-U2F FIDO-U2F provides key marginal benefits over using Google Authenticator. TL;DR - The benefits are marginal, tangible, and convenient. Which product do I use? I used the Yubico FIDO-U2F . You will need to register two of them on each account and put one in a safe place in case you lose the other. Benefits Fast compared to OTP 2FA (one-time password e.g. Google Authenticator) Immune to Shoulder Surfing (no visual acquisition vector) Phone theft happens daily, this is not in a phone A backup FIDO-U2F is cheaper & easier to maintain than a backup phone containing additional Google Authenticator OTP for each account. Many OTP setups only support one linked app, too (needs fact checked) The account server may be able to detect a man in the middle attack or a phishing website However, many companies may not bother doing this -- shame on them Cannot verify they are doing this or doing it right Costs Surprise: You have to use Google Authenticator on each account if you want to login to things on an iPhone Apparently you can connect the FIDO-U2F dongle to an android phone? Browsers: FIDO-U2F only works with Chrome and Opera (for now) Reportedly Firefox and Microsoft are coming No hope for Safari, iPhone FIDO-U2F (Apple hates sharing) You have to use Google Authenticator for everything else Make a backup U2F token in case you lose your keys Keep your backup up-to-date Maintain an index of what services use U2F so you can audit your backup Improving Security without FIDO-U2F? The same order of account protection can be achieved without FIDO-U2F: 1. Use Google Authenticator 2. Have a second BACKUP 2FA method (NOT a phone number) - WHEN your phone is stolen , you WILL lose all those Google Authenticator 2FA tokens. - iPhone Encrypted backups currently store them. This isn't guaranteed. - Unencrypted backups do not store them. I do not know if icloud backups store them. 3. Disable Phone Number Account Recovery Know your recovery emails and recovery phone numbers Google has a recovery email feature. Is it your Yahoo account from 2003? If your recovery email for tons of services is Google, and your recovery email for Google is hacked, then you are a sitting duck . Change your recovery email! Did you know that yahoo is totally compromised ? A customer service agent at a phone company often has the power to reallocate your phone number to a new device. If a person steals your identity , they can compromise any accounts with a recovery phone number . Building an account recovery graph It is helpful to build a graph of how your account dependencies resolve. This requires you to list out your commonly accessed accounts. Draw this graph with bubbles and arrows. For each account ask yourself, \"if I lose the password for this account, how do I recover it?\" The answer is usually traced back to one recovery phone number and a few recovery email accounts. Once you find your most common recovery emails and recovery phone numbers , ask yourself - how do you recover those accounts? You should find that everything depeonds on one or two things, often your phone number and primary email . Now imagine if a thief got access to one of these recovery accounts . What happens next? How many accounts can they steal from you? Does your primary email have a recovery email ? Why would you have a recovery email on your primary email? If that recovery email is compromised, it is at the top of your account recovery graph , and a prime target for an attacker. Know your Circular Dependencies If your Google and iCloud accounts both recover each other, they form a closed loop and can compromise any account linked to either one. Account Traversal This just means the ability to walk down your whole graph from one piece of information. This is how you lose all your data. Account traversal generally begins at your email or phone number. For a given online account, a person can probably access your recovery email if they control your recovery phone number .","title":"Account Traversal"},{"location":"docs/monographs/account_traversal/#account-traversal","text":"Disclaimer: This document does not include a strict howto. Can someone who has gained control of your phone number take over all your online accounts? What if someone controls one of these: 1. Primary Email 2. Recovery Email for the Primary Email 3. Domain Name Registrar - for the Domain Name of your Primary Email","title":"Account Traversal"},{"location":"docs/monographs/account_traversal/#can-i-trust-my-phone-company","text":"No, that's how the CIA Director got hacked . If you need more fear, watch this exploit demo video . Not convinced? This reporter lost it all (and got some back ).","title":"Can I Trust my phone company?"},{"location":"docs/monographs/account_traversal/#should-i-turn-off-phone-number-recovery","text":"I don't know, should you? This whole document is dedicated to convincing you that you should, unless you don't have the bandwidth to do so. Removing Phone Number Recovery from primary accounts will help a lot, but it's also the default way that you recover your account if you lose your password. It is not the only way though, and we will explore better alternatives. Most accounts are dependent on one of the following accounts: - Google Account (parent account of gmail service) - iCloud Account (Apple) - Facebook Profile - Phone Number (Provider Managed Account)","title":"Should I turn off phone number recovery?"},{"location":"docs/monographs/account_traversal/#but-im-in-a-hurry","text":"First of all, if you aren't really thinking about these problems and how they affect your online presence, you should just leave phone recovery on. Turning it off requires attention, consideration, and light maintenance. If you are in a position that could compromise your salary , business , community , or family , think carefully about whether you govern your information in a way that impacts those relationships fairly.","title":"But I'm in a hurry!"},{"location":"docs/monographs/account_traversal/#determine-if-you-have-what-it-takes","text":"If you are disorganized, lose your keys often, or have things stolen often, the recovery phone number may be safer for you.","title":"Determine if you have what it takes!"},{"location":"docs/monographs/account_traversal/#clarifying-2fa-and-fido-u2f","text":"FIDO-U2F provides key marginal benefits over using Google Authenticator. TL;DR - The benefits are marginal, tangible, and convenient.","title":"Clarifying 2FA and FIDO-U2F"},{"location":"docs/monographs/account_traversal/#which-product-do-i-use","text":"I used the Yubico FIDO-U2F . You will need to register two of them on each account and put one in a safe place in case you lose the other.","title":"Which product do I use?"},{"location":"docs/monographs/account_traversal/#benefits","text":"Fast compared to OTP 2FA (one-time password e.g. Google Authenticator) Immune to Shoulder Surfing (no visual acquisition vector) Phone theft happens daily, this is not in a phone A backup FIDO-U2F is cheaper & easier to maintain than a backup phone containing additional Google Authenticator OTP for each account. Many OTP setups only support one linked app, too (needs fact checked) The account server may be able to detect a man in the middle attack or a phishing website However, many companies may not bother doing this -- shame on them Cannot verify they are doing this or doing it right","title":"Benefits"},{"location":"docs/monographs/account_traversal/#costs","text":"Surprise: You have to use Google Authenticator on each account if you want to login to things on an iPhone Apparently you can connect the FIDO-U2F dongle to an android phone? Browsers: FIDO-U2F only works with Chrome and Opera (for now) Reportedly Firefox and Microsoft are coming No hope for Safari, iPhone FIDO-U2F (Apple hates sharing) You have to use Google Authenticator for everything else Make a backup U2F token in case you lose your keys Keep your backup up-to-date Maintain an index of what services use U2F so you can audit your backup","title":"Costs"},{"location":"docs/monographs/account_traversal/#improving-security-without-fido-u2f","text":"The same order of account protection can be achieved without FIDO-U2F: 1. Use Google Authenticator 2. Have a second BACKUP 2FA method (NOT a phone number) - WHEN your phone is stolen , you WILL lose all those Google Authenticator 2FA tokens. - iPhone Encrypted backups currently store them. This isn't guaranteed. - Unencrypted backups do not store them. I do not know if icloud backups store them. 3. Disable Phone Number Account Recovery","title":"Improving Security without FIDO-U2F?"},{"location":"docs/monographs/account_traversal/#know-your-recovery-emails-and-recovery-phone-numbers","text":"Google has a recovery email feature. Is it your Yahoo account from 2003? If your recovery email for tons of services is Google, and your recovery email for Google is hacked, then you are a sitting duck . Change your recovery email! Did you know that yahoo is totally compromised ? A customer service agent at a phone company often has the power to reallocate your phone number to a new device. If a person steals your identity , they can compromise any accounts with a recovery phone number .","title":"Know your recovery emails and recovery phone numbers"},{"location":"docs/monographs/account_traversal/#building-an-account-recovery-graph","text":"It is helpful to build a graph of how your account dependencies resolve. This requires you to list out your commonly accessed accounts. Draw this graph with bubbles and arrows. For each account ask yourself, \"if I lose the password for this account, how do I recover it?\" The answer is usually traced back to one recovery phone number and a few recovery email accounts. Once you find your most common recovery emails and recovery phone numbers , ask yourself - how do you recover those accounts? You should find that everything depeonds on one or two things, often your phone number and primary email . Now imagine if a thief got access to one of these recovery accounts . What happens next? How many accounts can they steal from you?","title":"Building an account recovery graph"},{"location":"docs/monographs/account_traversal/#does-your-primary-email-have-a-recovery-email","text":"Why would you have a recovery email on your primary email? If that recovery email is compromised, it is at the top of your account recovery graph , and a prime target for an attacker.","title":"Does your primary email have a recovery email?"},{"location":"docs/monographs/account_traversal/#know-your-circular-dependencies","text":"If your Google and iCloud accounts both recover each other, they form a closed loop and can compromise any account linked to either one.","title":"Know your Circular Dependencies"},{"location":"docs/monographs/account_traversal/#account-traversal_1","text":"This just means the ability to walk down your whole graph from one piece of information. This is how you lose all your data. Account traversal generally begins at your email or phone number. For a given online account, a person can probably access your recovery email if they control your recovery phone number .","title":"Account Traversal"},{"location":"docs/monographs/candidate-languages-for-genetic-algorithms/","text":"Self Description and Self replication and Genetic Algorithms Candidate Languages for Genetic Algorithms: Binary Lambda Calculus (BLC) Game of Life / Wiring / other derivatives brainfuck m4 Generating Brainfuck using a genetic algorithm Project here . Binary Lambda Calculus A lot of interesting blc information is stored here: https://tromp.github.io/cl/Binary_lambda_calculus.html A ton of info from the creator of tromp : https://tromp.github.io/cl/cl.html This ties in closely to computer science theory and brainfuck in general. The author claims that tromp is the most concise possible universal machine details about tromp: http://www.ioccc.org/2012/tromp/hint.html m4 macro language Written by: Brian Kernighan, Dennis Ritchie m4 is a general-purpose macro processor included in all UNIX-like operating systems, and is a component of the POSIX standard. Someone who made obfuscated casino software (about 20 years before 2018) in brainfuck on hacker news said that they \"leaned heavily on make and m4\" in order to write most of the brainfuck. https://en.wikipedia.org/wiki/M4_(computer_language)","title":"Candidate Languages For Genetic Algorithms"},{"location":"docs/monographs/candidate-languages-for-genetic-algorithms/#self-description-and-self-replication-and-genetic-algorithms","text":"Candidate Languages for Genetic Algorithms: Binary Lambda Calculus (BLC) Game of Life / Wiring / other derivatives brainfuck m4","title":"Self Description and Self replication and Genetic Algorithms"},{"location":"docs/monographs/candidate-languages-for-genetic-algorithms/#generating-brainfuck-using-a-genetic-algorithm","text":"Project here .","title":"Generating Brainfuck using a genetic algorithm"},{"location":"docs/monographs/candidate-languages-for-genetic-algorithms/#binary-lambda-calculus","text":"A lot of interesting blc information is stored here: https://tromp.github.io/cl/Binary_lambda_calculus.html A ton of info from the creator of tromp : https://tromp.github.io/cl/cl.html This ties in closely to computer science theory and brainfuck in general. The author claims that tromp is the most concise possible universal machine details about tromp: http://www.ioccc.org/2012/tromp/hint.html","title":"Binary Lambda Calculus"},{"location":"docs/monographs/candidate-languages-for-genetic-algorithms/#m4-macro-language","text":"Written by: Brian Kernighan, Dennis Ritchie m4 is a general-purpose macro processor included in all UNIX-like operating systems, and is a component of the POSIX standard. Someone who made obfuscated casino software (about 20 years before 2018) in brainfuck on hacker news said that they \"leaned heavily on make and m4\" in order to write most of the brainfuck. https://en.wikipedia.org/wiki/M4_(computer_language)","title":"m4 macro language"},{"location":"docs/monographs/case-study-agar.io/","text":"Case Study: agar.io This game has been around for awhile now and represents migrating a viral game to an ad-based and app based revenue platform. References Wikipedia: Agar.io Research Growth Originally released on the creator's IP address via 4chan Game released 1 week later on Steam Greenlight which is now called Steam Direct . Monetization Methods Ads in-game purchases Mobile Platform vs HTML5 - which came first, do they play together? HTML5 - Browser Experience Is this really the original platform or just initially the most viral? Mobile Experience Install the mobile game and experience how it is compared to the online game Is this an HTML5 game? What packager does it use? How is the performance, usership? Does it share users with the browser game?","title":"Case Study Agar.Io"},{"location":"docs/monographs/case-study-agar.io/#case-study-agario","text":"This game has been around for awhile now and represents migrating a viral game to an ad-based and app based revenue platform.","title":"Case Study: agar.io"},{"location":"docs/monographs/case-study-agar.io/#references","text":"Wikipedia: Agar.io","title":"References"},{"location":"docs/monographs/case-study-agar.io/#research","text":"","title":"Research"},{"location":"docs/monographs/case-study-agar.io/#growth","text":"Originally released on the creator's IP address via 4chan Game released 1 week later on Steam Greenlight which is now called Steam Direct .","title":"Growth"},{"location":"docs/monographs/case-study-agar.io/#monetization-methods","text":"Ads in-game purchases","title":"Monetization Methods"},{"location":"docs/monographs/case-study-agar.io/#mobile-platform-vs-html5-which-came-first-do-they-play-together","text":"","title":"Mobile Platform vs HTML5 - which came first, do they play together?"},{"location":"docs/monographs/case-study-agar.io/#html5-browser-experience","text":"Is this really the original platform or just initially the most viral?","title":"HTML5 - Browser Experience"},{"location":"docs/monographs/case-study-agar.io/#mobile-experience","text":"Install the mobile game and experience how it is compared to the online game Is this an HTML5 game? What packager does it use? How is the performance, usership? Does it share users with the browser game?","title":"Mobile Experience"},{"location":"docs/monographs/cheap_raid_server/","text":"Cheap Raid Server Working Free Space When your storage is 80% full, consider it full due to difficulty shuffling data. So add a 80% multiplier on any storage requirements and get a 30% overhead for required stuff. ref: https://jrs-s.net/2016/11/08/depressing-storage-calculator/ What is the base cost of a software RAID server Hardware or software raid? According to this reddit post, hardware raid is incredibly out of date. Raid Configurations Available today According to the below, only btrfs RAID10 is stable. This has great redundancy except 2 adjacent disk stripes during failure, so there is stripe single redundancy... Used Hard Drives LTT on why these drives are out there today (2022): https://www.youtube.com/watch?v=xQMQW4sbXf8 crypto mining aka \"chia mining\", these drives are \"barely used\", just written once... they had 2300-2600 hours of poweron time... that's only 100 days? expected lifetime 50k-60k, manufacturer says 45k hours is the reliability standard linus recommends 20k to 25k hours as the safe ceiling This video shows a lot of drive metrics (SMART attrs) that can predict drive failure up to 70% of the time Video also shows how to determine the drive was used for mining (1 write, low reads, lots of poweron hours) WD drives didn't record reads and writes... DIY NAS best deal was 80gb per dollar, seagate was the cheapest brand on ebay and had reads/writes. However, the 18TB shucked drives are only $170 (provided they are not SMR), which are the same price... Linux recommends used, i guess to save on electronic waste? Shingled Drives / SMR Do not use random consumer drives for RAID arrays... ;( Check out the SMR section here for understanding what drives don't use it lately: https://www.reddit.com/r/DataHoarder/wiki/hardware The exact easystore shucked drive, post 2019 WD Red drives, are shingled/SMR. According to this thread, that is not true for larger drives, they converge on helium filled: https://www.reddit.com/r/DataHoarder/comments/wlingk/should_i_buy_cmr_or_smr/ However, shucking can require power pin reroute, which I don't want to mess with. For occasional backups and cold storage, SMR is perfectly fine. In my experience, WD SMR is implemented much better than Seagate. But for WD 8-20TB are all CMR. Seagate 10-20TB are CMR. ref: https://raid.wiki.kernel.org/index.php/Linux_Raid ref 2: https://raid.wiki.kernel.org/index.php/Timeout_Mismatch In 2019, a new technology called shingled magnetic recording (SMR) started becoming mainstream. Whereas drive usage limits on conventional drives are advisory, burst limits especially on SMR drives are mandatory, and interfere with raid operation. While all manufacturers have been quietly introducing SMR on their desktop lines, WD unfortunately also introduced it on their \"suitable for NAS/RAID\" WD Red drives. Unfortunately, combining SMR and RAID is not a good idea, with many reports of new WD Reds simply refusing to be added to an existing array. While conventional desktop drives (which use conventional magnetic recording or CMR) may take up to two minutes to give up reading, SMR drives are even worse - there are reports of them stalling for over 10 minutes as the drive shuffles everything around to make space. For SMR drives, the drive should report that the trim command is supported. Unfortunately, some (many?) cheaper SMR drives do not, and due to the nature of SMR drives that don't support trim will have problems, leading to exactly the grief many have reported - the drive stalling for ever almost as it has to rewrite masses of data. Note, however, that SMR drives come in at least three types - DM (device managed) which may or may not support trimming, and HM (host managed) which shouldn't be a problem as they leave it to the computer to sort out. Types of RAID apparently RAID5 has some risks after drive fail, mainly a second drive will possibly fail when data is being redistributed. https://www.reddit.com/r/sysadmin/comments/uu8115/raid5_ideal_configuration_is_35_or_9_drives_plus/ RAID10 aka RAID (1+0) is recommended for 2-drive redundancy Apparently SSDs are safer for RAID5 but it seems their max size is 2 TB, at 9 drives == 16TB So, SSD could be technically viable with multiple RAID servers However, cost is probably not viable, since 2 * 9 * $160*1.1 == $3168 for 16 TB, cost is like 6x RAID6 Ideally use RAID6 since it has double redundancy, 2 arbitrary drives can fail, and good efficiency. It looks like LVM directly supports RAID6, so this must be the go-to software RAID: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_logical_volumes/assembly_configure-mange-raid-configuring-and-managing-logical-volumes The main problem with RAID6 seems to be software RAID support, BTRFS discourages it for production: https://www.phoronix.com/news/Btrfs-Warning-RAID5-RAID6 RAID6 considered unstable for btrfs: https://btrfs.wiki.kernel.org/index.php/Status#RAID56 RAID6 has 2 redundant drives, this seems good if I build a system from unreliable parts. This seems suitable for having tons of drives. How would it work with mismatched drives, e.g. does it batch the smaller drives to bring them up to \"effectively 2 redundant drives\"? There must be some algorithm... e.g. if I had 1 8tb disk and 10 2 tb disks, and I have an 8tb disk, does that mean that I can still have an arbitrary disk fail and keep all my data? Or does that mean that the initial max storage calculated will be much lower for mismatch drive scenarios? Post explaining redundancy and bad reads in a drive failure scenario, explaining why RAID5 is dangerous and RAID6 provides additional bad read redundancy in this case: https://www.reddit.com/r/DataHoarder/comments/b57u7r/at_what_point_is_raid_6_worth_it/ejbsj55/ RAID10 RAID10 is RAID1+0. It is 50% redundant and would be good for critical data storage, but I don't need that. Expensive RAID5 server Hard drive cost: $1534.50 Total effective storage: 65.48 terabytes $306.90 after tax per 18tb easystore: https://shucks.top/ 16.37 terabytes true storage after converting 18,000 GB by /1024/1024/1024/1024 (terabytes on computer are actually tib) https://www.bestbuy.com/site/questions/wd-easystore-18tb-external-usb-3-0-hard-drive-black/6427995/question/833048c7-e97b-38e8-b8fe-f6e48d6aea8e 5 drives and 18tb/drive = 81.85 tb and 4/5 storage to redundancy = 65.48 terabytes effective Cost of $306.90 * 5 + base cost of RAID server Cheaper RAID server Still pretty expensive, how much space do we get? Probably 8/18 * 65.48 == 29.1 TB So we get 44% of the space for 60% of the cost of drives, so drives are 50% more expensive, plus the base cost 8 tb easystores are typically $187 after tax 5 * 187 = $935","title":"Cheap Raid Server"},{"location":"docs/monographs/cheap_raid_server/#cheap-raid-server","text":"","title":"Cheap Raid Server"},{"location":"docs/monographs/cheap_raid_server/#working-free-space","text":"When your storage is 80% full, consider it full due to difficulty shuffling data. So add a 80% multiplier on any storage requirements and get a 30% overhead for required stuff. ref: https://jrs-s.net/2016/11/08/depressing-storage-calculator/","title":"Working Free Space"},{"location":"docs/monographs/cheap_raid_server/#what-is-the-base-cost-of-a-software-raid-server","text":"","title":"What is the base cost of a software RAID server"},{"location":"docs/monographs/cheap_raid_server/#hardware-or-software-raid","text":"According to this reddit post, hardware raid is incredibly out of date.","title":"Hardware or software raid?"},{"location":"docs/monographs/cheap_raid_server/#raid-configurations-available-today","text":"According to the below, only btrfs RAID10 is stable. This has great redundancy except 2 adjacent disk stripes during failure, so there is stripe single redundancy...","title":"Raid Configurations Available today"},{"location":"docs/monographs/cheap_raid_server/#used-hard-drives","text":"LTT on why these drives are out there today (2022): https://www.youtube.com/watch?v=xQMQW4sbXf8 crypto mining aka \"chia mining\", these drives are \"barely used\", just written once... they had 2300-2600 hours of poweron time... that's only 100 days? expected lifetime 50k-60k, manufacturer says 45k hours is the reliability standard linus recommends 20k to 25k hours as the safe ceiling This video shows a lot of drive metrics (SMART attrs) that can predict drive failure up to 70% of the time Video also shows how to determine the drive was used for mining (1 write, low reads, lots of poweron hours) WD drives didn't record reads and writes... DIY NAS best deal was 80gb per dollar, seagate was the cheapest brand on ebay and had reads/writes. However, the 18TB shucked drives are only $170 (provided they are not SMR), which are the same price... Linux recommends used, i guess to save on electronic waste?","title":"Used Hard Drives"},{"location":"docs/monographs/cheap_raid_server/#shingled-drives-smr","text":"Do not use random consumer drives for RAID arrays... ;( Check out the SMR section here for understanding what drives don't use it lately: https://www.reddit.com/r/DataHoarder/wiki/hardware The exact easystore shucked drive, post 2019 WD Red drives, are shingled/SMR. According to this thread, that is not true for larger drives, they converge on helium filled: https://www.reddit.com/r/DataHoarder/comments/wlingk/should_i_buy_cmr_or_smr/ However, shucking can require power pin reroute, which I don't want to mess with. For occasional backups and cold storage, SMR is perfectly fine. In my experience, WD SMR is implemented much better than Seagate. But for WD 8-20TB are all CMR. Seagate 10-20TB are CMR. ref: https://raid.wiki.kernel.org/index.php/Linux_Raid ref 2: https://raid.wiki.kernel.org/index.php/Timeout_Mismatch In 2019, a new technology called shingled magnetic recording (SMR) started becoming mainstream. Whereas drive usage limits on conventional drives are advisory, burst limits especially on SMR drives are mandatory, and interfere with raid operation. While all manufacturers have been quietly introducing SMR on their desktop lines, WD unfortunately also introduced it on their \"suitable for NAS/RAID\" WD Red drives. Unfortunately, combining SMR and RAID is not a good idea, with many reports of new WD Reds simply refusing to be added to an existing array. While conventional desktop drives (which use conventional magnetic recording or CMR) may take up to two minutes to give up reading, SMR drives are even worse - there are reports of them stalling for over 10 minutes as the drive shuffles everything around to make space. For SMR drives, the drive should report that the trim command is supported. Unfortunately, some (many?) cheaper SMR drives do not, and due to the nature of SMR drives that don't support trim will have problems, leading to exactly the grief many have reported - the drive stalling for ever almost as it has to rewrite masses of data. Note, however, that SMR drives come in at least three types - DM (device managed) which may or may not support trimming, and HM (host managed) which shouldn't be a problem as they leave it to the computer to sort out.","title":"Shingled Drives / SMR"},{"location":"docs/monographs/cheap_raid_server/#types-of-raid","text":"apparently RAID5 has some risks after drive fail, mainly a second drive will possibly fail when data is being redistributed. https://www.reddit.com/r/sysadmin/comments/uu8115/raid5_ideal_configuration_is_35_or_9_drives_plus/ RAID10 aka RAID (1+0) is recommended for 2-drive redundancy Apparently SSDs are safer for RAID5 but it seems their max size is 2 TB, at 9 drives == 16TB So, SSD could be technically viable with multiple RAID servers However, cost is probably not viable, since 2 * 9 * $160*1.1 == $3168 for 16 TB, cost is like 6x","title":"Types of RAID"},{"location":"docs/monographs/cheap_raid_server/#raid6","text":"Ideally use RAID6 since it has double redundancy, 2 arbitrary drives can fail, and good efficiency. It looks like LVM directly supports RAID6, so this must be the go-to software RAID: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_logical_volumes/assembly_configure-mange-raid-configuring-and-managing-logical-volumes The main problem with RAID6 seems to be software RAID support, BTRFS discourages it for production: https://www.phoronix.com/news/Btrfs-Warning-RAID5-RAID6 RAID6 considered unstable for btrfs: https://btrfs.wiki.kernel.org/index.php/Status#RAID56 RAID6 has 2 redundant drives, this seems good if I build a system from unreliable parts. This seems suitable for having tons of drives. How would it work with mismatched drives, e.g. does it batch the smaller drives to bring them up to \"effectively 2 redundant drives\"? There must be some algorithm... e.g. if I had 1 8tb disk and 10 2 tb disks, and I have an 8tb disk, does that mean that I can still have an arbitrary disk fail and keep all my data? Or does that mean that the initial max storage calculated will be much lower for mismatch drive scenarios? Post explaining redundancy and bad reads in a drive failure scenario, explaining why RAID5 is dangerous and RAID6 provides additional bad read redundancy in this case: https://www.reddit.com/r/DataHoarder/comments/b57u7r/at_what_point_is_raid_6_worth_it/ejbsj55/","title":"RAID6"},{"location":"docs/monographs/cheap_raid_server/#raid10","text":"RAID10 is RAID1+0. It is 50% redundant and would be good for critical data storage, but I don't need that.","title":"RAID10"},{"location":"docs/monographs/cheap_raid_server/#expensive-raid5-server","text":"Hard drive cost: $1534.50 Total effective storage: 65.48 terabytes $306.90 after tax per 18tb easystore: https://shucks.top/ 16.37 terabytes true storage after converting 18,000 GB by /1024/1024/1024/1024 (terabytes on computer are actually tib) https://www.bestbuy.com/site/questions/wd-easystore-18tb-external-usb-3-0-hard-drive-black/6427995/question/833048c7-e97b-38e8-b8fe-f6e48d6aea8e 5 drives and 18tb/drive = 81.85 tb and 4/5 storage to redundancy = 65.48 terabytes effective Cost of $306.90 * 5 + base cost of RAID server","title":"Expensive RAID5 server"},{"location":"docs/monographs/cheap_raid_server/#cheaper-raid-server","text":"Still pretty expensive, how much space do we get? Probably 8/18 * 65.48 == 29.1 TB So we get 44% of the space for 60% of the cost of drives, so drives are 50% more expensive, plus the base cost 8 tb easystores are typically $187 after tax 5 * 187 = $935","title":"Cheaper RAID server"},{"location":"docs/monographs/crm_data_model/","text":"Simple Data Model for CRM Types of data Customer Organization Data Fields Date first entered into this table Organization Name Active? Definite end date? Over 10k future value? Missed payment? History of late payment? Did we ever do a project with them? Do we want to work with them again? Contact @ Customer Organization Data Fields Customer Organization Date first entered into this table Name Job Role Office Phone Number Cell Phone Number Supervisor Name Supervisor Job Role Email Notes Interaction with Contact at Customer Organization Data Fields Customer Organization Contact Date of Interaction Time of Interaction Type of Interaction (phone, email, etc.) Purpose Notes New Lead with Contact at Customer Organization Data Fields Contact Customer Organization Date Source of Client (advertising, referral, website, etc.) Referred By (optional) Estimated Project Value Estimated Client Long-Term Value Contact (implies link to Customer Organization ) Lead Status follows a branching control flow Open or Outstanding Lead Won Lead or Dead Lead Using a spreadsheet A sheet for each type, a row for each entry. This can easily be exported as CSV and imported to an ORM data model. Filters can easily be written on the fly for simple analysis in the meantime.","title":"Crm Data Model"},{"location":"docs/monographs/crm_data_model/#simple-data-model-for-crm","text":"","title":"Simple Data Model for CRM"},{"location":"docs/monographs/crm_data_model/#types-of-data","text":"Customer Organization Data Fields Date first entered into this table Organization Name Active? Definite end date? Over 10k future value? Missed payment? History of late payment? Did we ever do a project with them? Do we want to work with them again? Contact @ Customer Organization Data Fields Customer Organization Date first entered into this table Name Job Role Office Phone Number Cell Phone Number Supervisor Name Supervisor Job Role Email Notes Interaction with Contact at Customer Organization Data Fields Customer Organization Contact Date of Interaction Time of Interaction Type of Interaction (phone, email, etc.) Purpose Notes New Lead with Contact at Customer Organization Data Fields Contact Customer Organization Date Source of Client (advertising, referral, website, etc.) Referred By (optional) Estimated Project Value Estimated Client Long-Term Value Contact (implies link to Customer Organization ) Lead Status follows a branching control flow Open or Outstanding Lead Won Lead or Dead Lead","title":"Types of data"},{"location":"docs/monographs/crm_data_model/#using-a-spreadsheet","text":"A sheet for each type, a row for each entry. This can easily be exported as CSV and imported to an ORM data model. Filters can easily be written on the fly for simple analysis in the meantime.","title":"Using a spreadsheet"},{"location":"docs/monographs/debt_and_blame/","text":"Blame is like debt. If joe owes bob $2 and bob owes sam $2, that's $4 of debt but only $2 in total transaction. We parked in a spot for breakfast this morning and the car to the left was outside the parking line. So we parked to the right. A second person parked us in to our right, so we had to pull out to enter the vehicle, which is annoying. We blamed them and they blamed us, and we blamed the person to the left. That's about 2 units of blame for one unit of bad behavior, which is analogous to the debt scenario above. Debt and blame can be expanded to fill any connected graph size, such as a whole community, both for blame and debt.","title":"Debt And Blame"},{"location":"docs/monographs/licensing_rules/","text":"Basic Licensing Rules This is a living document. Please add an issue if you disagree. Does it compile? Rationale: if it is interpreted, the source is required to run the application. This criterion should be revisited with a focusing question that focuses more on source distribution rather than the more pedantic 'compiled v interpreted' concept. Specific test cases include uglified or beautified javascript, or pyc/pyo bytecode where the work is altered but there is not a sufficient legal test framework. GPL 3 - If it compiles Require descendant projects to use MIT - If it is interpreted Give more permissiveness What about business works? Apache License - Is there a case for retaining a separate agreement for business use?","title":"Licensing Rules"},{"location":"docs/monographs/licensing_rules/#basic-licensing-rules","text":"This is a living document. Please add an issue if you disagree. Does it compile? Rationale: if it is interpreted, the source is required to run the application. This criterion should be revisited with a focusing question that focuses more on source distribution rather than the more pedantic 'compiled v interpreted' concept. Specific test cases include uglified or beautified javascript, or pyc/pyo bytecode where the work is altered but there is not a sufficient legal test framework. GPL 3 - If it compiles Require descendant projects to use MIT - If it is interpreted Give more permissiveness What about business works? Apache License - Is there a case for retaining a separate agreement for business use?","title":"Basic Licensing Rules"},{"location":"docs/monographs/modes-of-thought/","text":"Modes of Thought What modes are useful? How can you enter modes? What modes are useful? This is the short list I came up with based on my usual way of working. Task or Result Focus Creative Focus Flow Diffuse Mode How can you enter modes? Flow* I am not sure this is a distinct mode, it may be a \"Composite Mode\" It seems like \"Task or Result Focus\" with some \"Creative Focus\" alternating loops. Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress. One weakness of the mode is that you might have trouble reentering the work later. Task or Result Focus: gather the task requirements and get to work Creative Focus go to a space with no stimuli such as an empty office room have tools such as notebook, whiteboard, writing tools avoid going into focused mode: pin any research requirements, plan those between creative focus sessions Diffuse mode: anything that completely unbinds the executive mind mindful meditation long mindful walk meandering conversation over dinner read a book take a nap exercise if mindful What are the modes? Task or Result Focus Often strongly supplemented by excel. Examples: Collecting a bunch of documents for taxes. Correlating a data set by hand, e.g. machines with a certain image. Comparing two financial alternatives to determine the risks and returns. Creative Focus Examples: - doing work for a design doc Iteratively whiteboard and refine while the idea gains concreteness. Capture the concrete result Spend some time in diffuse mode Revise repeat diffuse & revise until requirements satisfied Flow Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress. I am not sure this is a distinct mode, it may be a \"Composite Mode\" I usually run out of energy before finishing. Examples: - creative focus alternating with \"task focus\" aka coding/prototyping loop Jump right to prototyping and get an end to end result. Identify the components of the result and rewrite or optimize the incomplete ones. Continue to iterate and decompose the system components until requirements satisfied. Diffuse Mode Learning how to learn: exercise, conversation, resting, what else? See notes Mindful Meditation Walking Resting Conversation Exercise* I sometimes feel that exercise does not bring me to diffuse mode, instead I am in some focused mode.","title":"Modes Of Thought"},{"location":"docs/monographs/modes-of-thought/#modes-of-thought","text":"What modes are useful? How can you enter modes?","title":"Modes of Thought"},{"location":"docs/monographs/modes-of-thought/#what-modes-are-useful","text":"This is the short list I came up with based on my usual way of working. Task or Result Focus Creative Focus Flow Diffuse Mode","title":"What modes are useful?"},{"location":"docs/monographs/modes-of-thought/#how-can-you-enter-modes","text":"Flow* I am not sure this is a distinct mode, it may be a \"Composite Mode\" It seems like \"Task or Result Focus\" with some \"Creative Focus\" alternating loops. Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress. One weakness of the mode is that you might have trouble reentering the work later. Task or Result Focus: gather the task requirements and get to work Creative Focus go to a space with no stimuli such as an empty office room have tools such as notebook, whiteboard, writing tools avoid going into focused mode: pin any research requirements, plan those between creative focus sessions Diffuse mode: anything that completely unbinds the executive mind mindful meditation long mindful walk meandering conversation over dinner read a book take a nap exercise if mindful","title":"How can you enter modes?"},{"location":"docs/monographs/modes-of-thought/#what-are-the-modes","text":"","title":"What are the modes?"},{"location":"docs/monographs/modes-of-thought/#task-or-result-focus","text":"Often strongly supplemented by excel. Examples: Collecting a bunch of documents for taxes. Correlating a data set by hand, e.g. machines with a certain image. Comparing two financial alternatives to determine the risks and returns.","title":"Task or Result Focus"},{"location":"docs/monographs/modes-of-thought/#creative-focus","text":"Examples: - doing work for a design doc Iteratively whiteboard and refine while the idea gains concreteness. Capture the concrete result Spend some time in diffuse mode Revise repeat diffuse & revise until requirements satisfied","title":"Creative Focus"},{"location":"docs/monographs/modes-of-thought/#flow","text":"Flow is an opportunity to create an artifact of great worth, it reminds me of dwarf fortress. I am not sure this is a distinct mode, it may be a \"Composite Mode\" I usually run out of energy before finishing. Examples: - creative focus alternating with \"task focus\" aka coding/prototyping loop Jump right to prototyping and get an end to end result. Identify the components of the result and rewrite or optimize the incomplete ones. Continue to iterate and decompose the system components until requirements satisfied.","title":"Flow"},{"location":"docs/monographs/modes-of-thought/#diffuse-mode","text":"Learning how to learn: exercise, conversation, resting, what else? See notes Mindful Meditation Walking Resting Conversation Exercise* I sometimes feel that exercise does not bring me to diffuse mode, instead I am in some focused mode.","title":"Diffuse Mode"},{"location":"docs/monographs/squarespace_patterns/","text":"Squarespace Patterns A collection of concepts for developing bespoke web applications in the squarespace managed hosting framework. View a page's available JSON by appending ?format=json-pretty to the url. Avoid putting in credentials every git push Manage local git config in the project directory. From this squarespace answer . `git config credential.helper 'cache --timeout=3600' Text blocks merge! How to prevent text blocks from merging. Alternate text blocks with empty markdown blocks Managing LESS and CSS styles/reset.css - override squarespace default styles styles/base.css - seems to go on each site either before or after site Managing Editable Page Sections (inside a parent page) Squarespace requires some acrobatics in order to display editable pages inside the main page. Scenario: Bespoke Theme from Designer The client needs to edit the contents Plan: Use a squarespace index.conf . This page contains other pages. The index page will display its own template, collections/index.list which will wrap the \"main content\" from the Squarespace CMS. The json data available to the index.conf, primarily just title and navigation title and slug (all have similar names in the json) can also be called in the template. The client doesn't need to edit the contents Plan: Embed the content into the page templates Template Management jsont.squarespace.com json-t basics json-t advanced developers.squarespace.com what is json-t json-t system variables json-t predicates json-t directive json-t formatters json-t helpers custom Query tag for collection querying answers.squarespace.com disambiguating {.if} and {.equal} custom layout for individual page User-editable sections In order to allow to clients to edit their pages in a coherent way, it is necessary to use index pages to combine each editable page into one 'main page'. In order to aggregate pages and collections, use an index at the top level, and use folders at subordinate levels. Folders & Indexes are the mechanism for building custom aggregate pages. Custom Index Page Anchor Links in Index Pages - may or may not be important One pattern is to have headers and paragraphs of text interleaved with sections of content, for example project pages with a grid of images or a grid of logos, or a grid of contributors. An effective pattern for working with this may be to have one collection of paragraphs and titles which are specifically indexed in teh template. These are interleaved with actual collection sections which loop over each item in the collection to populate the segment. Template Partials break up sections so Squarespace users can edit them. Example: A simple 'blog post' section. Display any number of vertical paragraphs and images in any order. Squarespace Query: Access collection Data from another page A method for giving the user some edit control over a custom template. Managing Templates Layouts & Regions - how to make different page templates for different pages Basic Template, Navigation, and Blocks Beginner Tutorial - good intro to nav and code blocks. A little unclear at times. blocks/navigation.block was not being detected. I renamed it to blocks/nav.block and changed the reference to it to 'nav'.","title":"Squarespace Patterns"},{"location":"docs/monographs/squarespace_patterns/#squarespace-patterns","text":"A collection of concepts for developing bespoke web applications in the squarespace managed hosting framework. View a page's available JSON by appending ?format=json-pretty to the url.","title":"Squarespace Patterns"},{"location":"docs/monographs/squarespace_patterns/#avoid-putting-in-credentials-every-git-push","text":"Manage local git config in the project directory. From this squarespace answer . `git config credential.helper 'cache --timeout=3600'","title":"Avoid putting in credentials every git push"},{"location":"docs/monographs/squarespace_patterns/#text-blocks-merge-how-to-prevent-text-blocks-from-merging","text":"Alternate text blocks with empty markdown blocks","title":"Text blocks merge! How to prevent text blocks from merging."},{"location":"docs/monographs/squarespace_patterns/#managing-less-and-css","text":"styles/reset.css - override squarespace default styles styles/base.css - seems to go on each site either before or after site","title":"Managing LESS and CSS"},{"location":"docs/monographs/squarespace_patterns/#managing-editable-page-sections-inside-a-parent-page","text":"Squarespace requires some acrobatics in order to display editable pages inside the main page. Scenario: Bespoke Theme from Designer The client needs to edit the contents Plan: Use a squarespace index.conf . This page contains other pages. The index page will display its own template, collections/index.list which will wrap the \"main content\" from the Squarespace CMS. The json data available to the index.conf, primarily just title and navigation title and slug (all have similar names in the json) can also be called in the template. The client doesn't need to edit the contents Plan: Embed the content into the page templates","title":"Managing Editable Page Sections (inside a parent page)"},{"location":"docs/monographs/squarespace_patterns/#template-management","text":"jsont.squarespace.com json-t basics json-t advanced developers.squarespace.com what is json-t json-t system variables json-t predicates json-t directive json-t formatters json-t helpers custom Query tag for collection querying answers.squarespace.com disambiguating {.if} and {.equal} custom layout for individual page","title":"Template Management"},{"location":"docs/monographs/squarespace_patterns/#user-editable-sections","text":"In order to allow to clients to edit their pages in a coherent way, it is necessary to use index pages to combine each editable page into one 'main page'. In order to aggregate pages and collections, use an index at the top level, and use folders at subordinate levels. Folders & Indexes are the mechanism for building custom aggregate pages. Custom Index Page Anchor Links in Index Pages - may or may not be important One pattern is to have headers and paragraphs of text interleaved with sections of content, for example project pages with a grid of images or a grid of logos, or a grid of contributors. An effective pattern for working with this may be to have one collection of paragraphs and titles which are specifically indexed in teh template. These are interleaved with actual collection sections which loop over each item in the collection to populate the segment. Template Partials break up sections so Squarespace users can edit them. Example: A simple 'blog post' section. Display any number of vertical paragraphs and images in any order. Squarespace Query: Access collection Data from another page A method for giving the user some edit control over a custom template.","title":"User-editable sections"},{"location":"docs/monographs/squarespace_patterns/#managing-templates","text":"Layouts & Regions - how to make different page templates for different pages","title":"Managing Templates"},{"location":"docs/monographs/squarespace_patterns/#basic-template-navigation-and-blocks","text":"Beginner Tutorial - good intro to nav and code blocks. A little unclear at times. blocks/navigation.block was not being detected. I renamed it to blocks/nav.block and changed the reference to it to 'nav'.","title":"Basic Template, Navigation, and Blocks"},{"location":"docs/monographs/ssd_vs_hdd_2023/","text":"SSD vs HDD Optimal thing is to use what I already have and optimize my current data usage. Cost per TB-Year Assume drive is pretty much always spun up (ZFS or mirroring). Assume SSD idle cost is $0, aka $3/decade ~= .1/1000 24 365 .34 10` Assume cost of watts is constant with inflation for the next decade, and we are working in 2023-dollars. 6 idle Watts-hours per hard drive == 6/1000 KWH / HDD 1 HDD * 8 Years == 6/1000 KWH/HDD * 24 hours/day * 365 days/year * 8 years == 420 KWH 420 KWH * 0.34/KWH = $142.80 lifetime cost $322.80 / 18TB HDD @ 8 year lifetime == $322.80 / 144 TB-YEAR == $2.24/TB-YEAR $150 / 4TB SSD @ 10 year lifetime == $150 / 40 TB-YEAR == $3.75/TB-YEAR GPT-4 Analyzes the requirements Here's the final setup: Data Type Storage Type Capacity Location Special Functionality Gaming Data M.2 NVMe SSD 2TB Gaming Computer N/A Business Data M.2 NVMe SSD and 2.5\" SSD in ZFS (mirroring) 4TB Lenovo ThinkCentre M910q ZFS for data redundancy, Always-on Media Data HDD in USB-C Enclosure 8TB Connected to Lenovo ThinkCentre M910q N/A GPT-3 Recommendation: Use a external USB HDD enclosure with a smart plug, orchestrate unpowering the smart plug with unmounting the device via bash script Problem: Enclosures mainly do not power on when repowered, because they don't have mechanical switches. Googled solution: However, external drive bays often do. I already have 1, but it doesn't seem great for constant use... I will prototype with it.","title":"Ssd Vs Hdd 2023"},{"location":"docs/monographs/ssd_vs_hdd_2023/#ssd-vs-hdd","text":"Optimal thing is to use what I already have and optimize my current data usage.","title":"SSD vs HDD"},{"location":"docs/monographs/ssd_vs_hdd_2023/#cost-per-tb-year","text":"Assume drive is pretty much always spun up (ZFS or mirroring). Assume SSD idle cost is $0, aka $3/decade ~= .1/1000 24 365 .34 10` Assume cost of watts is constant with inflation for the next decade, and we are working in 2023-dollars. 6 idle Watts-hours per hard drive == 6/1000 KWH / HDD 1 HDD * 8 Years == 6/1000 KWH/HDD * 24 hours/day * 365 days/year * 8 years == 420 KWH 420 KWH * 0.34/KWH = $142.80 lifetime cost $322.80 / 18TB HDD @ 8 year lifetime == $322.80 / 144 TB-YEAR == $2.24/TB-YEAR $150 / 4TB SSD @ 10 year lifetime == $150 / 40 TB-YEAR == $3.75/TB-YEAR","title":"Cost per TB-Year"},{"location":"docs/monographs/ssd_vs_hdd_2023/#gpt-4-analyzes-the-requirements","text":"Here's the final setup: Data Type Storage Type Capacity Location Special Functionality Gaming Data M.2 NVMe SSD 2TB Gaming Computer N/A Business Data M.2 NVMe SSD and 2.5\" SSD in ZFS (mirroring) 4TB Lenovo ThinkCentre M910q ZFS for data redundancy, Always-on Media Data HDD in USB-C Enclosure 8TB Connected to Lenovo ThinkCentre M910q N/A GPT-3 Recommendation: Use a external USB HDD enclosure with a smart plug, orchestrate unpowering the smart plug with unmounting the device via bash script Problem: Enclosures mainly do not power on when repowered, because they don't have mechanical switches. Googled solution: However, external drive bays often do. I already have 1, but it doesn't seem great for constant use... I will prototype with it.","title":"GPT-4 Analyzes the requirements"},{"location":"docs/monographs/taking_notes_on_books/","text":"How to take notes on books Reading and taking notes on books is time consuming and many concepts exist for making the first time you read something the last time. Review these resources 1 2 3 Goals Read comprehensively the first time and ensure that key information is ingested. My Method As you read, take notes in an outline. Allow the outline to take its own form. Use supporting information. Short Summaries Key Quotes Page Numbers References Transcribe the outline into a markdown file. Enhance the supporting information and create a references section. Additional Resources How to Read a Book by Mortimer Adler Wikipedia: Reading (Process)","title":"Taking Notes On Books"},{"location":"docs/monographs/taking_notes_on_books/#how-to-take-notes-on-books","text":"Reading and taking notes on books is time consuming and many concepts exist for making the first time you read something the last time.","title":"How to take notes on books"},{"location":"docs/monographs/taking_notes_on_books/#review-these-resources","text":"1 2 3","title":"Review these resources"},{"location":"docs/monographs/taking_notes_on_books/#goals","text":"Read comprehensively the first time and ensure that key information is ingested.","title":"Goals"},{"location":"docs/monographs/taking_notes_on_books/#my-method","text":"As you read, take notes in an outline. Allow the outline to take its own form. Use supporting information. Short Summaries Key Quotes Page Numbers References Transcribe the outline into a markdown file. Enhance the supporting information and create a references section.","title":"My Method"},{"location":"docs/monographs/taking_notes_on_books/#additional-resources","text":"How to Read a Book by Mortimer Adler Wikipedia: Reading (Process)","title":"Additional Resources"},{"location":"docs/monographs/threat_model_test_cases/","text":"Possible Information Attacks for Threat-Model Building This is an aggregation of potential information-based attacks. This list should always be growing. These attacks should be considered when building a threat model for information defense. General Information Attacks Spying by communications and content delivery engines for sale to advertisers. Types of agencies (expand and reorganize) Verizon, AT&T, Sprint, PCS, Comcast, Sonic, CDN Services Internet level traffic (upstream of digital ocean) Digital Ocean, AWS, storage and compute providers Business Espionage Small business espionage cryptolocker Big Business on Small Business high level coordination between content storage services (gmail) and related companies (Alphabet) to use competitor data for markets of interest Amazon, Google, Microsoft Targeted Information Attacks Device tampering Loss of control over physical device Organizations tampering with physical device before transfer of ownership Lenovo + Superfish Any government tampering Intel ME Coercive power Organizations are always in a legal jurisdiction Organizations have parent companies Reddit + Conde Nast","title":"Threat Model Test Cases"},{"location":"docs/monographs/threat_model_test_cases/#possible-information-attacks-for-threat-model-building","text":"This is an aggregation of potential information-based attacks. This list should always be growing. These attacks should be considered when building a threat model for information defense.","title":"Possible Information Attacks for Threat-Model Building"},{"location":"docs/monographs/threat_model_test_cases/#general-information-attacks","text":"Spying by communications and content delivery engines for sale to advertisers. Types of agencies (expand and reorganize) Verizon, AT&T, Sprint, PCS, Comcast, Sonic, CDN Services Internet level traffic (upstream of digital ocean) Digital Ocean, AWS, storage and compute providers Business Espionage Small business espionage cryptolocker Big Business on Small Business high level coordination between content storage services (gmail) and related companies (Alphabet) to use competitor data for markets of interest Amazon, Google, Microsoft","title":"General Information Attacks"},{"location":"docs/monographs/threat_model_test_cases/#targeted-information-attacks","text":"Device tampering Loss of control over physical device Organizations tampering with physical device before transfer of ownership Lenovo + Superfish Any government tampering Intel ME Coercive power Organizations are always in a legal jurisdiction Organizations have parent companies Reddit + Conde Nast","title":"Targeted Information Attacks"},{"location":"docs/praxes/audio_to_wav_via_ffmpeg/","text":"Convert audio to 1 channel wav for DeepSpeech It is remarkable that recording sound is the hard part of DeepSpeech. With deepspeech installed in a virtualenv , do the following. Recording audio macos: get a m4a format audio with quicktime Use ffmpeg Get ffmpeg: brew install ffmpeg or apt install ffmpeg Convert to single channel 192kbps: $ ffmpeg -i ~/Desktop/test_audio.m4a -ac 1 -ab 192k ~/Desktop/test.wav Run the demo: deepspeech models/output_graph.pb ~/Desktop/test.wav models/alphabet.txt","title":"Audio To Wav Via Ffmpeg"},{"location":"docs/praxes/audio_to_wav_via_ffmpeg/#convert-audio-to-1-channel-wav-for-deepspeech","text":"It is remarkable that recording sound is the hard part of DeepSpeech. With deepspeech installed in a virtualenv , do the following.","title":"Convert audio to 1 channel wav for DeepSpeech"},{"location":"docs/praxes/audio_to_wav_via_ffmpeg/#recording-audio","text":"macos: get a m4a format audio with quicktime","title":"Recording audio"},{"location":"docs/praxes/audio_to_wav_via_ffmpeg/#use-ffmpeg","text":"Get ffmpeg: brew install ffmpeg or apt install ffmpeg Convert to single channel 192kbps: $ ffmpeg -i ~/Desktop/test_audio.m4a -ac 1 -ab 192k ~/Desktop/test.wav Run the demo: deepspeech models/output_graph.pb ~/Desktop/test.wav models/alphabet.txt","title":"Use ffmpeg"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/","text":"Backup Management with S3 Glacier The most economical bulk offsite storage for a few terabytes of data in 2022 is AWS S3 Glacier Flexible Retrieval with bulk data retrieval. The bulk retrieval parameter must be specified during data restore and will take up to 12 hours for retrieval. Note: Glacier deep archive could be 10x more economical but carries risks. Bulk restore costs are 0.025 per 1000 objects and 0.0025 per GB. Future: Model glacier deep archive costs. 10x cheaper is huge. If objects can be reduced by using zip, then this would only cost about $2.50 per terabyte. How to set up a bucket with glacier TODO, did this manually in the past, write a terraform module. How to restore all objects in a bucket There is no recursive restore option. Restore must be implemented. The following implementation was tested separately but not as a single script as below. Parallelism can probably be increased, consider logging object name each attempt to stdout as well The flag --restore-priority=bulk was also not tested but will save cost so has been added. #!/bin/bash set +ex # Execute this script and capture errors to a file, then grep the file for error types # ./restore-glacier-object-list.sh > restore-results-my-bucket.txt 2>&1 BUCKETNAME = \"my-bucket\" # grep this file for NoSuchKey or other errors FILENAME = \"glacier-restore- $BUCKETNAME .txt\" # read all the glacier object paths and store them in a file, one line per object aws s3api list-objects-v2 --bucket $BUCKETNAME --query \"Contents[?StorageClass=='GLACIER']\" --output text | awk 'BEGIN {FS=\"\\t\"}; {print $2}' > $FILENAME # consume the file, this parallelism cap is defensive to avoid too many concurrent requests to aws, consider much more, perhaps 10x as many if your machine will support it. parallel -j 30 -q -a $FILENAME aws s3api restore-object --restore-request Days = 7 --restore-priority = bulk --bucket \" $BUCKETNAME \" --key \"{}\" How to download a restored object After 12 hours, all objects are guaranteed (by AWS) restored. This is for \"bulk\" retrieval, as depicted above. The flag --force-glacier-transfer must be used to download objects with aws cli. Verify files or add new files to the bucket: s3 sync with the existing bucket These 2 operations will verify the size and timestamp parameters match. WARNING: Sync is destructive for the destination if the timestamp is older or the size is incorrect. Format below is . Below, we first sync to the bucket, then we sync from the bucket. This considers any local change should overwrite or update new objects to the bucket, then the second command downloads objects that are in the bucket that don't exist locally. cd my-bucket; aws s3 sync --force-glacier-transfer . s3://my-bucket cd my-bucket; aws s3 sync --force-glacier-transfer s3://my-bucket . Note: You may wish to use the flag --size-only if files repeatedly transfer. There is a documented bug in some related to filenames with special characters causing files to resync, and timestamps are typically not relevant if size is the same size for backups and backups flow into the backup space from user space, although not universally true, especially if you have multiple user spaces flowing into a backup that need reconciled. Sync new files to the bucket without considering glacier objects Typically archive updates are additive, so we don't want to affect what's already in the archive. It saves time and prevents errors to avoid enumerating what was changed, so aws s3 sync is preferred. This cd my-bucket; aws s3 sync . s3://my-bucket --size-only --size-only is optional, it excludes date comparison. This helps avoid accidental updates if your local files have a date change without content change Deleting from a bucket with sync NOT RECOMMENDED for operating on buckets that contain source of truth (only use for cache buckets). Consider deleting the individual objects using s3 rm instead of trying to delete with sync. Deleting with sync is very dangerous because it removes any files in that are not in . before removing the files from local, sync from the bucket to local. Otherwise files added to the bucket from somewhere else would be deleted, since they aren't yet in local. remove the desired files from local run another s3 sync with the --delete flag. WARNING, this could delete any remote file not on your local. Not advised for backup operations.","title":"Backup Mgmt With S3 Glacier"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#backup-management-with-s3-glacier","text":"The most economical bulk offsite storage for a few terabytes of data in 2022 is AWS S3 Glacier Flexible Retrieval with bulk data retrieval. The bulk retrieval parameter must be specified during data restore and will take up to 12 hours for retrieval. Note: Glacier deep archive could be 10x more economical but carries risks. Bulk restore costs are 0.025 per 1000 objects and 0.0025 per GB. Future: Model glacier deep archive costs. 10x cheaper is huge. If objects can be reduced by using zip, then this would only cost about $2.50 per terabyte.","title":"Backup Management with S3 Glacier"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#how-to-set-up-a-bucket-with-glacier","text":"TODO, did this manually in the past, write a terraform module.","title":"How to set up a bucket with glacier"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#how-to-restore-all-objects-in-a-bucket","text":"There is no recursive restore option. Restore must be implemented. The following implementation was tested separately but not as a single script as below. Parallelism can probably be increased, consider logging object name each attempt to stdout as well The flag --restore-priority=bulk was also not tested but will save cost so has been added. #!/bin/bash set +ex # Execute this script and capture errors to a file, then grep the file for error types # ./restore-glacier-object-list.sh > restore-results-my-bucket.txt 2>&1 BUCKETNAME = \"my-bucket\" # grep this file for NoSuchKey or other errors FILENAME = \"glacier-restore- $BUCKETNAME .txt\" # read all the glacier object paths and store them in a file, one line per object aws s3api list-objects-v2 --bucket $BUCKETNAME --query \"Contents[?StorageClass=='GLACIER']\" --output text | awk 'BEGIN {FS=\"\\t\"}; {print $2}' > $FILENAME # consume the file, this parallelism cap is defensive to avoid too many concurrent requests to aws, consider much more, perhaps 10x as many if your machine will support it. parallel -j 30 -q -a $FILENAME aws s3api restore-object --restore-request Days = 7 --restore-priority = bulk --bucket \" $BUCKETNAME \" --key \"{}\"","title":"How to restore all objects in a bucket"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#how-to-download-a-restored-object","text":"After 12 hours, all objects are guaranteed (by AWS) restored. This is for \"bulk\" retrieval, as depicted above. The flag --force-glacier-transfer must be used to download objects with aws cli.","title":"How to download a restored object"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#verify-files-or-add-new-files-to-the-bucket-s3-sync-with-the-existing-bucket","text":"These 2 operations will verify the size and timestamp parameters match. WARNING: Sync is destructive for the destination if the timestamp is older or the size is incorrect. Format below is . Below, we first sync to the bucket, then we sync from the bucket. This considers any local change should overwrite or update new objects to the bucket, then the second command downloads objects that are in the bucket that don't exist locally. cd my-bucket; aws s3 sync --force-glacier-transfer . s3://my-bucket cd my-bucket; aws s3 sync --force-glacier-transfer s3://my-bucket . Note: You may wish to use the flag --size-only if files repeatedly transfer. There is a documented bug in some related to filenames with special characters causing files to resync, and timestamps are typically not relevant if size is the same size for backups and backups flow into the backup space from user space, although not universally true, especially if you have multiple user spaces flowing into a backup that need reconciled.","title":"Verify files or add new files to the bucket: s3 sync with the existing bucket"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#sync-new-files-to-the-bucket-without-considering-glacier-objects","text":"Typically archive updates are additive, so we don't want to affect what's already in the archive. It saves time and prevents errors to avoid enumerating what was changed, so aws s3 sync is preferred. This cd my-bucket; aws s3 sync . s3://my-bucket --size-only --size-only is optional, it excludes date comparison. This helps avoid accidental updates if your local files have a date change without content change","title":"Sync new files to the bucket without considering glacier objects"},{"location":"docs/praxes/backup_mgmt_with_s3_glacier/#deleting-from-a-bucket-with-sync","text":"NOT RECOMMENDED for operating on buckets that contain source of truth (only use for cache buckets). Consider deleting the individual objects using s3 rm instead of trying to delete with sync. Deleting with sync is very dangerous because it removes any files in that are not in . before removing the files from local, sync from the bucket to local. Otherwise files added to the bucket from somewhere else would be deleted, since they aren't yet in local. remove the desired files from local run another s3 sync with the --delete flag. WARNING, this could delete any remote file not on your local. Not advised for backup operations.","title":"Deleting from a bucket with sync"},{"location":"docs/praxes/budget-building-101/","text":"Budget Building 101 An introductory course on building a budget in Google Sheets. You can modify the included template for your own budget, try to avoid changing the calculations in some of the cells. The template assumes a monthly income of $4092 based on a pretax salary of $70,000. The income does not take into account the 2 months you get 3 paychecks (26 paychecks in a 52 week year). If you want to include the two extra checks in your choice making, simply take your salary after tax and divide it by 12. Figuring tax is annoying but you can figure it from your paycheck by taking your hourly earnings * hours and subtracting what you were actually paid. This is approximately your tax rate, but is not fully accurate. It also includes certain things your company gives you that are considered 'income', like a life insurance policy with them as the beneficiary that you pay for. That's late stage capitalism! Template Click the link to view the template. Make yourself a copy of this sheet and work from your copy. https://docs.google.com/spreadsheets/d/1YHzrjfVjtNEITDNScakGoeyWAFbc789iKEZDwCndXn0/edit?usp=sharing Incomplete How To You can adjust this document to fit your needs, mostly adding new lines and deleting items you do not need. Make sure to copy and paste the calculations that go on each line. Make yourself a copy of the google sheet template listed in the Template section. Add your income Multiply your BIWEEKLY paycheck by 2 and put it in the monthly income box. Add your expenses Use your debit card and credit card records Review your checking account Save receipts and enter them into the Transaction Log Optional to calculate unknown spends. Your expenses might be fixed or variable . If it changes, just do your best. Be as accurate as your decisions need you to be. Review and keep adding expenses (forever) The budget is a living document you should review regularly as a habit. I review my budget when I get paid or before I consider a medium to large purchase. Budget Categories I used some categories in the spreadsheet: Core Budget Spend rent, electric, internet, water, phone, prescriptions, transit to work Debt Spend Student loans, credit cards, QUANTIFY IT Savings Spend Save a little, you will need it Helps in employment negotiations too... you can afford to say no to a bad offer... Hygeine Spend Gotta brush those teeth Subscriptions Spend Netflix, Hulu, Spotify, New York Times, etc. Nonessential Spend Fun, uber/lyft, transit to fun, nail salon, etc. Some things listed above can have an essential component What if you have to uber to work because you would be late? goes in essential spend as a seperate uber line item than 'fun and nonessential' De-Annualized Spend Annual or non-monthly events - flights home, non-routine dr visits. Donations Spend Noisebridge, EFF, etc. Making Spending Judgments If something is a high percent of my income, I try to bring it down. There are different strategies for everything, it usually just comes down to two things: Adjust your habits Eating a $12 lunch at work every day costs $3120 per year - pack your lunch - or quit... just kidding Find more things like this, especially daily or weekly habits that cost you. Shop Around Stop buying books and games and instead make a list of what you already have, read the top priority on that Transaction Log You can play around with this. It also helps to have different transaction logs for different categories. Don't let perfect be the enemy of good, it is hard to capture everything, be approximate where necessary, get precise if it is a big part of your budget. I recommend doing it for at least a few months by saving every single receipt. It will help you capture more interesting budget line items that you use every day like 'deoderant', 'toothpaste', 'dish soap'. As you start to track your spend, you might find more reasons to buy things in bulk as your finances allow, as the savings will be more apparent. No more 4 ounce bottles of dish soap at the bodega.","title":"Budget Building 101"},{"location":"docs/praxes/budget-building-101/#budget-building-101","text":"An introductory course on building a budget in Google Sheets. You can modify the included template for your own budget, try to avoid changing the calculations in some of the cells. The template assumes a monthly income of $4092 based on a pretax salary of $70,000. The income does not take into account the 2 months you get 3 paychecks (26 paychecks in a 52 week year). If you want to include the two extra checks in your choice making, simply take your salary after tax and divide it by 12. Figuring tax is annoying but you can figure it from your paycheck by taking your hourly earnings * hours and subtracting what you were actually paid. This is approximately your tax rate, but is not fully accurate. It also includes certain things your company gives you that are considered 'income', like a life insurance policy with them as the beneficiary that you pay for. That's late stage capitalism!","title":"Budget Building 101"},{"location":"docs/praxes/budget-building-101/#template","text":"Click the link to view the template. Make yourself a copy of this sheet and work from your copy. https://docs.google.com/spreadsheets/d/1YHzrjfVjtNEITDNScakGoeyWAFbc789iKEZDwCndXn0/edit?usp=sharing","title":"Template"},{"location":"docs/praxes/budget-building-101/#incomplete-how-to","text":"You can adjust this document to fit your needs, mostly adding new lines and deleting items you do not need. Make sure to copy and paste the calculations that go on each line. Make yourself a copy of the google sheet template listed in the Template section. Add your income Multiply your BIWEEKLY paycheck by 2 and put it in the monthly income box. Add your expenses Use your debit card and credit card records Review your checking account Save receipts and enter them into the Transaction Log Optional to calculate unknown spends. Your expenses might be fixed or variable . If it changes, just do your best. Be as accurate as your decisions need you to be. Review and keep adding expenses (forever) The budget is a living document you should review regularly as a habit. I review my budget when I get paid or before I consider a medium to large purchase.","title":"Incomplete How To"},{"location":"docs/praxes/budget-building-101/#budget-categories","text":"I used some categories in the spreadsheet: Core Budget Spend rent, electric, internet, water, phone, prescriptions, transit to work Debt Spend Student loans, credit cards, QUANTIFY IT Savings Spend Save a little, you will need it Helps in employment negotiations too... you can afford to say no to a bad offer... Hygeine Spend Gotta brush those teeth Subscriptions Spend Netflix, Hulu, Spotify, New York Times, etc. Nonessential Spend Fun, uber/lyft, transit to fun, nail salon, etc. Some things listed above can have an essential component What if you have to uber to work because you would be late? goes in essential spend as a seperate uber line item than 'fun and nonessential' De-Annualized Spend Annual or non-monthly events - flights home, non-routine dr visits. Donations Spend Noisebridge, EFF, etc.","title":"Budget Categories"},{"location":"docs/praxes/budget-building-101/#making-spending-judgments","text":"If something is a high percent of my income, I try to bring it down. There are different strategies for everything, it usually just comes down to two things: Adjust your habits Eating a $12 lunch at work every day costs $3120 per year - pack your lunch - or quit... just kidding Find more things like this, especially daily or weekly habits that cost you. Shop Around Stop buying books and games and instead make a list of what you already have, read the top priority on that","title":"Making Spending Judgments"},{"location":"docs/praxes/budget-building-101/#transaction-log","text":"You can play around with this. It also helps to have different transaction logs for different categories. Don't let perfect be the enemy of good, it is hard to capture everything, be approximate where necessary, get precise if it is a big part of your budget. I recommend doing it for at least a few months by saving every single receipt. It will help you capture more interesting budget line items that you use every day like 'deoderant', 'toothpaste', 'dish soap'. As you start to track your spend, you might find more reasons to buy things in bulk as your finances allow, as the savings will be more apparent. No more 4 ounce bottles of dish soap at the bodega.","title":"Transaction Log"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/","text":"Guide for using the Jupyter datascience-notebook with Docker (brew must be installed; cask must be installed) brew cask install docker Quick References I guess what I would really like is one of these with sage math? Guide covers this notebook Jupyter Notebook 5.2.x Conda Python 3.x environment pandas, matplotlib, scipy, seaborn, scikit-learn, scikit-image, sympy, cython, patsy, statsmodel, cloudpickle, dill, numba, bokeh pre-installed Conda R v3.3.x and channel plyr, devtools, shiny, rmarkdown, forecast, rsqlite, reshape2, nycflights13, caret, rcurl, and randomforest pre-installed The tidyverse R packages are also installed, including ggplot2, dplyr, tidyr, readr, purrr, tibble, stringr, lubridate, and broom Julia v0.6.x with Gadfly, RDatasets and HDF5 pre-installed Unprivileged user jovyan (uid=1000, configurable, see options) in group users (gid=100) with ownership over /home/jovyan and /opt/conda tini as the container entrypoint and start-notebook.sh as the default command A start-singleuser.sh script useful for running a single-user instance of the Notebook server, as required by JupyterHub A start.sh script useful for running alternative commands in the container (e.g. ipython, jupyter kernelgateway, jupyter lab) Jupyter Notebook Shortcuts Steps I recommend doing this from your home internet. It is about 2 GB. brew cask install docker run docker (open spotlight search or press CMD+space, and type docker) docker should be running in the top bar of the mac docker pull jupyter/datascience-notebook . (2 GB) docker images - see what's installed docker run -p 8888:8888 jupyter/datascience-notebook Go to the URL it spits out (in iterm you can command+click the URL to open it in your browser) Part II ssh into your docker container. docker ps get the name of your container docker exec -it /bin/bash use generically: `docker exec -it that home directory seems to be where notebooks go or something i put a text file in jovyan@e47f8b66eea3:~/work/ and could see it Resources This is based on the docker-stacks The following is a summary of the linked diagram. The diagram is a superior explanation. Docker stacks are very interesting: 1. tensorflow-notebook 1. datascience-notebook 1. pyspark-notebook --> all-spark-notebook All these notebooks are based on the scipy-notebook , which is ubuntu base-notebook based. (And all descend from minimal-notebook ). There is a separate r-notebook found on this list of notebooks: https://hub.docker.com/r/jupyter/notebook/ i did not review all the docker containers that jupyter manages https://hub.docker.com/u/jupyter/ Planet Labs maintains notebooks too! https://github.com/planetlabs/notebooks","title":"Docker Jupyter Datasciencenotebook"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#guide-for-using-the-jupyter-datascience-notebook-with-docker","text":"(brew must be installed; cask must be installed) brew cask install docker","title":"Guide for using the Jupyter datascience-notebook with Docker"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#quick-references","text":"I guess what I would really like is one of these with sage math? Guide covers this notebook Jupyter Notebook 5.2.x Conda Python 3.x environment pandas, matplotlib, scipy, seaborn, scikit-learn, scikit-image, sympy, cython, patsy, statsmodel, cloudpickle, dill, numba, bokeh pre-installed Conda R v3.3.x and channel plyr, devtools, shiny, rmarkdown, forecast, rsqlite, reshape2, nycflights13, caret, rcurl, and randomforest pre-installed The tidyverse R packages are also installed, including ggplot2, dplyr, tidyr, readr, purrr, tibble, stringr, lubridate, and broom Julia v0.6.x with Gadfly, RDatasets and HDF5 pre-installed Unprivileged user jovyan (uid=1000, configurable, see options) in group users (gid=100) with ownership over /home/jovyan and /opt/conda tini as the container entrypoint and start-notebook.sh as the default command A start-singleuser.sh script useful for running a single-user instance of the Notebook server, as required by JupyterHub A start.sh script useful for running alternative commands in the container (e.g. ipython, jupyter kernelgateway, jupyter lab) Jupyter Notebook Shortcuts","title":"Quick References"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#steps","text":"I recommend doing this from your home internet. It is about 2 GB. brew cask install docker run docker (open spotlight search or press CMD+space, and type docker) docker should be running in the top bar of the mac docker pull jupyter/datascience-notebook . (2 GB) docker images - see what's installed docker run -p 8888:8888 jupyter/datascience-notebook Go to the URL it spits out (in iterm you can command+click the URL to open it in your browser)","title":"Steps"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#part-ii","text":"ssh into your docker container. docker ps get the name of your container docker exec -it /bin/bash use generically: `docker exec -it that home directory seems to be where notebooks go or something i put a text file in jovyan@e47f8b66eea3:~/work/ and could see it","title":"Part II"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#resources","text":"","title":"Resources"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#this-is-based-on-the-docker-stacks","text":"The following is a summary of the linked diagram. The diagram is a superior explanation. Docker stacks are very interesting: 1. tensorflow-notebook 1. datascience-notebook 1. pyspark-notebook --> all-spark-notebook All these notebooks are based on the scipy-notebook , which is ubuntu base-notebook based. (And all descend from minimal-notebook ). There is a separate r-notebook","title":"This is based on the docker-stacks"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#found-on-this-list-of-notebooks","text":"https://hub.docker.com/r/jupyter/notebook/","title":"found on this list of notebooks:"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#i-did-not-review-all-the-docker-containers-that-jupyter-manages","text":"https://hub.docker.com/u/jupyter/","title":"i did not review all the docker containers that jupyter manages"},{"location":"docs/praxes/docker-jupyter-datasciencenotebook/#planet-labs-maintains-notebooks-too","text":"https://github.com/planetlabs/notebooks","title":"Planet Labs maintains notebooks too!"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/","text":"Ergonomic Assessment from Alameda County Evaluator: Alfonso Mejorado, Associate Ergonomist Company: VSI Risk Management and Ergonomics, Inc. note: same company hired by Genentech Focus The focus of the ergonomic evaluation is my desk work. Problems Radial Deviation and Ulnar Deviation are common issues I face Try not to rest wrists while typing, especially on the far right of the keyboard where I am weak. When I plant my hand while deviating, it causes contact stress at the base of the hand. Seat bucket too deep, pressure on middle of thighs. Seatback greater than 100 degrees moving me away from the desk. Behavioral Corrections When sitting, move forwards: RULE: Elbow, Shoulder, Ear should be VERTICALLY aligned I tend to always move my butt too far back which means my arms have to reach. I do not want to reach with my arms because I end up planting my wrists and hunching my shoulders. Do not plant palms, too much contact stress. Move the mouse as close to center as possible Avoid Right Shoulder Abduction when using the mouse Use TWO possible resting hand positions: Hands resting on 'meat' of hand below pinkie 'extra padding below pinkie` Hands resting in lap (neutral) Do not PLANT the wrist forcefully, especially during radial and ulnar deviation. Try to always free type, I think this means have your wrists up? Or maybe it was free flow type? 90 degree sitting angle is an active posture using the muscles. This is good. 100 degree sitting angle is relaxed but not moving you away from the desk. This is good. Requires seatback to be positioned for 100 degree resting angle. Always put my notebook on the right side so I don't twist when writing and reading from it. Recommended Resting Posture Hands turned in, extra padding below pinkie resting on keyboard rest Shoulders fully at rest on arm wrests Feet planted at 90 degrees on the ground Back at 100 degrees resting on the backrest Do not plant palms. Equipment Fixes Armwrests must not contact the desk (push them back) Otherwise they may prevent me from moving close to the desk. Armwrests should be below my neutral elbow height when typing and just barely high enough to fully REST shoulders when resting hands . Move my coding screen up much higher so it is near the center of my vision Alfonso: \"Coders always work at the bottom of their screen\" This can cause some right neck and shoulder issues (due to turning head and looking down?) Use reams of paper to move the screen up Seatpan is moved as far forward as possible to support the mid thigh and prevent cut-off bloodflow. This is to avoid numbness in the legs and feet. Fix right armrest (this one is broken) Use a \"RFM Internet High-Back Chair\": http://rfmseating.com/portfolio-view/internet/ Mouse is too narrow and activating my finger flexons or something. I am planting my hand while mousing in an ulnar deviation . BAD. Replace mouse with a wider one, Kensington Slim Blade Trackball and a blue mouse slider identical to my Genentech one. Future Fixes (recommendations) Get a \"Workright Electric Sit Stand Desk\" - Needs approved and delivered Repair the right armwrest of the \"RFM Internet High-Back Chair\"","title":"Ergonomic Eval Alameda 20180228"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#ergonomic-assessment-from-alameda-county","text":"Evaluator: Alfonso Mejorado, Associate Ergonomist Company: VSI Risk Management and Ergonomics, Inc. note: same company hired by Genentech","title":"Ergonomic Assessment from Alameda County"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#focus","text":"The focus of the ergonomic evaluation is my desk work.","title":"Focus"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#problems","text":"Radial Deviation and Ulnar Deviation are common issues I face Try not to rest wrists while typing, especially on the far right of the keyboard where I am weak. When I plant my hand while deviating, it causes contact stress at the base of the hand. Seat bucket too deep, pressure on middle of thighs. Seatback greater than 100 degrees moving me away from the desk.","title":"Problems"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#behavioral-corrections","text":"When sitting, move forwards: RULE: Elbow, Shoulder, Ear should be VERTICALLY aligned I tend to always move my butt too far back which means my arms have to reach. I do not want to reach with my arms because I end up planting my wrists and hunching my shoulders. Do not plant palms, too much contact stress. Move the mouse as close to center as possible Avoid Right Shoulder Abduction when using the mouse Use TWO possible resting hand positions: Hands resting on 'meat' of hand below pinkie 'extra padding below pinkie` Hands resting in lap (neutral) Do not PLANT the wrist forcefully, especially during radial and ulnar deviation. Try to always free type, I think this means have your wrists up? Or maybe it was free flow type? 90 degree sitting angle is an active posture using the muscles. This is good. 100 degree sitting angle is relaxed but not moving you away from the desk. This is good. Requires seatback to be positioned for 100 degree resting angle. Always put my notebook on the right side so I don't twist when writing and reading from it.","title":"Behavioral Corrections"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#recommended-resting-posture","text":"Hands turned in, extra padding below pinkie resting on keyboard rest Shoulders fully at rest on arm wrests Feet planted at 90 degrees on the ground Back at 100 degrees resting on the backrest Do not plant palms.","title":"Recommended Resting Posture"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#equipment-fixes","text":"Armwrests must not contact the desk (push them back) Otherwise they may prevent me from moving close to the desk. Armwrests should be below my neutral elbow height when typing and just barely high enough to fully REST shoulders when resting hands . Move my coding screen up much higher so it is near the center of my vision Alfonso: \"Coders always work at the bottom of their screen\" This can cause some right neck and shoulder issues (due to turning head and looking down?) Use reams of paper to move the screen up Seatpan is moved as far forward as possible to support the mid thigh and prevent cut-off bloodflow. This is to avoid numbness in the legs and feet. Fix right armrest (this one is broken) Use a \"RFM Internet High-Back Chair\": http://rfmseating.com/portfolio-view/internet/ Mouse is too narrow and activating my finger flexons or something. I am planting my hand while mousing in an ulnar deviation . BAD. Replace mouse with a wider one, Kensington Slim Blade Trackball and a blue mouse slider identical to my Genentech one.","title":"Equipment Fixes"},{"location":"docs/praxes/ergonomic-eval-alameda-20180228/#future-fixes-recommendations","text":"Get a \"Workright Electric Sit Stand Desk\" - Needs approved and delivered Repair the right armwrest of the \"RFM Internet High-Back Chair\"","title":"Future Fixes (recommendations)"},{"location":"docs/praxes/exercise-calories-burning-reference/","text":"Calories General guide to calorie facts. You use your bmr to determine how many calories you can eat. There is a variance of 25% between individuals so you basically MUST build an empirical baseline for yourself. Start at the low end of your calorie intake for a few weeks, then slightly adjust to achieve your ideal weight loss based on calorie expense. You should lose 1-2 lbs, but more importantly, that should be pretty consistent each week (aka NOT 1.2 lb then 1.8 lb then back to 1.2 lb). How many calories do I burn in a day? Calorimetry Device Online BMR tests with rigid formulas are not the most accurate method of determining an individual's BMR. It is better to consult a certified specialist or measure BMR through a calorimetry device. These handheld devices are available in many health and fitness clubs, doctor offices, and weight-loss clinics. \"Do Hand-held Calorimeters Have a Role in Assessment of Nutrition Needs in Hospitalized Patients? A Systematic Review of Literature\" Results from a hand-held calorimeter were similar to those obtained from metabolic cart studies. The Douglas bag method compared to the MedGem indicated a significant agreement with a p=0.286. The hand-held device compared to metabolic carts in 9 studies with mixed results. The predictive equations (Harris-Benedict, Mifflin St. Joer and FAO/WHO equations) were found to over and underestimate RMR compared to the MedGem. The Harris-Benedict was found to overestimate the RMR by 3-11%, the Mifflin St Joer equation overestimated the RMR by 1% and the FAO/WHO equation overestimated RMR by 12%. Total energy expenditure (TEE) consists of three major components: basal metabolic rate (BMR), thermogenic effect of food, and the effect of physical activity or exercise.1 Basal metabolic rate is defined as the measurement of resting energy expenditure under the following conditions: a state of complete rest, ambient temperature is between 68\u00b0 to 77\u00b0 Fahrenheit. The subject is tested immediately upon waking after a minimum of a four hour sleep and in a post-absorptive state (12 hours after a meal). Thermogenic effect of food refers to the heat the body generates as food is digested. Physical activity is any activity in which work is performed which results in an increase in metabolic rate. Resting metabolic rate (RMR), which is synonymous with resting energy expenditure (REE), is not measured under basal conditions. It is a measurement taken during a fast (two to four hours after a meal) and allows for some movement with a rest period prior to testing.1,2 The RMR is usually higher than the BMR due to less restrictive conditions for measureing RMR. Therefore, basal metabolic rate accounts for 60- 75% 1 of TEE while RMR accounts for 50-70% of TEE.. Since the difference between BMR and RMR is only about 10%, it is more practical to measure RMR in a clinical setting.2 In clinical settings RMR is used to determine accurate energy expenditure of a patient's caloric needs. Resting metabolic rate can be measured either directly or indirectly. trent: the medgem seems fine until you have any deviation from normal including old age - see the details inside the study... Harris-Benedict Formula Calculator.net Calculations Muscle Mass \u2013 Aerobic exercise such as running or cycling has no effect on BMR. However, anaerobic exercise, such as weight-lifting, indirectly leads to a higher BMR because it builds muscle mass, increasing resting energy consumption. The more muscle mass in the physical composition of an individual, the higher the BMR required to sustain their body at a certain level. my bmr: 1955 calories / day calculator.net bmr calculator men: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) + 5 women: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) - 161 Why do you just subtract a constant from the men's BMR to get the womens' BMR? This seems like bullshit. My Calorie Calculator Using this calculator.net calculator 3031 calories to maintain weight 2531 calories to lose 1 lb per week 2031 calories to lose 2 lb per week How do I think about this? Well, the BMR calculator said 1955, so 2031 - 1955 = 76 excess calories before factoring in exercise. The resting exercise state is 1.2x and my moderately active state is 1.55x. 1.55-1.2 = 0.35x. 1955 * 0.35x = 684 calories/day spent to exercise related behavior My Ideal Weight Using this calculator.net calculator Based on the Robinson formula (1983), your ideal weight is 177.5 lbs Based on the Miller formula (1983), your ideal weight is 170.5 lbs Based on the Devine formula (1974), your ideal weight is 186.3 lbs Based on the Hamwi formula (1964), your ideal weight is 195.1 lbs Based on the healthy BMI recommendation, your recommended weight is 148.0 lbs - 200.0 lbs Healthline calculations based on: https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula BMR: Basal Metabolic Rate Sex, Age, Weight men: 66 + 6.2 x weight + 12.7 x height + 6.76 x age = BMR for men women: 655.1 + 4.35 x weight + 4.7 x height + 4.7 x age = BMR for women This is insane so a person with more fat needs more calories? shouldn't it be by lean bodymass? An older person needs 50 more calories per decade?? trent: 66 + 6.2 x 205 lbs + 12.7 x (12 x 6 + 3) + 6.76 x 34 = 66 + 1271 + 952.5 + 229.84 = 2519.34 activity level is moderately active (mod exercise 3-5 days per week) but I do hard exercise 3-5 days per week... which there is no choice for... kinda bullshit so you can only exercise hard 6-7 days per week... but, the difference is 1.55 versus 1.725 so i could fudge this constant easily... total calories = 2519.34 * 1.55 = 3904.98 calores per day This is truly insane and I have no faith in this number BMR Effects Cold environments raise BMR, external heat raises BMR (body trends towards homeostasis) Starvation reduces BMR negatively impacting weight loss -- along with many negative effects: physical, psychological, permanent damage Caffeine is supposed to raise BMR References If there are inconsistencies, prefer better vetted literature. Use more than one source for all facts! https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula","title":"Exercise Calories Burning Reference"},{"location":"docs/praxes/exercise-calories-burning-reference/#calories","text":"General guide to calorie facts. You use your bmr to determine how many calories you can eat. There is a variance of 25% between individuals so you basically MUST build an empirical baseline for yourself. Start at the low end of your calorie intake for a few weeks, then slightly adjust to achieve your ideal weight loss based on calorie expense. You should lose 1-2 lbs, but more importantly, that should be pretty consistent each week (aka NOT 1.2 lb then 1.8 lb then back to 1.2 lb).","title":"Calories"},{"location":"docs/praxes/exercise-calories-burning-reference/#how-many-calories-do-i-burn-in-a-day","text":"","title":"How many calories do I burn in a day?"},{"location":"docs/praxes/exercise-calories-burning-reference/#calorimetry-device","text":"Online BMR tests with rigid formulas are not the most accurate method of determining an individual's BMR. It is better to consult a certified specialist or measure BMR through a calorimetry device. These handheld devices are available in many health and fitness clubs, doctor offices, and weight-loss clinics. \"Do Hand-held Calorimeters Have a Role in Assessment of Nutrition Needs in Hospitalized Patients? A Systematic Review of Literature\" Results from a hand-held calorimeter were similar to those obtained from metabolic cart studies. The Douglas bag method compared to the MedGem indicated a significant agreement with a p=0.286. The hand-held device compared to metabolic carts in 9 studies with mixed results. The predictive equations (Harris-Benedict, Mifflin St. Joer and FAO/WHO equations) were found to over and underestimate RMR compared to the MedGem. The Harris-Benedict was found to overestimate the RMR by 3-11%, the Mifflin St Joer equation overestimated the RMR by 1% and the FAO/WHO equation overestimated RMR by 12%. Total energy expenditure (TEE) consists of three major components: basal metabolic rate (BMR), thermogenic effect of food, and the effect of physical activity or exercise.1 Basal metabolic rate is defined as the measurement of resting energy expenditure under the following conditions: a state of complete rest, ambient temperature is between 68\u00b0 to 77\u00b0 Fahrenheit. The subject is tested immediately upon waking after a minimum of a four hour sleep and in a post-absorptive state (12 hours after a meal). Thermogenic effect of food refers to the heat the body generates as food is digested. Physical activity is any activity in which work is performed which results in an increase in metabolic rate. Resting metabolic rate (RMR), which is synonymous with resting energy expenditure (REE), is not measured under basal conditions. It is a measurement taken during a fast (two to four hours after a meal) and allows for some movement with a rest period prior to testing.1,2 The RMR is usually higher than the BMR due to less restrictive conditions for measureing RMR. Therefore, basal metabolic rate accounts for 60- 75% 1 of TEE while RMR accounts for 50-70% of TEE.. Since the difference between BMR and RMR is only about 10%, it is more practical to measure RMR in a clinical setting.2 In clinical settings RMR is used to determine accurate energy expenditure of a patient's caloric needs. Resting metabolic rate can be measured either directly or indirectly. trent: the medgem seems fine until you have any deviation from normal including old age - see the details inside the study...","title":"Calorimetry Device"},{"location":"docs/praxes/exercise-calories-burning-reference/#harris-benedict-formula","text":"","title":"Harris-Benedict Formula"},{"location":"docs/praxes/exercise-calories-burning-reference/#calculatornet-calculations","text":"Muscle Mass \u2013 Aerobic exercise such as running or cycling has no effect on BMR. However, anaerobic exercise, such as weight-lifting, indirectly leads to a higher BMR because it builds muscle mass, increasing resting energy consumption. The more muscle mass in the physical composition of an individual, the higher the BMR required to sustain their body at a certain level. my bmr: 1955 calories / day calculator.net bmr calculator men: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) + 5 women: BMR = 10 * weight(kg) + 6.25 * height(cm) - 5 * age(y) - 161 Why do you just subtract a constant from the men's BMR to get the womens' BMR? This seems like bullshit.","title":"Calculator.net Calculations"},{"location":"docs/praxes/exercise-calories-burning-reference/#my-calorie-calculator","text":"Using this calculator.net calculator 3031 calories to maintain weight 2531 calories to lose 1 lb per week 2031 calories to lose 2 lb per week","title":"My Calorie Calculator"},{"location":"docs/praxes/exercise-calories-burning-reference/#how-do-i-think-about-this","text":"Well, the BMR calculator said 1955, so 2031 - 1955 = 76 excess calories before factoring in exercise. The resting exercise state is 1.2x and my moderately active state is 1.55x. 1.55-1.2 = 0.35x. 1955 * 0.35x = 684 calories/day spent to exercise related behavior","title":"How do I think about this?"},{"location":"docs/praxes/exercise-calories-burning-reference/#my-ideal-weight","text":"Using this calculator.net calculator Based on the Robinson formula (1983), your ideal weight is 177.5 lbs Based on the Miller formula (1983), your ideal weight is 170.5 lbs Based on the Devine formula (1974), your ideal weight is 186.3 lbs Based on the Hamwi formula (1964), your ideal weight is 195.1 lbs Based on the healthy BMI recommendation, your recommended weight is 148.0 lbs - 200.0 lbs","title":"My Ideal Weight"},{"location":"docs/praxes/exercise-calories-burning-reference/#healthline-calculations","text":"based on: https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula BMR: Basal Metabolic Rate Sex, Age, Weight men: 66 + 6.2 x weight + 12.7 x height + 6.76 x age = BMR for men women: 655.1 + 4.35 x weight + 4.7 x height + 4.7 x age = BMR for women This is insane so a person with more fat needs more calories? shouldn't it be by lean bodymass? An older person needs 50 more calories per decade?? trent: 66 + 6.2 x 205 lbs + 12.7 x (12 x 6 + 3) + 6.76 x 34 = 66 + 1271 + 952.5 + 229.84 = 2519.34 activity level is moderately active (mod exercise 3-5 days per week) but I do hard exercise 3-5 days per week... which there is no choice for... kinda bullshit so you can only exercise hard 6-7 days per week... but, the difference is 1.55 versus 1.725 so i could fudge this constant easily... total calories = 2519.34 * 1.55 = 3904.98 calores per day This is truly insane and I have no faith in this number","title":"Healthline calculations"},{"location":"docs/praxes/exercise-calories-burning-reference/#bmr-effects","text":"Cold environments raise BMR, external heat raises BMR (body trends towards homeostasis) Starvation reduces BMR negatively impacting weight loss -- along with many negative effects: physical, psychological, permanent damage Caffeine is supposed to raise BMR","title":"BMR Effects"},{"location":"docs/praxes/exercise-calories-burning-reference/#references","text":"If there are inconsistencies, prefer better vetted literature. Use more than one source for all facts! https://www.healthline.com/health/fitness-exercise/how-many-calories-do-i-burn-a-day#harrisbenedict-formula","title":"References"},{"location":"docs/praxes/exercise-heart-rate-reference/","text":"Exercise Heart Rate Calculations Maximum Heart Rate WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you than the calculations, it's just an AVERAGE, so DON'T reach this heart rate. But reaching your MAXIMUM HEART RATE\u2014the greatest number of beats per minute your heart can possibly achieve during exercise\u2014requires an all-out effort that is extremely uncomfortable and impossible to maintain; even the most highly trained athletes can only maintain this intensity for a few minutes at a time. In addition, exercising at or near your maximum heart rate has not been shown to have significant benefits. In fact, it can actually be risky because of the stress it puts on your heart. (1) Reserve Heart Rate You can get a more accurate picture by using the 'reserve heart rate' method from The Mayo Clinic . Your reserve heart rate is: Maximum Heart Rate - Resting Heart Rate Get your resting heart rate Get a stopwatch (try on your phone) \"Rest\" for a few moments. Put your finger on your pulse (I use my neck) Start the timer on a beat, and count beats for 60 seconds. The number of beats per 60 seconds is your resting heart rate. \"The American Heart Association recommends checking your resting heart rate first thing in the morning (but before you get out of bed.\" 1 Target Heart Rate Range Your Target Heart Rate (THR) Range is generally 70 to 85 percent of your maximum heart rate, although it is based on you individually and there are a few ways to calculate it. IMPORTANT: There's no evidence that being at the high or low range of your Target Heart Rate is better... By knowing your TARGET HEART RATE you assure yourself that you optimize fitness improvement, calorie- and fat-burning, and you prevent overdoing it and not having fun during exercise. (1) How to improve at cardio There is no reason to push your heart rate beyond the target range during non-competitive exercise. It is bad to go too close to the max at any time. Going above your Target Heart Rate Range increases risk of damage. If you want to push yourself then: increase the TIME you are at your target heart rate. Calculate Target Heart Rate Range: Reserve Heart Rate Method This method takes into account age and base heart rate. The method is from the Mayo Clinic . Lets check target at some regular ages assuming 65 BPM Resting Heart Rate (RHR). 20 YRS : (220-20-65)*.7+65 to (220-20-65)*.85+65 = 160-180 30 YRS : (220-30-65)*.7+65 to (220-30-65)*.85+65 = 153-171 40 YRS : (220-40-65)*.7+65 to (220-40-65)*.85+65 = 146-163 50 YRS : (220-50-65)*.7+65 to (220-50-65)*.85+65 = 139-154 60 YRS : (220-60-65)*.7+65 to (220-60-65)*.85+65 = 132-146 70 YRS : (220-70-65)*.7+65 to (220-70-65)*.85+65 = 125-137 80 YRS : (220-80-65)*.7+65 to (220-80-65)*.85+65 = 118-129 Lets also check with a heart rate of 80 BPM. Note that a high heart rate increases all cause mortality, and you should seek to have a heart rate between 60-75 through physical fitness I don't love this one because it recommends people with higher resting heart rates need to reach a higher Target Heart Rate. I think this comes from lack of fitness, so it's sort of crummy advice to tell someone out of shape they need to work harder. But the range is pretty close between both. My heart rate is very stable at my level of exertion at the gym, so each individual can figure out their comfortable level on a per-machine basis. 20 YRS : (220-20-80)*.7+80 to (220-20-80)*.85+80 = 164-182 30 YRS : (220-30-80)*.7+80 to (220-30-80)*.85+80 = 157-174 40 YRS : (220-40-80)*.7+80 to (220-40-80)*.85+80 = 150-165 50 YRS : (220-50-80)*.7+80 to (220-50-80)*.85+80 = 143-157 60 YRS : (220-60-80)*.7+80 to (220-60-80)*.85+80 = 136-148 70 YRS : (220-70-80)*.7+80 to (220-70-80)*.85+80 = 129-140 80 YRS : (220-80-80)*.7+80 to (220-80-80)*.85+80 = 122-131 Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you, it's just an AVERAGE. Reserve Heart Rate (HRR) @ 34 years (MHR-HRR): 186 - 66 = 120 BPM This is how much you have \"left over\" between your resting and your max. Target Heart rate is approximately 70%-85% of Max Heart Rate, based on HRR: (186-66) * (70% to 85%) + 66 = 150 - 168 BPM The exact calculation is HRR * (70% to 85%) + RHR = THR Range Think of it as using 70-85% of your reserve This is the range for an intense workout I currently like to switch between 70% to 85% every 5 min for 25 min, this gives me some recovery. I tend to stick closer to 146 right now, I consider 154 to be a really heavy workout. I hit this something like 8 minutes into the workout? I measure what is a comfortable and natural ramp. Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm I easily hit this and warm up quite comfortably to 120 BPM within a few minutes I think this is too low, but it is for mild exercise at 150 minutes per week If I did moderate exercise I would do 150 mins per week, or 50 minutes per session at 120 BPM. Calculate Target Heart Rate Range: with General Method This method takes into account age only and NOT resting heart rate. Lets check target against the resting method at some regular ages. These ranges are a lot broader and don't go nearly as high. 20 YRS : (220-20)*.7 to (220-20)*.85 = 140-170 30 YRS : (220-20)*.7 to (220-20)*.85 = 133-162 40 YRS : (220-20)*.7 to (220-20)*.85 = 126-153 50 YRS : (220-20)*.7 to (220-20)*.85 = 119-145 60 YRS : (220-20)*.7 to (220-20)*.85 = 112-136 70 YRS : (220-20)*.7 to (220-20)*.85 = 105-128 80 YRS : (220-20)*.7 to (220-20)*.85 = 98-119 Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you, it's just an AVERAGE. Target Heart rate is 70%-85% of Max Heart Rate: 186 * (70% to 85%) = 130 - 158 BPM You want to spend your workout in this range... but how much time at each part of the range? I like to alternate every 5 min for 25 min. I hit this something like 8 minutes into the workout? Measure what is a comfortable and natural ramp. Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm I easily hit this and warm out quite comfortably to 120 BPM within a few minutes Intensity and Time Span Summary: 150 min moderate exercise or 75 min vigorous exercise per week. Use the Rating of Perceived Exertion or 'borg' scale. Intensity You can use relative intensity to measure your workout. You are the judge of the intensity in this system. You probably need some experience to make this accurate. The primary scale has two names: Borg Scale and Rating of Perceived Exertion (RPE) Scale . Wikipedia: Borg Scale CDC: Measuring Exertion A rating of 12-13 probably is a moderate physical exercise?? A rating of 15-17 probably is a vigorous physical exercise?? Studies show that your perceived exertion compares well with your heart rate. So if you think you're working hard, your heart rate is probably higher than usual. (1) Time Span The Mayo Clinic recommends every week do one of the following : 150 minutes of moderate aerobic activity or 75 minutes of vigorous aerobic activity You may need to work up to vigorous aerobic activity. I certainly did in 2018. You should also do: 2 strength training sessions - per week (including rock climbing, \"heavy gardening\") Free weights are ideal Weight machines References CALCULATING YOUR TARGET HEART RATE This is the reference for some of these facts, and it has no citations. Please verify ALL data with the AHA or other entity and remove this reference. I have read similar things elsewhere, but that's not a substitute for real citations. CDC Exercise Guide CDC Activity Intensity CDC Heart Rate Method","title":"Exercise Heart Rate Reference"},{"location":"docs/praxes/exercise-heart-rate-reference/#exercise-heart-rate-calculations","text":"","title":"Exercise Heart Rate Calculations"},{"location":"docs/praxes/exercise-heart-rate-reference/#maximum-heart-rate","text":"WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you than the calculations, it's just an AVERAGE, so DON'T reach this heart rate. But reaching your MAXIMUM HEART RATE\u2014the greatest number of beats per minute your heart can possibly achieve during exercise\u2014requires an all-out effort that is extremely uncomfortable and impossible to maintain; even the most highly trained athletes can only maintain this intensity for a few minutes at a time. In addition, exercising at or near your maximum heart rate has not been shown to have significant benefits. In fact, it can actually be risky because of the stress it puts on your heart. (1)","title":"Maximum Heart Rate"},{"location":"docs/praxes/exercise-heart-rate-reference/#reserve-heart-rate","text":"You can get a more accurate picture by using the 'reserve heart rate' method from The Mayo Clinic . Your reserve heart rate is: Maximum Heart Rate - Resting Heart Rate","title":"Reserve Heart Rate"},{"location":"docs/praxes/exercise-heart-rate-reference/#get-your-resting-heart-rate","text":"Get a stopwatch (try on your phone) \"Rest\" for a few moments. Put your finger on your pulse (I use my neck) Start the timer on a beat, and count beats for 60 seconds. The number of beats per 60 seconds is your resting heart rate. \"The American Heart Association recommends checking your resting heart rate first thing in the morning (but before you get out of bed.\" 1","title":"Get your resting heart rate"},{"location":"docs/praxes/exercise-heart-rate-reference/#target-heart-rate-range","text":"Your Target Heart Rate (THR) Range is generally 70 to 85 percent of your maximum heart rate, although it is based on you individually and there are a few ways to calculate it. IMPORTANT: There's no evidence that being at the high or low range of your Target Heart Rate is better... By knowing your TARGET HEART RATE you assure yourself that you optimize fitness improvement, calorie- and fat-burning, and you prevent overdoing it and not having fun during exercise. (1)","title":"Target Heart Rate Range"},{"location":"docs/praxes/exercise-heart-rate-reference/#how-to-improve-at-cardio","text":"There is no reason to push your heart rate beyond the target range during non-competitive exercise. It is bad to go too close to the max at any time. Going above your Target Heart Rate Range increases risk of damage. If you want to push yourself then: increase the TIME you are at your target heart rate.","title":"How to improve at cardio"},{"location":"docs/praxes/exercise-heart-rate-reference/#calculate-target-heart-rate-range-reserve-heart-rate-method","text":"This method takes into account age and base heart rate. The method is from the Mayo Clinic . Lets check target at some regular ages assuming 65 BPM Resting Heart Rate (RHR). 20 YRS : (220-20-65)*.7+65 to (220-20-65)*.85+65 = 160-180 30 YRS : (220-30-65)*.7+65 to (220-30-65)*.85+65 = 153-171 40 YRS : (220-40-65)*.7+65 to (220-40-65)*.85+65 = 146-163 50 YRS : (220-50-65)*.7+65 to (220-50-65)*.85+65 = 139-154 60 YRS : (220-60-65)*.7+65 to (220-60-65)*.85+65 = 132-146 70 YRS : (220-70-65)*.7+65 to (220-70-65)*.85+65 = 125-137 80 YRS : (220-80-65)*.7+65 to (220-80-65)*.85+65 = 118-129 Lets also check with a heart rate of 80 BPM. Note that a high heart rate increases all cause mortality, and you should seek to have a heart rate between 60-75 through physical fitness I don't love this one because it recommends people with higher resting heart rates need to reach a higher Target Heart Rate. I think this comes from lack of fitness, so it's sort of crummy advice to tell someone out of shape they need to work harder. But the range is pretty close between both. My heart rate is very stable at my level of exertion at the gym, so each individual can figure out their comfortable level on a per-machine basis. 20 YRS : (220-20-80)*.7+80 to (220-20-80)*.85+80 = 164-182 30 YRS : (220-30-80)*.7+80 to (220-30-80)*.85+80 = 157-174 40 YRS : (220-40-80)*.7+80 to (220-40-80)*.85+80 = 150-165 50 YRS : (220-50-80)*.7+80 to (220-50-80)*.85+80 = 143-157 60 YRS : (220-60-80)*.7+80 to (220-60-80)*.85+80 = 136-148 70 YRS : (220-70-80)*.7+80 to (220-70-80)*.85+80 = 129-140 80 YRS : (220-80-80)*.7+80 to (220-80-80)*.85+80 = 122-131 Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you, it's just an AVERAGE. Reserve Heart Rate (HRR) @ 34 years (MHR-HRR): 186 - 66 = 120 BPM This is how much you have \"left over\" between your resting and your max. Target Heart rate is approximately 70%-85% of Max Heart Rate, based on HRR: (186-66) * (70% to 85%) + 66 = 150 - 168 BPM The exact calculation is HRR * (70% to 85%) + RHR = THR Range Think of it as using 70-85% of your reserve This is the range for an intense workout I currently like to switch between 70% to 85% every 5 min for 25 min, this gives me some recovery. I tend to stick closer to 146 right now, I consider 154 to be a really heavy workout. I hit this something like 8 minutes into the workout? I measure what is a comfortable and natural ramp. Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm I easily hit this and warm up quite comfortably to 120 BPM within a few minutes I think this is too low, but it is for mild exercise at 150 minutes per week If I did moderate exercise I would do 150 mins per week, or 50 minutes per session at 120 BPM.","title":"Calculate Target Heart Rate Range: Reserve Heart Rate Method"},{"location":"docs/praxes/exercise-heart-rate-reference/#calculate-target-heart-rate-range-with-general-method","text":"This method takes into account age only and NOT resting heart rate. Lets check target against the resting method at some regular ages. These ranges are a lot broader and don't go nearly as high. 20 YRS : (220-20)*.7 to (220-20)*.85 = 140-170 30 YRS : (220-20)*.7 to (220-20)*.85 = 133-162 40 YRS : (220-20)*.7 to (220-20)*.85 = 126-153 50 YRS : (220-20)*.7 to (220-20)*.85 = 119-145 60 YRS : (220-20)*.7 to (220-20)*.85 = 112-136 70 YRS : (220-20)*.7 to (220-20)*.85 = 105-128 80 YRS : (220-20)*.7 to (220-20)*.85 = 98-119 Max Heart Rate @ 34 Years: 220 - 34 = 186 BPM - WARNING - DO NOT GET NEAR THIS HEART RATE WARNING: This heart rate is your absolute MAXIMUM and could cause damage. It may also be EVEN LOWER for you, it's just an AVERAGE. Target Heart rate is 70%-85% of Max Heart Rate: 186 * (70% to 85%) = 130 - 158 BPM You want to spend your workout in this range... but how much time at each part of the range? I like to alternate every 5 min for 25 min. I hit this something like 8 minutes into the workout? Measure what is a comfortable and natural ramp. Minimum Exercise Heart Rate is 60% of Max Heart Rate: 186 * 60% = 112 bpm I easily hit this and warm out quite comfortably to 120 BPM within a few minutes","title":"Calculate Target Heart Rate Range: with General Method"},{"location":"docs/praxes/exercise-heart-rate-reference/#intensity-and-time-span","text":"Summary: 150 min moderate exercise or 75 min vigorous exercise per week. Use the Rating of Perceived Exertion or 'borg' scale.","title":"Intensity and Time Span"},{"location":"docs/praxes/exercise-heart-rate-reference/#intensity","text":"You can use relative intensity to measure your workout. You are the judge of the intensity in this system. You probably need some experience to make this accurate. The primary scale has two names: Borg Scale and Rating of Perceived Exertion (RPE) Scale . Wikipedia: Borg Scale CDC: Measuring Exertion A rating of 12-13 probably is a moderate physical exercise?? A rating of 15-17 probably is a vigorous physical exercise?? Studies show that your perceived exertion compares well with your heart rate. So if you think you're working hard, your heart rate is probably higher than usual. (1)","title":"Intensity"},{"location":"docs/praxes/exercise-heart-rate-reference/#time-span","text":"The Mayo Clinic recommends every week do one of the following : 150 minutes of moderate aerobic activity or 75 minutes of vigorous aerobic activity You may need to work up to vigorous aerobic activity. I certainly did in 2018. You should also do: 2 strength training sessions - per week (including rock climbing, \"heavy gardening\") Free weights are ideal Weight machines","title":"Time Span"},{"location":"docs/praxes/exercise-heart-rate-reference/#references","text":"CALCULATING YOUR TARGET HEART RATE This is the reference for some of these facts, and it has no citations. Please verify ALL data with the AHA or other entity and remove this reference. I have read similar things elsewhere, but that's not a substitute for real citations. CDC Exercise Guide CDC Activity Intensity CDC Heart Rate Method","title":"References"},{"location":"docs/praxes/git-make-diff-patch/","text":"Git Patch and General Patching General patching, especially wrt git repositories, both: Committed Changes Uncommitted Changes Processes Some processes are listed below. Patch between two directories with diff / patch - NO SCM REQUIRED! No need for git, you can keep your files in a signed tarball. Not as useful in a world with popular, collaborative SCM tools. Patch individual files with git diff / patch . You could actually diff two different files, but in this case it's easier to git diff between the file at HEAD and the current file. Patch a git repository by applying actual commits with git diff / git apply A similar process exists for SVN but is not detailed below, it can also be used to push patches from git to SVN. Individual Files and Uncommitted Changes: Use the patch command This process does not require a git repository. You just need two files (or groups of files) to diff to get the output. Then anyone can apply the diff to the old file to get the new one. Make the patch in the desired directory: git diff --no-prefix > some-feature.diff This git feature can provide output that patch can use. If you are using git: Find where you want to patch from and check the commit out headless, then you can proceed as if the changes are uncommitted (using patch ). Apply the patch in the same directory: patch < some-feature.diff This is not a git feature, it only interacts with the filesystem. Committed Changes: Use the git apply command This process requires a git repository. You can patch commit history onto another .git instance. Use the git patch tools: git diff and git apply This isn't so different than the patch command: https://www.lullabot.com/articles/git-best-practices-upgrading-the-patch-process Resources http://scribu.net/wordpress/svn-patches-from-git.html https://markjaquith.wordpress.com/2005/11/02/my-wordpress-toolbox/ patch manpage","title":"Git Make Diff Patch"},{"location":"docs/praxes/git-make-diff-patch/#git-patch-and-general-patching","text":"General patching, especially wrt git repositories, both: Committed Changes Uncommitted Changes","title":"Git Patch and General Patching"},{"location":"docs/praxes/git-make-diff-patch/#processes","text":"Some processes are listed below. Patch between two directories with diff / patch - NO SCM REQUIRED! No need for git, you can keep your files in a signed tarball. Not as useful in a world with popular, collaborative SCM tools. Patch individual files with git diff / patch . You could actually diff two different files, but in this case it's easier to git diff between the file at HEAD and the current file. Patch a git repository by applying actual commits with git diff / git apply A similar process exists for SVN but is not detailed below, it can also be used to push patches from git to SVN.","title":"Processes"},{"location":"docs/praxes/git-make-diff-patch/#individual-files-and-uncommitted-changes-use-the-patch-command","text":"This process does not require a git repository. You just need two files (or groups of files) to diff to get the output. Then anyone can apply the diff to the old file to get the new one. Make the patch in the desired directory: git diff --no-prefix > some-feature.diff This git feature can provide output that patch can use. If you are using git: Find where you want to patch from and check the commit out headless, then you can proceed as if the changes are uncommitted (using patch ). Apply the patch in the same directory: patch < some-feature.diff This is not a git feature, it only interacts with the filesystem.","title":"Individual Files and Uncommitted Changes: Use the patch command"},{"location":"docs/praxes/git-make-diff-patch/#committed-changes-use-the-git-apply-command","text":"This process requires a git repository. You can patch commit history onto another .git instance. Use the git patch tools: git diff and git apply This isn't so different than the patch command: https://www.lullabot.com/articles/git-best-practices-upgrading-the-patch-process","title":"Committed Changes: Use the git apply command"},{"location":"docs/praxes/git-make-diff-patch/#resources","text":"http://scribu.net/wordpress/svn-patches-from-git.html https://markjaquith.wordpress.com/2005/11/02/my-wordpress-toolbox/ patch manpage","title":"Resources"},{"location":"docs/praxes/gitolite-manual-reinstall-graft/","text":"Gitolite Migration Instructions for migrating gitolite3 to a new host. Gitolite gitolite-admin management If gitolite-admin is managed remotely, it simply needs the git remote path changed. If gitolite-admin is managed locally, ensure the old admin.pub key is kept as it is committed in the repo. Graft gitolite3 install onto a server and change your admin key This process assumes you are doing a key change in your admin repo concurrent with reinstall. If you do not need to do a keychange and keep gitolite-admin remote then the only thing you have to do is install gitolite through apt and graft the replacement directory. Much faster. There may be an easier way, LMK if you try one. This method is intended to graft the magic, whole hog, rather than try to integrate new magic on top. ssh-keygen - have a local key for easy gitolite install apt-get install gitolite3 Do a default setup and DO point it to your local pubkey: /home//.ssh/id_rsa.pub this pubkey is going to get wiped out anyways Move the generated keys (from ssh-keygen ) to temporary files I like to put them in /home/ for now Add the old keys where the generated keys were This ensures you will be able to push to your grafted repository id_rsa , id_rsa.pub` Copy the original gitolite-admin management repo to the new host The git remote can be set as localhost if it is managed locally Delete the gitolite management repo on the new host /var/lib/gitolite3 Copy the original gitolite installation directory to the new host /var/lib/gitolite3 Chown the gitolite installation directory to gitolite:gitolite You should be able to git fetch with no issues Add the new key to the gitolite-admin repository Replace gitolite-admin/keydir/admin.pub with your new id_rsa.pub Push this commit Replace the old keys in .ssh with the generated keys","title":"Gitolite Manual Reinstall Graft"},{"location":"docs/praxes/gitolite-manual-reinstall-graft/#gitolite-migration","text":"Instructions for migrating gitolite3 to a new host.","title":"Gitolite Migration"},{"location":"docs/praxes/gitolite-manual-reinstall-graft/#gitolite-gitolite-admin-management","text":"If gitolite-admin is managed remotely, it simply needs the git remote path changed. If gitolite-admin is managed locally, ensure the old admin.pub key is kept as it is committed in the repo.","title":"Gitolite gitolite-admin management"},{"location":"docs/praxes/gitolite-manual-reinstall-graft/#graft-gitolite3-install-onto-a-server-and-change-your-admin-key","text":"This process assumes you are doing a key change in your admin repo concurrent with reinstall. If you do not need to do a keychange and keep gitolite-admin remote then the only thing you have to do is install gitolite through apt and graft the replacement directory. Much faster. There may be an easier way, LMK if you try one. This method is intended to graft the magic, whole hog, rather than try to integrate new magic on top. ssh-keygen - have a local key for easy gitolite install apt-get install gitolite3 Do a default setup and DO point it to your local pubkey: /home//.ssh/id_rsa.pub this pubkey is going to get wiped out anyways Move the generated keys (from ssh-keygen ) to temporary files I like to put them in /home/ for now Add the old keys where the generated keys were This ensures you will be able to push to your grafted repository id_rsa , id_rsa.pub` Copy the original gitolite-admin management repo to the new host The git remote can be set as localhost if it is managed locally Delete the gitolite management repo on the new host /var/lib/gitolite3 Copy the original gitolite installation directory to the new host /var/lib/gitolite3 Chown the gitolite installation directory to gitolite:gitolite You should be able to git fetch with no issues Add the new key to the gitolite-admin repository Replace gitolite-admin/keydir/admin.pub with your new id_rsa.pub Push this commit Replace the old keys in .ssh with the generated keys","title":"Graft gitolite3 install onto a server and change your admin key"},{"location":"docs/praxes/lftp_automation/","text":"lftp FTPS/FTP Automation We want to use ftps which uses FTP over TLS/SSL. This is not the same as sftp which is FTP over SSH. FTP Server: Port: 990 User name: Password: The user name does not allow @. This may be possible somehow. Example with lftp command line FTP/FTPS program FTPS Example Note that you must specify ftps:// in the URL. lftp -c \"open -p990 -u , ftps://; ls\" FTP Example $ lftp -c \"open -u , ; ls\" This can be used to send and receive files automatically via scripted action. Security Always use FTPS over port 990. Standard (Port 21) or Implicit SSL/TLS (Port 990) are available.","title":"Lftp Automation"},{"location":"docs/praxes/lftp_automation/#lftp-ftpsftp-automation","text":"We want to use ftps which uses FTP over TLS/SSL. This is not the same as sftp which is FTP over SSH. FTP Server: Port: 990 User name: Password: The user name does not allow @. This may be possible somehow.","title":"lftp FTPS/FTP Automation"},{"location":"docs/praxes/lftp_automation/#example-with-lftp-command-line-ftpftps-program","text":"","title":"Example with lftp command line FTP/FTPS program"},{"location":"docs/praxes/lftp_automation/#ftps-example","text":"Note that you must specify ftps:// in the URL. lftp -c \"open -p990 -u , ftps://; ls\"","title":"FTPS Example"},{"location":"docs/praxes/lftp_automation/#ftp-example","text":"$ lftp -c \"open -u , ; ls\" This can be used to send and receive files automatically via scripted action.","title":"FTP Example"},{"location":"docs/praxes/lftp_automation/#security","text":"Always use FTPS over port 990. Standard (Port 21) or Implicit SSL/TLS (Port 990) are available.","title":"Security"},{"location":"docs/praxes/my-organization-tools/","text":"My Organization Tools pinboard.in github.com trello.com would like to replace with oss with easy sync with iphone and offline mode gmail.com notetoself tag should be moved to trello outlines.git firefox bookmarks (would like to reduce/remove) Low Use Organizational Tools librarything.com * todoist * anki","title":"My Organization Tools"},{"location":"docs/praxes/my-organization-tools/#my-organization-tools","text":"pinboard.in github.com trello.com would like to replace with oss with easy sync with iphone and offline mode gmail.com notetoself tag should be moved to trello outlines.git firefox bookmarks (would like to reduce/remove)","title":"My Organization Tools"},{"location":"docs/praxes/my-organization-tools/#low-use-organizational-tools","text":"librarything.com * todoist * anki","title":"Low Use Organizational Tools"},{"location":"docs/praxes/optiplex/","text":"Setting up a Dell OptiPlex FX160 Use a sata 22-pin extender to add a 2.5\" drive Update the BIOS Settings In System -> Boot Options (make sure both the drive and usb are inserted) Hard Drive USB (no option) (no option) (no option) In Drives -> SATA Operation select AHCI Optional: reset security settings by unseating the bios coin battery for 1 minute Download xubuntu 16.04.2 iso and write to a flash drive Attach a monitor, keyboard, mouse, and ethernet cable or USB wifi card install xubuntu Select: install 3rd party software and download updates during install Set an appropriate: hostname , username , and password Install vim , openssh-server , and openssh-client Get a static IP on your local network (lan) Paste the contents in the snippet below into /etc/network/interfaces ``` interfaces(5) file used by ifup(8) and ifdown(8) default loopback interface (from install) auto lo iface lo inet loopback auto enp2s0 iface enp2s0 inet static address 192.168.1.ddd netmask 255.255.255.0 gateway 192.168.1.1 google DNS dns-nameservers 8.8.8.8 ``` Update your address and gateway for your local network Additionally, your interface name may be different, here called enp2s0 Find your interface by typing ifconfig , it is the one that is not lo Make sure you are setting up the interface you will always be using Ubuntu guarantees consistent naming for these interfaces per hardware configuration SSH into your computer through your local network at the correct local IP If you will connect over the internet, test this too through a remote connection Restart the computer, optionally test SSH again If everything works, you can remove the peripherals and manage the machine through SSH This guide does not cover securing or managing your installation.","title":"Optiplex"},{"location":"docs/praxes/optiplex/#setting-up-a-dell-optiplex-fx160","text":"Use a sata 22-pin extender to add a 2.5\" drive Update the BIOS Settings In System -> Boot Options (make sure both the drive and usb are inserted) Hard Drive USB (no option) (no option) (no option) In Drives -> SATA Operation select AHCI Optional: reset security settings by unseating the bios coin battery for 1 minute Download xubuntu 16.04.2 iso and write to a flash drive Attach a monitor, keyboard, mouse, and ethernet cable or USB wifi card install xubuntu Select: install 3rd party software and download updates during install Set an appropriate: hostname , username , and password Install vim , openssh-server , and openssh-client Get a static IP on your local network (lan) Paste the contents in the snippet below into /etc/network/interfaces ```","title":"Setting up a Dell OptiPlex FX160"},{"location":"docs/praxes/optiplex/#interfaces5-file-used-by-ifup8-and-ifdown8","text":"","title":"interfaces(5) file used by ifup(8) and ifdown(8)"},{"location":"docs/praxes/optiplex/#default-loopback-interface-from-install","text":"auto lo iface lo inet loopback auto enp2s0 iface enp2s0 inet static address 192.168.1.ddd netmask 255.255.255.0 gateway 192.168.1.1","title":"default loopback interface (from install)"},{"location":"docs/praxes/optiplex/#google-dns","text":"dns-nameservers 8.8.8.8 ``` Update your address and gateway for your local network Additionally, your interface name may be different, here called enp2s0 Find your interface by typing ifconfig , it is the one that is not lo Make sure you are setting up the interface you will always be using Ubuntu guarantees consistent naming for these interfaces per hardware configuration SSH into your computer through your local network at the correct local IP If you will connect over the internet, test this too through a remote connection Restart the computer, optionally test SSH again If everything works, you can remove the peripherals and manage the machine through SSH This guide does not cover securing or managing your installation.","title":"google DNS"},{"location":"docs/praxes/osx_disable_sip/","text":"How to get a terminal and remove System Integrity Protection in OSX Hold [CMD+R] to get a recovery menu. If this doesn't work (osx sierra bug) then use [CMD+OPT+R], internet recovery. In the top menu choose Utilities->Terminal Type csrutil disable Success message will show Perform system modifications csrutil enable - ENABLE SIP AGAIN. This is a pretty good defense mechanism.","title":"Osx Disable Sip"},{"location":"docs/praxes/osx_disable_sip/#how-to-get-a-terminal-and-remove-system-integrity-protection-in-osx","text":"Hold [CMD+R] to get a recovery menu. If this doesn't work (osx sierra bug) then use [CMD+OPT+R], internet recovery. In the top menu choose Utilities->Terminal Type csrutil disable Success message will show Perform system modifications csrutil enable - ENABLE SIP AGAIN. This is a pretty good defense mechanism.","title":"How to get a terminal and remove System Integrity Protection in OSX"},{"location":"docs/praxes/pcb-etching/","text":"PCB Etching Placeholder outline document. Resources: Noisebridge PCB Etching Tutorial","title":"Pcb Etching"},{"location":"docs/praxes/pcb-etching/#pcb-etching","text":"Placeholder outline document.","title":"PCB Etching"},{"location":"docs/praxes/pcb-etching/#resources","text":"Noisebridge PCB Etching Tutorial","title":"Resources:"},{"location":"docs/praxes/raspi_home_setup/","text":"Raspberry Pi Home Setup A history of how my two raspberry pi headless machines were set up at home. Future Consider writing a service to detect and deliver changes to raspberry PI IP addresses over a static location such as digitalocean/flask. Configuration System Apt sudo apt-get update sudo apt-get upgrade sudo apt-get install vim git tree tmux pwgen fail2ban SSH Port Add additional ssh port Port 2200 to /etc/ssh/sshd_config Set PermitRootLogin to 'no' in /etc/ssh/sshd_config Restart ssh server: sudo service sshd restart Add ssh port forwarding on router Static IP: sudo vim /etc/dhcpcd.conf Append this to the file (change as necessary): interface eth0 static ip_address=192.168.1.111 static routers=192.168.1.1 static domain_name_servers=192.168.1.1 raspi-config FIRST: Advanced Options -> Update (update the tool) Note: if this triggers an update, this file will need updated too. Expand Filesystem (select it to auto expand) Change User Password: pi password to a pwgen -cn 12 password Boot Options -> Console Internationalization Set timezone to Pacific Ocean Set keyboard to 101-key , US Standard Set wifi country to United States Advanced Options Hostname -> Change to desired hostname Memory Split -> 16 (headless needs no gpu) SSH -> Enable (default) User Management Add user adduser robbintt - use a new pwgen -cn 12 password. Add robbintt to sudo group Create SSH keys ssh-keygen Add SSH pubkey to bitbucket dotfiles.git as deployment key cd ~; git clone git@bitbucket.org:robbintt/dotfiles.git .dotfiles Unpack dotfile symlinks w/ make_symlinks.sh script Log in as user, delete any pi account ssh keys. Configure dotfiles ssh to include user, port. Add authorized_keys from other machines as necessary and update .ssh/config in dotfiles. Redeploy dotfiles. Remove pi NOPASSWD sudo priveleges in visudo","title":"Raspi Home Setup"},{"location":"docs/praxes/raspi_home_setup/#raspberry-pi-home-setup","text":"A history of how my two raspberry pi headless machines were set up at home.","title":"Raspberry Pi Home Setup"},{"location":"docs/praxes/raspi_home_setup/#future","text":"Consider writing a service to detect and deliver changes to raspberry PI IP addresses over a static location such as digitalocean/flask.","title":"Future"},{"location":"docs/praxes/raspi_home_setup/#configuration","text":"","title":"Configuration"},{"location":"docs/praxes/raspi_home_setup/#system","text":"Apt sudo apt-get update sudo apt-get upgrade sudo apt-get install vim git tree tmux pwgen fail2ban SSH Port Add additional ssh port Port 2200 to /etc/ssh/sshd_config Set PermitRootLogin to 'no' in /etc/ssh/sshd_config Restart ssh server: sudo service sshd restart Add ssh port forwarding on router Static IP: sudo vim /etc/dhcpcd.conf Append this to the file (change as necessary): interface eth0 static ip_address=192.168.1.111 static routers=192.168.1.1 static domain_name_servers=192.168.1.1","title":"System"},{"location":"docs/praxes/raspi_home_setup/#raspi-config","text":"FIRST: Advanced Options -> Update (update the tool) Note: if this triggers an update, this file will need updated too. Expand Filesystem (select it to auto expand) Change User Password: pi password to a pwgen -cn 12 password Boot Options -> Console Internationalization Set timezone to Pacific Ocean Set keyboard to 101-key , US Standard Set wifi country to United States Advanced Options Hostname -> Change to desired hostname Memory Split -> 16 (headless needs no gpu) SSH -> Enable (default)","title":"raspi-config"},{"location":"docs/praxes/raspi_home_setup/#user-management","text":"Add user adduser robbintt - use a new pwgen -cn 12 password. Add robbintt to sudo group Create SSH keys ssh-keygen Add SSH pubkey to bitbucket dotfiles.git as deployment key cd ~; git clone git@bitbucket.org:robbintt/dotfiles.git .dotfiles Unpack dotfile symlinks w/ make_symlinks.sh script Log in as user, delete any pi account ssh keys. Configure dotfiles ssh to include user, port. Add authorized_keys from other machines as necessary and update .ssh/config in dotfiles. Redeploy dotfiles. Remove pi NOPASSWD sudo priveleges in visudo","title":"User Management"},{"location":"docs/praxes/set_dvdplayer_region/","text":"Set a DVD Player's Region from Linux (Debian based) Many DVD players have manufacturer limits in the firmware. Mine had a limit of 5 region resets. There are 8 regions. You probably want a US region. If you always need more than one region you will need multiple DVD drives. In 2017, DVD drives are practically without value. Procedure Use the regionset utility to change the region. If you run out of resets, the DVD player keeps the final region you selected. Some DVD players may have firmware upgrades that reset the counter. apt install regionset Run regionset and set the region if it is not already set.","title":"Set Dvdplayer Region"},{"location":"docs/praxes/set_dvdplayer_region/#set-a-dvd-players-region-from-linux-debian-based","text":"Many DVD players have manufacturer limits in the firmware. Mine had a limit of 5 region resets. There are 8 regions. You probably want a US region. If you always need more than one region you will need multiple DVD drives. In 2017, DVD drives are practically without value.","title":"Set a DVD Player's Region from Linux (Debian based)"},{"location":"docs/praxes/set_dvdplayer_region/#procedure","text":"Use the regionset utility to change the region. If you run out of resets, the DVD player keeps the final region you selected. Some DVD players may have firmware upgrades that reset the counter. apt install regionset Run regionset and set the region if it is not already set.","title":"Procedure"},{"location":"docs/praxes/site_asset_checklist/","text":"Website Project Checklist favicon.ico 16x16 32x32 ??","title":"Site Asset Checklist"},{"location":"docs/praxes/site_asset_checklist/#website-project-checklist","text":"favicon.ico 16x16 32x32 ??","title":"Website Project Checklist"},{"location":"docs/praxes/site_launch_checklist/","text":"Website Launch Checklist Google Analytics ID Enabled Amazon Cloudwatch Monitoring (when applicable)","title":"Site Launch Checklist"},{"location":"docs/praxes/site_launch_checklist/#website-launch-checklist","text":"Google Analytics ID Enabled Amazon Cloudwatch Monitoring (when applicable)","title":"Website Launch Checklist"},{"location":"docs/praxes/ssh_socks_proxy/","text":"Procedure: Set up ssh as a SOCKS proxy over 443 \"A simple VPN.\" - lee Prerequisites The remote server's sshd needs to accept ssh on 443 if you can only get 443 outbound. Edit /etc/ssh/sshd_config to have the line Port 443 after any similar lines and service sshd restart Server and client setup ssh -p443 -D localhost:443 @ macos: sudo ssh -i -D localhost:443 @ make sure to use the path to the private key, not the public key!! Configure your local system to send network traffic over a SOCKS proxy at localhost:443 macos: System Preferences->Network unlock administrative access (press the lock) select 'wifi' for wifi choose Advanced...->Proxies Add localhost : 443 to the SOCKS Proxy , choose ok In the 'network' window choose save Check your IP at google.com by typing \"whats my IP\"","title":"Ssh Socks Proxy"},{"location":"docs/praxes/ssh_socks_proxy/#procedure-set-up-ssh-as-a-socks-proxy-over-443","text":"\"A simple VPN.\" - lee","title":"Procedure: Set up ssh as a SOCKS proxy over 443"},{"location":"docs/praxes/ssh_socks_proxy/#prerequisites","text":"The remote server's sshd needs to accept ssh on 443 if you can only get 443 outbound. Edit /etc/ssh/sshd_config to have the line Port 443 after any similar lines and service sshd restart","title":"Prerequisites"},{"location":"docs/praxes/ssh_socks_proxy/#server-and-client-setup","text":"ssh -p443 -D localhost:443 @ macos: sudo ssh -i -D localhost:443 @ make sure to use the path to the private key, not the public key!! Configure your local system to send network traffic over a SOCKS proxy at localhost:443 macos: System Preferences->Network unlock administrative access (press the lock) select 'wifi' for wifi choose Advanced...->Proxies Add localhost : 443 to the SOCKS Proxy , choose ok In the 'network' window choose save Check your IP at google.com by typing \"whats my IP\"","title":"Server and client setup"},{"location":"docs/praxes/ssh_tunnel_back/","text":"Setting up tunneling back into an SSH connection This is for establishing a new connection back to the server through the original SSH connection. This is typically used if you are behind a proxy but the machine you want to be on is not. You can access the machine, then use that tunnel to access your machine. The best use case for this is if you have some non-ssh access to a remote machine and need to establish a tunnel back to your local machine in order to have direct ssh access to the remote machine. One use case for this might be a citrix desktop. Definitions This gets confusing so we will use 2 terms to disambiguate each server. Establishing Server - The server which sends the first SSH connection. Its SSH connection will be tunneled back through. Remote Server - The server that receives the original SSH connection and is used to tunnel back into the Establishing Server Setup Open /etc/ssh/sshd_config and add the line GatewayPorts yes Create a tunnleable connection from the Establishing Server to the Remote Server . ssh -R 2000:localhost:22 yourusername@remoteservername -p22 Tunnel back from the Remote Server to the Establishing Server ssh -p2000 yourusername@localhost This connection is only available through loopback/localhost References ServerFault 'SSH back to local machine from remote SSH session' AskUbuntu reverse port tunneling man sshd_config","title":"Ssh Tunnel Back"},{"location":"docs/praxes/ssh_tunnel_back/#setting-up-tunneling-back-into-an-ssh-connection","text":"This is for establishing a new connection back to the server through the original SSH connection. This is typically used if you are behind a proxy but the machine you want to be on is not. You can access the machine, then use that tunnel to access your machine. The best use case for this is if you have some non-ssh access to a remote machine and need to establish a tunnel back to your local machine in order to have direct ssh access to the remote machine. One use case for this might be a citrix desktop.","title":"Setting up tunneling back into an SSH connection"},{"location":"docs/praxes/ssh_tunnel_back/#definitions","text":"This gets confusing so we will use 2 terms to disambiguate each server. Establishing Server - The server which sends the first SSH connection. Its SSH connection will be tunneled back through. Remote Server - The server that receives the original SSH connection and is used to tunnel back into the Establishing Server","title":"Definitions"},{"location":"docs/praxes/ssh_tunnel_back/#setup","text":"Open /etc/ssh/sshd_config and add the line GatewayPorts yes Create a tunnleable connection from the Establishing Server to the Remote Server . ssh -R 2000:localhost:22 yourusername@remoteservername -p22 Tunnel back from the Remote Server to the Establishing Server ssh -p2000 yourusername@localhost This connection is only available through loopback/localhost","title":"Setup"},{"location":"docs/praxes/ssh_tunnel_back/#references","text":"ServerFault 'SSH back to local machine from remote SSH session' AskUbuntu reverse port tunneling man sshd_config","title":"References"},{"location":"docs/praxes/ssh_vnc_reverse_proxy/","text":"VNC Reverse Proxy In order to create a reverse proxy, you will need access to the server behind the firewall and a computer with a static IP address to proxy/receive the connection from your laptop. Steps Setup - proxy server/computer Make sure it has a static IP and that the sshd server is active Set the sshd_config 's GatewayPorts clientspecified - this is used to allow any domain to hit the proxy Installation - computer/server behind the firewall apt install autossh tightvncserver xfce4 xfce4-goodies firefox store the vnc server password somewhere safe, choose connection 1 as that corresponds to port 5901 Write a systemd unit for connecting to the proxy replace your_username_here with your username and 1.2.3.4 with the IP or DNS hostname of your proxy server Install the systemd service, restart the daemon , start it, and enable it. ```[Unit] Description=AutoSSH Tunnel After=network.target [Service] User=your_username_here Environment=\"AUTOSSH_GATETIME=0\" ExecStart=/usr/bin/autossh -M 0 -o \"ServerAliveInterval 30\" -o \"ServerAliveCountMax 3\" -NR *:5901:localhost:5901 your_username_here@1.2.3.4 -p 22 [Install] WantedBy=multi-user.target ``` Connect to vnc server use the default mac client $ open vnc://1.2.3.4:5901 you should not need to specify a username or anything else or use a specialized client Future Configure the tightvncserver service or pick a different one if preferred. Consider better macos, windows, linux vnc clients and special configuration options Option: per-user vnc connection instead of per user proxy","title":"Ssh Vnc Reverse Proxy"},{"location":"docs/praxes/ssh_vnc_reverse_proxy/#vnc-reverse-proxy","text":"In order to create a reverse proxy, you will need access to the server behind the firewall and a computer with a static IP address to proxy/receive the connection from your laptop.","title":"VNC Reverse Proxy"},{"location":"docs/praxes/ssh_vnc_reverse_proxy/#steps","text":"Setup - proxy server/computer Make sure it has a static IP and that the sshd server is active Set the sshd_config 's GatewayPorts clientspecified - this is used to allow any domain to hit the proxy Installation - computer/server behind the firewall apt install autossh tightvncserver xfce4 xfce4-goodies firefox store the vnc server password somewhere safe, choose connection 1 as that corresponds to port 5901 Write a systemd unit for connecting to the proxy replace your_username_here with your username and 1.2.3.4 with the IP or DNS hostname of your proxy server Install the systemd service, restart the daemon , start it, and enable it. ```[Unit] Description=AutoSSH Tunnel After=network.target [Service] User=your_username_here Environment=\"AUTOSSH_GATETIME=0\" ExecStart=/usr/bin/autossh -M 0 -o \"ServerAliveInterval 30\" -o \"ServerAliveCountMax 3\" -NR *:5901:localhost:5901 your_username_here@1.2.3.4 -p 22 [Install] WantedBy=multi-user.target ``` Connect to vnc server use the default mac client $ open vnc://1.2.3.4:5901 you should not need to specify a username or anything else or use a specialized client","title":"Steps"},{"location":"docs/praxes/ssh_vnc_reverse_proxy/#future","text":"Configure the tightvncserver service or pick a different one if preferred. Consider better macos, windows, linux vnc clients and special configuration options Option: per-user vnc connection instead of per user proxy","title":"Future"},{"location":"docs/praxes/using-scad-clj/","text":"Howto: Using the scad-clj OpenSCAD DSL on the CLI This DSL domain specific language was used by adereth to make the dactyl keyboard . This howto is based on Adereth's blog post . OpenSCAD becomes insane after awhile and what it needs most is lisp, because everything needs lisp. Install leiningen What is leiningen ? There are a lot of ways to do this. check out the leiningen website macos: brew install leiningen On 2017/12/28 the project page says: be sure you get version 2.x Check your version in a shell $ lein -v Leiningen 2 .8.1 on Java 1 .8.0_144 Java HotSpot ( TM ) 64 -Bit Server VM Get scad-clj Available on github: https://github.com/farrellm/scad-clj Quickstart! Based on Adereth's 2014/3/19 Post: 3d printing with Clojure Save this code as example.clj in the git repository scad-clj that you just cloned: ;; import scad - clj objects or something ( ns scad - demo . core (: use [ scad - clj . scad ]) (: use [ scad - clj . model ])) ;; make something called primitives ( def primitives ( sphere 50 )) ;; export primitives to scad ( spit \"example.scad\" ( write - scad primitives )) In a shell, cd into the scad-clj project directory: cd scad-clj Run the example.clj file: $ lein repl < example.clj Start the OpenSCAD program Navigate to and open the generated example.scad in OpenSCAD You can now make changes to example.clj as you wish, recompile them, and reload the file in OpenSCAD. As an example, try changing the sphere to size 50 in example.clj run the repl command your OpenSCAD instance should auto reload If this setting is not already chosen it is at (see the menu - TODO, add exact file->location_name ) If not, choose file->reload or CMD+r on a mac. Todo: run from your own project directory , not scad-clj . Otherwise it's messy and hard to keep stuff under source control. Use adereth's dactyl project as a template (avoid users needing to know much about clojure/lein/OpenSCAD before starting) References OpenSCAD User Manual/The OpenSCAD Language scad-clj source code (includes compiler) Adereth's Blog Post","title":"Using Scad Clj"},{"location":"docs/praxes/using-scad-clj/#howto-using-the-scad-clj-openscad-dsl-on-the-cli","text":"This DSL domain specific language was used by adereth to make the dactyl keyboard . This howto is based on Adereth's blog post . OpenSCAD becomes insane after awhile and what it needs most is lisp, because everything needs lisp.","title":"Howto: Using the scad-clj OpenSCAD DSL on the CLI"},{"location":"docs/praxes/using-scad-clj/#install-leiningen","text":"What is leiningen ? There are a lot of ways to do this. check out the leiningen website macos: brew install leiningen On 2017/12/28 the project page says: be sure you get version 2.x","title":"Install leiningen"},{"location":"docs/praxes/using-scad-clj/#check-your-version-in-a-shell","text":"$ lein -v Leiningen 2 .8.1 on Java 1 .8.0_144 Java HotSpot ( TM ) 64 -Bit Server VM","title":"Check your version in a shell"},{"location":"docs/praxes/using-scad-clj/#get-scad-clj","text":"Available on github: https://github.com/farrellm/scad-clj","title":"Get scad-clj"},{"location":"docs/praxes/using-scad-clj/#quickstart","text":"Based on Adereth's 2014/3/19 Post: 3d printing with Clojure Save this code as example.clj in the git repository scad-clj that you just cloned: ;; import scad - clj objects or something ( ns scad - demo . core (: use [ scad - clj . scad ]) (: use [ scad - clj . model ])) ;; make something called primitives ( def primitives ( sphere 50 )) ;; export primitives to scad ( spit \"example.scad\" ( write - scad primitives )) In a shell, cd into the scad-clj project directory: cd scad-clj Run the example.clj file: $ lein repl < example.clj Start the OpenSCAD program Navigate to and open the generated example.scad in OpenSCAD You can now make changes to example.clj as you wish, recompile them, and reload the file in OpenSCAD. As an example, try changing the sphere to size 50 in example.clj run the repl command your OpenSCAD instance should auto reload If this setting is not already chosen it is at (see the menu - TODO, add exact file->location_name ) If not, choose file->reload or CMD+r on a mac. Todo: run from your own project directory , not scad-clj . Otherwise it's messy and hard to keep stuff under source control. Use adereth's dactyl project as a template (avoid users needing to know much about clojure/lein/OpenSCAD before starting)","title":"Quickstart!"},{"location":"docs/praxes/using-scad-clj/#references","text":"OpenSCAD User Manual/The OpenSCAD Language scad-clj source code (includes compiler) Adereth's Blog Post","title":"References"},{"location":"docs/praxes/vacation_july_2023/","text":"Vacation 2023 Some time to focus on my way of being. Look back at 2023 New Year Goals My Analysis: \"it seems like i can just read scifi, workout, and program c++ for the rest of the year, and work on my creativity process which is my top one right now.\" Lose 8 lbs need to start doing this, i know exactly what to do. i can be done by october if I start by the end of vacation. tentative start date: 2023-7-27 goals: don't eat any burgers/fries, indian, pizza 1 cheat meal per week, historically do it on a wednesday probably want to leave it up to me to decide when Keep participating actively and doing recall on my personal training TODO - add my new personal fitness goals to my 2023 goals mobility - shoulders, hips, ?? compound weightlifting practice (squats, deadlifts, etc) \"at home\" practice better fitness \"goalsetting\" what else? Work on my creative process TODO - eed to review my summaries for the Michalko books, and keep reading. TODO - Write a \"creative process\" markdown / outline / cliff notes for reviewing TODO - review the learning how to learn stuff in the context of creativity ONGOING - Find creative applications in my every day life Write c++ I'm not really listless here so much as \"uncollected\" TODO: get collected in my c++ learning TODO - review the learning how to learn stuff in the context of c++ TODO: consider if I should learn java this year based on my H2 goals. Read scifi Goal: none yet, keep reading what I am reading in the gym Can I add a paper book? Do I have too much reading going on already? I have had a lot of boring scifi misses or light scifi. I am missing the \"ringworld\" style mindbenders that dream up whole new possibiltiies. I would like to: maintain a clear mind keep space in every thought and decision for innovation or creativity maintain my practices for: diet, fitness, and meditation focus on big lifts not get caught in the weeds of a particular lift Non Goals No \"catching up\" small projects fit in my regular life don't waste big blocks of time on small projects resist \"catching up\", it doesn't exist No \"catching up\" with books this is part of the regular practice if there is a book, it should be related to my \"vacation projects\" No discord / slack / hacker news / reddit don't read the news, just take the time off don't get on weird tangents No code for the sake of code I get enough of this this fits in the \"small projects\" that fit in my regular life No Dragonrealms Spent enough time here, this is just for tinkering This is tiny projects not worth a big block of time No Home Network & Home Automation This isn't important This is fun to tinker with, but it's a good side project for smaller blocks of time No Financial Planning I have a full 10-11 year financial plan and it is on track Any investment in this is overinvestment No Apartment/Housing Pain Points Discussing any housing situation changes Materially improving our current apartment No Professional Development I can work on this after vacation I just finished a major milestone and have room to breathe this is doing fine Goals set SMART goals for my goals/visions For broad goals/visions, set a few more specific SMART goals have an optimized diet and improve my practice impove my meditation practice break the habit mold of my exercise repeatibly leverage learning, pratice, and trainer Vacation Projects Question: how will I balance deep dives / \"big blocks\" with \"new discovery\" Things I am interested in: 1. woodworking 2. c++ 3. cross compiling c++ - for esp32 - for openwrt 4. embedded controllers 5. leveraging llms - don't want to rabbit hole - i will have this at work when I get back, for free 6. self documentation - i have been doing this on the weekends - might be worth a big block to: 1. enumerate this stuff 2. write a basic gpt4 assisted doc for each 7. inventors and creativity Documentation List of things I would like to document diet: just start with current practice, let it flow not a huge priority, but want to get the draft down meditation: current practice learning: learning how to learn / habit forming + chunking + ? exercise: practice, current, and some alternatives and swapping in this is intended to be documented once then improved immediately and radically Woodworking Idea: focus on copying others' designs to offload goal setting workload Goal: Less planning, more small scale executive, more with the hands Personal Maintenance Vision: Document what I am doing in terms of maintenance so I can improve over time in a directed way. Overarching goal: Use my markdown outlines and openai to standardize my important personal management practices. Daily Skill Building Spend some time every day writing down all my practices spend some time with the creativity books every day Meditation write down some core of my practice into markdown consistent daily practice improve daily mindfulness and awareness find some new meditations to listen to do some directed research Exercise everything i learn will be well documented to carry forwards break out of my typical exercise routine extra time in the gym research adian's ideas and expand on them decouple some exercise routine from the gym, using substitution and alternative goals Diet done eating by 5 PM eat from the refrigerator solid well planned daily diet no special foods, really eat regularly and healthily no upset stomach","title":"Vacation July 2023"},{"location":"docs/praxes/vacation_july_2023/#vacation-2023","text":"Some time to focus on my way of being.","title":"Vacation 2023"},{"location":"docs/praxes/vacation_july_2023/#look-back-at-2023-new-year-goals","text":"My Analysis: \"it seems like i can just read scifi, workout, and program c++ for the rest of the year, and work on my creativity process which is my top one right now.\"","title":"Look back at 2023 New Year Goals"},{"location":"docs/praxes/vacation_july_2023/#lose-8-lbs","text":"need to start doing this, i know exactly what to do. i can be done by october if I start by the end of vacation. tentative start date: 2023-7-27 goals: don't eat any burgers/fries, indian, pizza 1 cheat meal per week, historically do it on a wednesday probably want to leave it up to me to decide when","title":"Lose 8 lbs"},{"location":"docs/praxes/vacation_july_2023/#keep-participating-actively-and-doing-recall-on-my-personal-training","text":"TODO - add my new personal fitness goals to my 2023 goals mobility - shoulders, hips, ?? compound weightlifting practice (squats, deadlifts, etc) \"at home\" practice better fitness \"goalsetting\" what else?","title":"Keep participating actively and doing recall on my personal training"},{"location":"docs/praxes/vacation_july_2023/#work-on-my-creative-process","text":"TODO - eed to review my summaries for the Michalko books, and keep reading. TODO - Write a \"creative process\" markdown / outline / cliff notes for reviewing TODO - review the learning how to learn stuff in the context of creativity ONGOING - Find creative applications in my every day life","title":"Work on my creative process"},{"location":"docs/praxes/vacation_july_2023/#write-c","text":"I'm not really listless here so much as \"uncollected\" TODO: get collected in my c++ learning TODO - review the learning how to learn stuff in the context of c++ TODO: consider if I should learn java this year based on my H2 goals.","title":"Write c++"},{"location":"docs/praxes/vacation_july_2023/#read-scifi","text":"Goal: none yet, keep reading what I am reading in the gym Can I add a paper book? Do I have too much reading going on already? I have had a lot of boring scifi misses or light scifi. I am missing the \"ringworld\" style mindbenders that dream up whole new possibiltiies.","title":"Read scifi"},{"location":"docs/praxes/vacation_july_2023/#i-would-like-to","text":"maintain a clear mind keep space in every thought and decision for innovation or creativity maintain my practices for: diet, fitness, and meditation focus on big lifts not get caught in the weeds of a particular lift","title":"I would like to:"},{"location":"docs/praxes/vacation_july_2023/#non-goals","text":"No \"catching up\" small projects fit in my regular life don't waste big blocks of time on small projects resist \"catching up\", it doesn't exist No \"catching up\" with books this is part of the regular practice if there is a book, it should be related to my \"vacation projects\" No discord / slack / hacker news / reddit don't read the news, just take the time off don't get on weird tangents No code for the sake of code I get enough of this this fits in the \"small projects\" that fit in my regular life No Dragonrealms Spent enough time here, this is just for tinkering This is tiny projects not worth a big block of time No Home Network & Home Automation This isn't important This is fun to tinker with, but it's a good side project for smaller blocks of time No Financial Planning I have a full 10-11 year financial plan and it is on track Any investment in this is overinvestment No Apartment/Housing Pain Points Discussing any housing situation changes Materially improving our current apartment No Professional Development I can work on this after vacation I just finished a major milestone and have room to breathe this is doing fine","title":"Non Goals"},{"location":"docs/praxes/vacation_july_2023/#goals","text":"set SMART goals for my goals/visions For broad goals/visions, set a few more specific SMART goals have an optimized diet and improve my practice impove my meditation practice break the habit mold of my exercise repeatibly leverage learning, pratice, and trainer","title":"Goals"},{"location":"docs/praxes/vacation_july_2023/#vacation-projects","text":"Question: how will I balance deep dives / \"big blocks\" with \"new discovery\" Things I am interested in: 1. woodworking 2. c++ 3. cross compiling c++ - for esp32 - for openwrt 4. embedded controllers 5. leveraging llms - don't want to rabbit hole - i will have this at work when I get back, for free 6. self documentation - i have been doing this on the weekends - might be worth a big block to: 1. enumerate this stuff 2. write a basic gpt4 assisted doc for each 7. inventors and creativity","title":"Vacation Projects"},{"location":"docs/praxes/vacation_july_2023/#documentation","text":"","title":"Documentation"},{"location":"docs/praxes/vacation_july_2023/#list-of-things-i-would-like-to-document","text":"diet: just start with current practice, let it flow not a huge priority, but want to get the draft down meditation: current practice learning: learning how to learn / habit forming + chunking + ? exercise: practice, current, and some alternatives and swapping in this is intended to be documented once then improved immediately and radically","title":"List of things I would like to document"},{"location":"docs/praxes/vacation_july_2023/#woodworking","text":"Idea: focus on copying others' designs to offload goal setting workload Goal: Less planning, more small scale executive, more with the hands","title":"Woodworking"},{"location":"docs/praxes/vacation_july_2023/#personal-maintenance","text":"Vision: Document what I am doing in terms of maintenance so I can improve over time in a directed way. Overarching goal: Use my markdown outlines and openai to standardize my important personal management practices.","title":"Personal Maintenance"},{"location":"docs/praxes/vacation_july_2023/#daily-skill-building","text":"Spend some time every day writing down all my practices spend some time with the creativity books every day","title":"Daily Skill Building"},{"location":"docs/praxes/vacation_july_2023/#meditation","text":"write down some core of my practice into markdown consistent daily practice improve daily mindfulness and awareness find some new meditations to listen to do some directed research","title":"Meditation"},{"location":"docs/praxes/vacation_july_2023/#exercise","text":"everything i learn will be well documented to carry forwards break out of my typical exercise routine extra time in the gym research adian's ideas and expand on them decouple some exercise routine from the gym, using substitution and alternative goals","title":"Exercise"},{"location":"docs/praxes/vacation_july_2023/#diet","text":"done eating by 5 PM eat from the refrigerator solid well planned daily diet no special foods, really eat regularly and healthily no upset stomach","title":"Diet"},{"location":"docs/praxes/vim_registers_for_macro_templates/","text":"Managing Registers for Vim Macro Templates Problem: macro templating If you want to slightly modify a macro for special cases, you need to be able to manipulate its register easily. Vim Macro Review In vim, macros can be used for repetitive tasks. The typical use case is to record a macro and play it back when needed. A macro is recorded into a register. You can see your registers by typing reg in the ex prompt. It looks like this: :reg . How to use Macro Templates Macro Templates are not special features, they are simply lines of text you have stored to put back into a register for use as a macro. You could store a file where some lines are macro templates and others have comments. For example, you might paste an existing register, l , with \"lp . Methods for Copying Macros A macro doesn't really exist in vim, it's really a register, e.g. register l that is played back with the macro key, @ , e.g. @l . On any empty line, you can paste an existing register, j , into another register, l : \"jp0\"ld$ In ex mode , use the command: :let @l=@j Example We will use the command buffer as an anonymous buffer to avoid needing to modify a file to modify the register. The example looks like this: q:ij^[0\"ld$:q This example will fill the register l that executes j which moves the cursor down 1 line. You should replace j with any vim macro you wish. Breakdown of Example Access the command buffer: q: and enter insert mode with i You may paste a macro template instead of directly entering insert mode To paste directly from register k , type \"kp Make your modifications: j can be replaced by any line representing your macro. Exit insert mode: \u001b Move your text into the l register: 0\"ld$ 0 : go to the beginning of the line \"l : queue up the l register to be yanked d : begin delete at cursor, yanking to l in the process $ : move cursor to where the delete will terminate, the end of the line without the newline, apparently also can be the g_ sequence. Quit command mode: :q Run your macro: @l Detour: The Escape Key In a browser you probably cannot see the escape character, typically rendered as ^[ but as one glyph, \u001b , not two. This character simply means the escape key. You can also do this chord directly to escape, also written as ctrl+[ . It must be typed as the single character \u001b . It is accessed with the \u0016 character followed by the \u001b character: \u0016\u001b In vim this sequence looks like this, ^V^[ , but is only two characters long, not four. The key sequence to type the ^[ character in vim can also be written as ctrl+v ctrl+[ . To get ^V you can type ctrl+v ctrl+v . You should not use ctrl+c (also known as ^C or `) here because it will put you back into ex mode` with your typed command in the ex buffer. We want to stay in the command buffer so we can paste the macro back into the register.","title":"Vim Registers For Macro Templates"},{"location":"docs/praxes/vim_registers_for_macro_templates/#managing-registers-for-vim-macro-templates","text":"","title":"Managing Registers for Vim Macro Templates"},{"location":"docs/praxes/vim_registers_for_macro_templates/#problem-macro-templating","text":"If you want to slightly modify a macro for special cases, you need to be able to manipulate its register easily.","title":"Problem: macro templating"},{"location":"docs/praxes/vim_registers_for_macro_templates/#vim-macro-review","text":"In vim, macros can be used for repetitive tasks. The typical use case is to record a macro and play it back when needed. A macro is recorded into a register. You can see your registers by typing reg in the ex prompt. It looks like this: :reg .","title":"Vim Macro Review"},{"location":"docs/praxes/vim_registers_for_macro_templates/#how-to-use-macro-templates","text":"Macro Templates are not special features, they are simply lines of text you have stored to put back into a register for use as a macro. You could store a file where some lines are macro templates and others have comments. For example, you might paste an existing register, l , with \"lp .","title":"How to use Macro Templates"},{"location":"docs/praxes/vim_registers_for_macro_templates/#methods-for-copying-macros","text":"A macro doesn't really exist in vim, it's really a register, e.g. register l that is played back with the macro key, @ , e.g. @l . On any empty line, you can paste an existing register, j , into another register, l : \"jp0\"ld$ In ex mode , use the command: :let @l=@j","title":"Methods for Copying Macros"},{"location":"docs/praxes/vim_registers_for_macro_templates/#example","text":"We will use the command buffer as an anonymous buffer to avoid needing to modify a file to modify the register. The example looks like this: q:ij^[0\"ld$:q This example will fill the register l that executes j which moves the cursor down 1 line. You should replace j with any vim macro you wish.","title":"Example"},{"location":"docs/praxes/vim_registers_for_macro_templates/#breakdown-of-example","text":"Access the command buffer: q: and enter insert mode with i You may paste a macro template instead of directly entering insert mode To paste directly from register k , type \"kp Make your modifications: j can be replaced by any line representing your macro. Exit insert mode: \u001b Move your text into the l register: 0\"ld$ 0 : go to the beginning of the line \"l : queue up the l register to be yanked d : begin delete at cursor, yanking to l in the process $ : move cursor to where the delete will terminate, the end of the line without the newline, apparently also can be the g_ sequence. Quit command mode: :q Run your macro: @l","title":"Breakdown of Example"},{"location":"docs/praxes/vim_registers_for_macro_templates/#detour-the-escape-key","text":"In a browser you probably cannot see the escape character, typically rendered as ^[ but as one glyph, \u001b , not two. This character simply means the escape key. You can also do this chord directly to escape, also written as ctrl+[ . It must be typed as the single character \u001b . It is accessed with the \u0016 character followed by the \u001b character: \u0016\u001b In vim this sequence looks like this, ^V^[ , but is only two characters long, not four. The key sequence to type the ^[ character in vim can also be written as ctrl+v ctrl+[ . To get ^V you can type ctrl+v ctrl+v . You should not use ctrl+c (also known as ^C or `) here because it will put you back into ex mode` with your typed command in the ex buffer. We want to stay in the command buffer so we can paste the macro back into the register.","title":"Detour: The Escape Key"},{"location":"docs/praxes/wp_backup_migrate/","text":"Basic Backup or Migration Protocols for WordPress Sites A protocol for backing up and/or migrating a Wordpress site. Future Integrate Install Needs section into ansible for ubuntu 16.04 systems. Backup Components This is the same pattern for any modern web application framework. MySQL Database Project Directory Backing up the MySQL Database Get the following from the wp-config.pyp : Database Name Username Password `mysqldump {Database Name} > ~/backups/mywpsite.bkp.yyyymmdd.sql -u {Username} -p Enter password at the prompt Backing up the Project Directory tar -czvf ~/backups/myproject.bkp.yyyymmdd.tar.gz /my/project/root/directory/ Migration Do these in order. Back up the site and copy the tar.gz and the sql files to the new location Rebuilding the project Unzip the tar.gz file into /var/www/websites The full path should be /var/www/websites/www.example.com/www/{wordpress root} Change the permissions of this path: chown -R www-data:www-data {path} If you wish to traverse symlinks, use -H flag. Make a symlink at /var/www/www.example.com to /var/www/websites/www.example.com Saves tons of work later if you need to redirect to another location Set up the MySQL user, database, password on the new location Login to MySQL as the root user: $ mysql -u root -p enter password at prompt create database {Database Name}; create user '{User}'@'localhost' IDENTIFIED BY '{Password}' Does the next step create the user automatically if you don't do this? grant usage on {database}.* to '{User}'@'localhost' identified by '{Password}'; view your changes: mysql> select user, host, password from mysql.user; mysql> FLUSH PRIVILEGES; then mysql> quit; Ensure the wp-config.php has the same Database Name, Username, Password Move the sql file to the wordpress root directory $ wp-cli.phar db import mywpsite.bkp.yyyymmdd.sql wp db import You need wp-cli.phar on your path if it is not already Alternatively put a copy in local directory or specify /path/to/wp-cli.phar If your WordPress site URL has changed Update the database with wp-cli wp-cli is usually aliased to wp wp-cli.phar option update home 'http://www.example.com' wp-cli.phar option update siteurl 'http://www.example.com' If you have urls in your posts, pages, etc. wp-cli.phar search-replace 'example.dev' 'example.com' --skip-columns=guid Configure and restart apache2 Use a template! Generally I just copy another site that follows the same pattern Then search and replace your new website name Store in /etc/apache2/sites-available/{mywebsitename}.conf Make sure your apache logs exist in {projectdirectory}/logs/ For more info, check the path in your apache config file access.log , error.log a2ensite {mywebsitename} then apache2 restart If you have errors, fix this configuration as you fix the error. WP Codex - Changing The Site URL WordPress Requirements WordPress requires a great many packages and configuration settings. Here are some packages that were installed manually on a Ubuntu 14.04 server in the past. apt-get install postfix This is important so WordPress can send mail (doesn't need a real outbound address) This needs configured more completely to try to evade spam filters DigitalOcean WordPress Email Reference FUTURE: There are alternatives like going through a gmail acount with wp-smtp plugin FUTURE: WordPress Contact Form 7 Spam Reference - Apparently there are some nice tricks to avoid being treated as spam? Set up apache2 Virtual Hosts Set up mysql root user Set up php5 modules for apache2 Set up mod-rewrite for apache2 More... Fix the php upload file sizes Directory/File permission fixers (files vs dirs, see snips) for annoying hosts. Other snips from my snips git repo","title":"Wp Backup Migrate"},{"location":"docs/praxes/wp_backup_migrate/#basic-backup-or-migration-protocols-for-wordpress-sites","text":"A protocol for backing up and/or migrating a Wordpress site.","title":"Basic Backup or Migration Protocols for WordPress Sites"},{"location":"docs/praxes/wp_backup_migrate/#future","text":"Integrate Install Needs section into ansible for ubuntu 16.04 systems.","title":"Future"},{"location":"docs/praxes/wp_backup_migrate/#backup","text":"","title":"Backup"},{"location":"docs/praxes/wp_backup_migrate/#components","text":"This is the same pattern for any modern web application framework. MySQL Database Project Directory","title":"Components"},{"location":"docs/praxes/wp_backup_migrate/#backing-up-the-mysql-database","text":"Get the following from the wp-config.pyp : Database Name Username Password `mysqldump {Database Name} > ~/backups/mywpsite.bkp.yyyymmdd.sql -u {Username} -p Enter password at the prompt","title":"Backing up the MySQL Database"},{"location":"docs/praxes/wp_backup_migrate/#backing-up-the-project-directory","text":"tar -czvf ~/backups/myproject.bkp.yyyymmdd.tar.gz /my/project/root/directory/","title":"Backing up the Project Directory"},{"location":"docs/praxes/wp_backup_migrate/#migration","text":"Do these in order. Back up the site and copy the tar.gz and the sql files to the new location Rebuilding the project Unzip the tar.gz file into /var/www/websites The full path should be /var/www/websites/www.example.com/www/{wordpress root} Change the permissions of this path: chown -R www-data:www-data {path} If you wish to traverse symlinks, use -H flag. Make a symlink at /var/www/www.example.com to /var/www/websites/www.example.com Saves tons of work later if you need to redirect to another location Set up the MySQL user, database, password on the new location Login to MySQL as the root user: $ mysql -u root -p enter password at prompt create database {Database Name}; create user '{User}'@'localhost' IDENTIFIED BY '{Password}' Does the next step create the user automatically if you don't do this? grant usage on {database}.* to '{User}'@'localhost' identified by '{Password}'; view your changes: mysql> select user, host, password from mysql.user; mysql> FLUSH PRIVILEGES; then mysql> quit; Ensure the wp-config.php has the same Database Name, Username, Password Move the sql file to the wordpress root directory $ wp-cli.phar db import mywpsite.bkp.yyyymmdd.sql wp db import You need wp-cli.phar on your path if it is not already Alternatively put a copy in local directory or specify /path/to/wp-cli.phar If your WordPress site URL has changed Update the database with wp-cli wp-cli is usually aliased to wp wp-cli.phar option update home 'http://www.example.com' wp-cli.phar option update siteurl 'http://www.example.com' If you have urls in your posts, pages, etc. wp-cli.phar search-replace 'example.dev' 'example.com' --skip-columns=guid Configure and restart apache2 Use a template! Generally I just copy another site that follows the same pattern Then search and replace your new website name Store in /etc/apache2/sites-available/{mywebsitename}.conf Make sure your apache logs exist in {projectdirectory}/logs/ For more info, check the path in your apache config file access.log , error.log a2ensite {mywebsitename} then apache2 restart If you have errors, fix this configuration as you fix the error. WP Codex - Changing The Site URL","title":"Migration"},{"location":"docs/praxes/wp_backup_migrate/#wordpress-requirements","text":"WordPress requires a great many packages and configuration settings. Here are some packages that were installed manually on a Ubuntu 14.04 server in the past. apt-get install postfix This is important so WordPress can send mail (doesn't need a real outbound address) This needs configured more completely to try to evade spam filters DigitalOcean WordPress Email Reference FUTURE: There are alternatives like going through a gmail acount with wp-smtp plugin FUTURE: WordPress Contact Form 7 Spam Reference - Apparently there are some nice tricks to avoid being treated as spam? Set up apache2 Virtual Hosts Set up mysql root user Set up php5 modules for apache2 Set up mod-rewrite for apache2 More... Fix the php upload file sizes Directory/File permission fixers (files vs dirs, see snips) for annoying hosts. Other snips from my snips git repo","title":"WordPress Requirements"},{"location":"docs/praxes/wp_backup_restore/","text":"WordPress Backup and Restore Procedures These procedures have been tested at least once on an ansible managed Ubuntu 16.04 server. The backup and restore procedures are very good automation targets. Automation Constraints URL name length is different than mysql user, database, password maximum length Use sudo -u www-data do-stuff to maintain ownership under apache2 's www-data user. It looks like a lot of PHP5 stuff might break on PHP7. PHP versioning could be very important. PHP versioning creates tons of security concerns. Requires compartmentalization/virtualization WordPress Backup Procedure This backup methodology is generic across projects and databases. The written protocol is specific for apache2 , MySQL , and WordPress . Backup the database $ sudo mysql -e \"show databases; \\q\" $ sudo mysqldump mydbname > ~/mydbname.dump.sql Back up www project root directory, e.g. /var/www/websites/www.example.com Back up the whole wordpress install - it can be used as a complete snapshot The wordpress install is a specific version and is tiny anyways $ cd /var/www/websites/ Prune any big logs in logs : access.log , error.log $ tar -czvf ~/www.example.com.bad.YYYYMMDD.HHMM.tar.gz www.example.com Move the backups from ~ to the appropriate archival location WordPress Restore Procedure Backup the bad database and files. Include bad in the backup filenames. Use the WordPress Backup Procedure Disable the site in apache2 sudo a2dissite www.example.com sudo service apache2 reload Delete the database being overwritten in mysql - feel free to login and combine steps. These are added this way for atomicity.\" $ sudo mysql -e \"DROP DATABASE mydbname; \\q\" $ sudo mysql -e \"CREATE DATABASE wwwthesketchycom; \\q\" $ sudo mysql mydbname < mydbname.bkp.sql User grants stay intact when a database is dropped; no need to modify users Assess and restore the file backup to see which files will be restored. Typically the restore will be the entire public_html directory Delete the old directory that will be replaced. As www-data , restore the backup. cd /var/www/websites rm -rf www.example.com use extra caution, write the command then go back and add the -rf flags. sudo -u www-data tar -xzvf ~/www.thesketchy.com.bkp.YYYYMMDD.HHMM.tar.gz Re-enable the site: sudo a2ensite www.example.com sudo service apache2 reload","title":"Wp Backup Restore"},{"location":"docs/praxes/wp_backup_restore/#wordpress-backup-and-restore-procedures","text":"These procedures have been tested at least once on an ansible managed Ubuntu 16.04 server. The backup and restore procedures are very good automation targets.","title":"WordPress Backup and Restore Procedures"},{"location":"docs/praxes/wp_backup_restore/#automation-constraints","text":"URL name length is different than mysql user, database, password maximum length Use sudo -u www-data do-stuff to maintain ownership under apache2 's www-data user. It looks like a lot of PHP5 stuff might break on PHP7. PHP versioning could be very important. PHP versioning creates tons of security concerns. Requires compartmentalization/virtualization","title":"Automation Constraints"},{"location":"docs/praxes/wp_backup_restore/#wordpress-backup-procedure","text":"This backup methodology is generic across projects and databases. The written protocol is specific for apache2 , MySQL , and WordPress . Backup the database $ sudo mysql -e \"show databases; \\q\" $ sudo mysqldump mydbname > ~/mydbname.dump.sql Back up www project root directory, e.g. /var/www/websites/www.example.com Back up the whole wordpress install - it can be used as a complete snapshot The wordpress install is a specific version and is tiny anyways $ cd /var/www/websites/ Prune any big logs in logs : access.log , error.log $ tar -czvf ~/www.example.com.bad.YYYYMMDD.HHMM.tar.gz www.example.com Move the backups from ~ to the appropriate archival location","title":"WordPress Backup Procedure"},{"location":"docs/praxes/wp_backup_restore/#wordpress-restore-procedure","text":"Backup the bad database and files. Include bad in the backup filenames. Use the WordPress Backup Procedure Disable the site in apache2 sudo a2dissite www.example.com sudo service apache2 reload Delete the database being overwritten in mysql - feel free to login and combine steps. These are added this way for atomicity.\" $ sudo mysql -e \"DROP DATABASE mydbname; \\q\" $ sudo mysql -e \"CREATE DATABASE wwwthesketchycom; \\q\" $ sudo mysql mydbname < mydbname.bkp.sql User grants stay intact when a database is dropped; no need to modify users Assess and restore the file backup to see which files will be restored. Typically the restore will be the entire public_html directory Delete the old directory that will be replaced. As www-data , restore the backup. cd /var/www/websites rm -rf www.example.com use extra caution, write the command then go back and add the -rf flags. sudo -u www-data tar -xzvf ~/www.thesketchy.com.bkp.YYYYMMDD.HHMM.tar.gz Re-enable the site: sudo a2ensite www.example.com sudo service apache2 reload","title":"WordPress Restore Procedure"},{"location":"docs/praxes/wp_install_another/","text":"Another method for installing WordPress Get the WordPress files cd /var/www/websites sudo -u www-data mkdir -p ./public_html/logs sudo -u www-data touch ./public_html/logs/error.log ./public_html/logs/access.log cd public_html sudo -u www-data wp core download INSERT CUSTOM WP CONTENT STEP remove original wp-content download wp-base git repo from taui source, use submodules for 3rd party themes/plugins consider hosting stable mirrors of these 3rd party things and upgrading manually this would be quite possible by simply hosting my own submodules and leaving the 3rd party sources as non upstream Generate the database, user, and password for this WordPress instance Login to MySQL as the root user: $ sudo mysql -u root No password required on MySQL 5.7 (or enter password at prompt on 5.5) note that you must use root system privs to login to root mysql on 5.7 create database {Database Name}; create user '{User}'@'localhost' IDENTIFIED BY '{Password}' Does the next step create the user automatically if you don't do this? GRANT ALL PRIVILEGES ON {db}.* To '{user}'@'localhost' IDENTIFIED BY '{passwd}'; view your changes: mysql> select user, host, password from mysql.user; mysql> FLUSH PRIVILEGES; then mysql> quit; Set the wp-config.php salts and database info according to the MySQL information. sudo -u www-data cp wp-config-example.php wp-config.php sudo -u www-data vim wp-config.php DB_NAME DB_USER DB_PASSWORD DB_HOST $table_prefix Authentication Unique Keys and Salts Use wp-cli for first time install it is usually aliased to wp `sudo -u www-data wp core install --url=www.example.com --title=Example --admin_user=ex-admin --admin_password=123xyz --admin_email=admin@ex.com if installed in a subdirectory www.example.com/subdir then wp option update siteurl http://www.example.com/subdir Future HOW DOES THIS WORK? wp db create - create a new database using the wp-config.php not needed with my manual steps, but would i benefit from it? How about sane default settings from wp-cli? correct url rewrite rule traceback pingback settings in 'reading' or whatever remove tagline!! Enumerate even more sane defaults Create step 2. This will need to: install the custom wp-base enable theme and plugins for wp-base","title":"Wp Install Another"},{"location":"docs/praxes/wp_install_another/#another-method-for-installing-wordpress","text":"Get the WordPress files cd /var/www/websites sudo -u www-data mkdir -p ./public_html/logs sudo -u www-data touch ./public_html/logs/error.log ./public_html/logs/access.log cd public_html sudo -u www-data wp core download INSERT CUSTOM WP CONTENT STEP remove original wp-content download wp-base git repo from taui source, use submodules for 3rd party themes/plugins consider hosting stable mirrors of these 3rd party things and upgrading manually this would be quite possible by simply hosting my own submodules and leaving the 3rd party sources as non upstream Generate the database, user, and password for this WordPress instance Login to MySQL as the root user: $ sudo mysql -u root No password required on MySQL 5.7 (or enter password at prompt on 5.5) note that you must use root system privs to login to root mysql on 5.7 create database {Database Name}; create user '{User}'@'localhost' IDENTIFIED BY '{Password}' Does the next step create the user automatically if you don't do this? GRANT ALL PRIVILEGES ON {db}.* To '{user}'@'localhost' IDENTIFIED BY '{passwd}'; view your changes: mysql> select user, host, password from mysql.user; mysql> FLUSH PRIVILEGES; then mysql> quit; Set the wp-config.php salts and database info according to the MySQL information. sudo -u www-data cp wp-config-example.php wp-config.php sudo -u www-data vim wp-config.php DB_NAME DB_USER DB_PASSWORD DB_HOST $table_prefix Authentication Unique Keys and Salts Use wp-cli for first time install it is usually aliased to wp `sudo -u www-data wp core install --url=www.example.com --title=Example --admin_user=ex-admin --admin_password=123xyz --admin_email=admin@ex.com if installed in a subdirectory www.example.com/subdir then wp option update siteurl http://www.example.com/subdir","title":"Another method for installing WordPress"},{"location":"docs/praxes/wp_install_another/#future","text":"HOW DOES THIS WORK? wp db create - create a new database using the wp-config.php not needed with my manual steps, but would i benefit from it? How about sane default settings from wp-cli? correct url rewrite rule traceback pingback settings in 'reading' or whatever remove tagline!! Enumerate even more sane defaults Create step 2. This will need to: install the custom wp-base enable theme and plugins for wp-base","title":"Future"},{"location":"docs/praxes/training/20230724_training/","text":"Personal Training 20230724 Goal Ideas This is just a rough scratchpad. Compound weightlifting stuff, organize this better squats, deadlifts, i have like 8 others I am interested in, and whatever else too Lose 8 lbs, be at 8% body fat. Current target wt. 190.3 lbs. straightforwards: just 8 weeks of my current cardio/lifting without any cheeseburgers or pizza. I don't need to calorie count based on the low importance of the 8 week timeline. Develop a good routine: Dynamic Warmups before exercise, static stretching after exercise Improve balance in each leg and between legs, half ball stuff, what else? Mobility improve range of motion in shoulders and arms Determine needs for hip mobility general tips really feel and hold the squeeze at the top use a slow negative/eccentric too, 3 seconds up, pause and flex the muscle 2 seconds, 3 seconds down Questions: How often should I foam roll? I don't want to do it like... 6 hours a week... my guess: more is better, watch TV and foam roll like every other day what is the squat case in which I can somehow put strain or sliding on the knees? Maybe it isn't one of my problems? how can i improve mobility to get a bit deeper into my squat? what works the anterior deltoids on the two arm seated cable pull out of A I Y T? Do I have anything in my workouts that works the anterior deltoids? how does holding the squeeze go for say a curl, should i pause halfway down in the eccentric? how do i pause and flex \"at the top\" (or wherever) in other exercises than a pushup? how do you use the 2 lacrosse balls taped together? any more lacrosse ball tips? Body Composition Machine Nothing notable, 11.1% body fat. I think recommended is 10%-20% and minimum acceptable is about 6%. Based on this I don't need to lose any weight and can really only lose 21.9 - (198.3*.06) == 10.0 lbs BUT - all body fat loss is good for my cholesterol, so maybe I will aim for a 7-8% body fat. In this case, lose 21.9 - (198.3*.07) == 8 lbs. Target weight: 190.3 lbs Squats Squat Form to get the leg form, clench your butt and feel the tension pushing your outside feet into the ground and your outside legs flexingand your hips widening outwards knees should be above toes, going straight down squat should be wide, toes might be slightly out, it's based on body type low position is femurs parallel to the ground go straight down, don't tip forwards squat facing and up against the mirror to prevent leaning forwards i didn't do this, but may in the future i didn't tip back when i was holding a ~20 lbs kettlebell upside down and squatting with that if i just do a bunch of squats, will i stop tipping back as I get more stability? when going up activate the glutes A LOT breathing: inhale before going down, part of the way up, start your exhale, queston: is this related to the glute activation time? i will get a feel for it... Squat Stability Two leg squat stability stand on the half ball and squat, hold something for support ensure your feet are even forward and back ball is more advanced, you can also use the big black cube things Single Leg squat Stability stability exercise: stand on the half ball with one foot in the dead center move your other foot in front, then to the side, then back this is not exaggerated, just a few inches on each one, rotate between front, parallel, back, parallel, front, etc. maybe do this 10 times stability is a constant importance, even a 350 lbs squat was able to get to 420 by doing like 100 squats on a half ball muscle imbalance shows up as the fast rocking back and forth on the half ball Pushup Stability pushups on the half ball, don't grip the outsides, keep your hands flat we did this for 5 minutes, I had good pushup stability this was still a great exercise and I should repeat it 3 seconds down, 3 seconds up, 2 second flex at the top flex your muscles manually at the top for 2 seconds this manual activation will improve the burn even stop halfway down and hold it \"time in position\" or something? basically you hold it, that will give a good workout more strengthening in the negative of the weightlifting also pause/hold movement in tension for 2 seconds, e.g. halfway down Two arm seated cable pull Goal: Work the A and I positions into my back and core day, maybe move core day to leg day? Shoulder Mobility, 4 positions: A, I, Y, T I do a 30 deg. bench dumbbell reverse fly in the T and Y positions I felt very weak in the A position, both arms straight pulling down alongside my hips I used the minimum weight didn't really feel the activation much below my shoulderblades need to work this a lot to get these muscles going I felt weaker in the I position, both arms overhead, need to work on this too Broom Handle I should get a broom handle for my house, as this doesn't need to be done in the gym and probably needs done daily. Shoulder mobility find the minimum width where you can very smoothly clear the broom handle from in front of your hips to behind your hips the whole exercise should be smooth, going from front to back, then back to front keep the bar as far away from your body as you can throughout repeat it 15 times or something This is very wide for me, and I should be able to reduce the distance between my hands over time by doing this daily Planks Hold 12\" ball between the elbow and the knee, then hold the opposite leg and arm up and out, at kind of a 45 degree angle Elbow plank should be called \"forearm plank\" keep the weight distributed on my forearms, avoid lots on the elbows. keep the shoulders over the forearms keep a strong stance throughout, try not to sag 4 x 90 second plank is a good benchmark, get it in i don't think elbow should be harder than hand? Foam rolling Tools: foam roller (hard), lacrosse ball Rolling is a misnomer, it should be foam pressing or something. You only roll to find the spot, then you hold it there. lacrosse ball is great, you can go pretty hard, but don't go too hard put a string on a lacrosse ball for using against the wall tape 2 lacrosse balls together for the legs, not sure why You don't need to wait until you are tight to do this, do it early and do it often. Keep the pressure until you feel the release. positions: between the hip flare bone and the hip bone there are muscles that fan out, whatever those are anterior to the fan out is the hip flexor posterior to the fan out is something that needs it too similar to pidgeon to get the muscle outside of the shin - i definitely feel this calves etc classic leg foam rolling, i have done this a hundred times, hit the IT band, anywhere you can feel it, do it unti you get the release Dynamic warmups Dynamic warmup before exercise, static stretching after exercise/cardio (end of workout) For tomorrow: Alternatingly 25x - stand on one foot and sweep my arms up, sort of like a partial squat in the hips and knee. Switch feet each time.","title":"20230724 Training"},{"location":"docs/praxes/training/20230724_training/#personal-training-20230724","text":"","title":"Personal Training 20230724"},{"location":"docs/praxes/training/20230724_training/#goal-ideas","text":"This is just a rough scratchpad. Compound weightlifting stuff, organize this better squats, deadlifts, i have like 8 others I am interested in, and whatever else too Lose 8 lbs, be at 8% body fat. Current target wt. 190.3 lbs. straightforwards: just 8 weeks of my current cardio/lifting without any cheeseburgers or pizza. I don't need to calorie count based on the low importance of the 8 week timeline. Develop a good routine: Dynamic Warmups before exercise, static stretching after exercise Improve balance in each leg and between legs, half ball stuff, what else? Mobility improve range of motion in shoulders and arms Determine needs for hip mobility","title":"Goal Ideas"},{"location":"docs/praxes/training/20230724_training/#general-tips","text":"really feel and hold the squeeze at the top use a slow negative/eccentric too, 3 seconds up, pause and flex the muscle 2 seconds, 3 seconds down","title":"general tips"},{"location":"docs/praxes/training/20230724_training/#questions","text":"How often should I foam roll? I don't want to do it like... 6 hours a week... my guess: more is better, watch TV and foam roll like every other day what is the squat case in which I can somehow put strain or sliding on the knees? Maybe it isn't one of my problems? how can i improve mobility to get a bit deeper into my squat? what works the anterior deltoids on the two arm seated cable pull out of A I Y T? Do I have anything in my workouts that works the anterior deltoids? how does holding the squeeze go for say a curl, should i pause halfway down in the eccentric? how do i pause and flex \"at the top\" (or wherever) in other exercises than a pushup? how do you use the 2 lacrosse balls taped together? any more lacrosse ball tips?","title":"Questions:"},{"location":"docs/praxes/training/20230724_training/#body-composition-machine","text":"Nothing notable, 11.1% body fat. I think recommended is 10%-20% and minimum acceptable is about 6%. Based on this I don't need to lose any weight and can really only lose 21.9 - (198.3*.06) == 10.0 lbs BUT - all body fat loss is good for my cholesterol, so maybe I will aim for a 7-8% body fat. In this case, lose 21.9 - (198.3*.07) == 8 lbs. Target weight: 190.3 lbs","title":"Body Composition Machine"},{"location":"docs/praxes/training/20230724_training/#squats","text":"","title":"Squats"},{"location":"docs/praxes/training/20230724_training/#squat-form","text":"to get the leg form, clench your butt and feel the tension pushing your outside feet into the ground and your outside legs flexingand your hips widening outwards knees should be above toes, going straight down squat should be wide, toes might be slightly out, it's based on body type low position is femurs parallel to the ground go straight down, don't tip forwards squat facing and up against the mirror to prevent leaning forwards i didn't do this, but may in the future i didn't tip back when i was holding a ~20 lbs kettlebell upside down and squatting with that if i just do a bunch of squats, will i stop tipping back as I get more stability? when going up activate the glutes A LOT breathing: inhale before going down, part of the way up, start your exhale, queston: is this related to the glute activation time? i will get a feel for it...","title":"Squat Form"},{"location":"docs/praxes/training/20230724_training/#squat-stability","text":"","title":"Squat Stability"},{"location":"docs/praxes/training/20230724_training/#two-leg-squat-stability","text":"stand on the half ball and squat, hold something for support ensure your feet are even forward and back ball is more advanced, you can also use the big black cube things","title":"Two leg squat stability"},{"location":"docs/praxes/training/20230724_training/#single-leg-squat-stability","text":"stability exercise: stand on the half ball with one foot in the dead center move your other foot in front, then to the side, then back this is not exaggerated, just a few inches on each one, rotate between front, parallel, back, parallel, front, etc. maybe do this 10 times stability is a constant importance, even a 350 lbs squat was able to get to 420 by doing like 100 squats on a half ball muscle imbalance shows up as the fast rocking back and forth on the half ball","title":"Single Leg squat Stability"},{"location":"docs/praxes/training/20230724_training/#pushup-stability","text":"pushups on the half ball, don't grip the outsides, keep your hands flat we did this for 5 minutes, I had good pushup stability this was still a great exercise and I should repeat it 3 seconds down, 3 seconds up, 2 second flex at the top flex your muscles manually at the top for 2 seconds this manual activation will improve the burn even stop halfway down and hold it \"time in position\" or something? basically you hold it, that will give a good workout more strengthening in the negative of the weightlifting also pause/hold movement in tension for 2 seconds, e.g. halfway down","title":"Pushup Stability"},{"location":"docs/praxes/training/20230724_training/#two-arm-seated-cable-pull","text":"Goal: Work the A and I positions into my back and core day, maybe move core day to leg day? Shoulder Mobility, 4 positions: A, I, Y, T I do a 30 deg. bench dumbbell reverse fly in the T and Y positions I felt very weak in the A position, both arms straight pulling down alongside my hips I used the minimum weight didn't really feel the activation much below my shoulderblades need to work this a lot to get these muscles going I felt weaker in the I position, both arms overhead, need to work on this too","title":"Two arm seated cable pull"},{"location":"docs/praxes/training/20230724_training/#broom-handle","text":"I should get a broom handle for my house, as this doesn't need to be done in the gym and probably needs done daily. Shoulder mobility find the minimum width where you can very smoothly clear the broom handle from in front of your hips to behind your hips the whole exercise should be smooth, going from front to back, then back to front keep the bar as far away from your body as you can throughout repeat it 15 times or something This is very wide for me, and I should be able to reduce the distance between my hands over time by doing this daily","title":"Broom Handle"},{"location":"docs/praxes/training/20230724_training/#planks","text":"Hold 12\" ball between the elbow and the knee, then hold the opposite leg and arm up and out, at kind of a 45 degree angle Elbow plank should be called \"forearm plank\" keep the weight distributed on my forearms, avoid lots on the elbows. keep the shoulders over the forearms keep a strong stance throughout, try not to sag 4 x 90 second plank is a good benchmark, get it in i don't think elbow should be harder than hand?","title":"Planks"},{"location":"docs/praxes/training/20230724_training/#foam-rolling","text":"Tools: foam roller (hard), lacrosse ball Rolling is a misnomer, it should be foam pressing or something. You only roll to find the spot, then you hold it there. lacrosse ball is great, you can go pretty hard, but don't go too hard put a string on a lacrosse ball for using against the wall tape 2 lacrosse balls together for the legs, not sure why You don't need to wait until you are tight to do this, do it early and do it often. Keep the pressure until you feel the release. positions: between the hip flare bone and the hip bone there are muscles that fan out, whatever those are anterior to the fan out is the hip flexor posterior to the fan out is something that needs it too similar to pidgeon to get the muscle outside of the shin - i definitely feel this calves etc classic leg foam rolling, i have done this a hundred times, hit the IT band, anywhere you can feel it, do it unti you get the release","title":"Foam rolling"},{"location":"docs/praxes/training/20230724_training/#dynamic-warmups","text":"Dynamic warmup before exercise, static stretching after exercise/cardio (end of workout) For tomorrow: Alternatingly 25x - stand on one foot and sweep my arms up, sort of like a partial squat in the hips and knee. Switch feet each time.","title":"Dynamic warmups"},{"location":"docs/praxes/training/20230727_training/","text":"Training Today Exercises Dynamic Warmup - Lunges with Arms in stirrups lunge forwards and feel the arms pull out use the T and the Y shapes to stretch the arms and shoulders do this for a few minutes Barbell Rack Squats weights: bar, 25s, 35s, 45s I only got like 4 of the barbell+45s, but will be able to do more later SAFETY: when racking, walk bar into the rack all the way, then lower SAFETY: when racking, don't jam your finger pull the bar down onto the traps and engage the lats, keep it locked hands are of a natural distance on the grip, outside the shoulders keep using the broom handle daily to improve the shoulder mobility take one step back from the rack only ensure feet are aligned on a line on the floor get some flat shoes time to squat. Breathe in all the way before lowering activate your abs and core, keep your lats activated, and lower the bar should go STRIGHT DOWN AND UP your butt should not go out a lot your knees should not go forwards, only very slightly at the bottom and stay over your toes, not pass the toes RDL deadlifts? weights: barbell + 25 each I think that means romanian deadlift keep the bar pushing against your legs the whole time keep the lats activated remember feeling with trainer pulling bar away from my legs with a band go from upright to a few inches below the knee hands must be symmetrical on the bar AVOID INJURY: activate the abs and core, otherwise you will activate the back too much balance, step backwards into foot saddle, lunge knee to ground sqeeze the back foot's glute as you get into the position feel the front quad burn, feel the back hip stretch go to the bottom to get your spacing when needed should be a lunge position with front knee over foot Captain's chair: a. 15 both leg raises, don't lower too far, lower abs b. 10 (20 total) - one leg raises alternating c. purpose: improve core to support squats Planning for this week I would like to focus on technique with barbell rack squats my feeling is I could do 4x12 every other day focusing solely on technique in addition to my normal workouts (maybe not leg day) It's important to hit the captain's chair hard to build core stability also do everything else","title":"20230727 Training"},{"location":"docs/praxes/training/20230727_training/#training-today","text":"","title":"Training Today"},{"location":"docs/praxes/training/20230727_training/#exercises","text":"Dynamic Warmup - Lunges with Arms in stirrups lunge forwards and feel the arms pull out use the T and the Y shapes to stretch the arms and shoulders do this for a few minutes Barbell Rack Squats weights: bar, 25s, 35s, 45s I only got like 4 of the barbell+45s, but will be able to do more later SAFETY: when racking, walk bar into the rack all the way, then lower SAFETY: when racking, don't jam your finger pull the bar down onto the traps and engage the lats, keep it locked hands are of a natural distance on the grip, outside the shoulders keep using the broom handle daily to improve the shoulder mobility take one step back from the rack only ensure feet are aligned on a line on the floor get some flat shoes time to squat. Breathe in all the way before lowering activate your abs and core, keep your lats activated, and lower the bar should go STRIGHT DOWN AND UP your butt should not go out a lot your knees should not go forwards, only very slightly at the bottom and stay over your toes, not pass the toes RDL deadlifts? weights: barbell + 25 each I think that means romanian deadlift keep the bar pushing against your legs the whole time keep the lats activated remember feeling with trainer pulling bar away from my legs with a band go from upright to a few inches below the knee hands must be symmetrical on the bar AVOID INJURY: activate the abs and core, otherwise you will activate the back too much balance, step backwards into foot saddle, lunge knee to ground sqeeze the back foot's glute as you get into the position feel the front quad burn, feel the back hip stretch go to the bottom to get your spacing when needed should be a lunge position with front knee over foot Captain's chair: a. 15 both leg raises, don't lower too far, lower abs b. 10 (20 total) - one leg raises alternating c. purpose: improve core to support squats","title":"Exercises"},{"location":"docs/praxes/training/20230727_training/#planning-for-this-week","text":"I would like to focus on technique with barbell rack squats my feeling is I could do 4x12 every other day focusing solely on technique in addition to my normal workouts (maybe not leg day) It's important to hit the captain's chair hard to build core stability also do everything else","title":"Planning for this week"},{"location":"docs/praxes/training/20230803/","text":"Personal Training 20230803 Focused on: romanian deadlifts exercises for squats balance muscles upper abs raises (both raises and twists) Future: will this help me get off my right big toe when walking/running? i am feeling optimisitic might still need someone to help me specifically with this GOAL: get off right big toe during walking/running, prevent damage/arthritis explosiveness any additional mobility stuff? more core - obliques, upper abs, what else? more compound exercises reviewing existing routines Questions In RDLs, how low should I eventually go? Always just beneath the knees or further? If so is there a limit? How long is the pause at the bottom of a RDL? 1 second? 2 seconds? matters? Romanian Deadlifts (RDLs) (barbell) Legs hip width apart hands are at natural resting place of hands when standing typically outside of hips a bit back is always rigid (breathe in at the top to support the trunk) the exhale comes halfway up, with the power throughout the movement, especially at the bottom, you should be able to tap your toes up and down, the weight should be distributed in the meat of foot, never the toes Muscle Engagement keep the lats engaged, pull the bar against your legs at all times keep the traps engaged, like if you were trying to hold a pencil between them keep the core engaged at all times to protect the back which is rigid engage the glutes, which will create a tension pushing out down into the knees/feet don't move the knees/feet, just feel the tension from glutes pushing out Starting Position bend all the way down to bring the weight up, this is a first deadlift but also the starting position. grip the bar using the meat of your hand and thumb, DO NOT dangle from your fingers (damage) high weights you might use a clip in glove/grip so you can lift from your wrist Romanian Deadlift Movement starting at the top, bend as hinge from the hip, sticking your butt out the back should be completely rigid, abs remain engaged keep the barbell against your legs slowly lower the barbell down to just below your knees you are holding your breath, engaging your abs and trunk, engaging your lats and traps, engaging your arms, engaging your glutes to keep force in back of feet, pushing the barbell into your legs brief pause at the bottom, 1-2 seconds (which is it?) maintaining your muscle engagement, raise it back up, especially engaging the glutes and whole posterior change with rigid back, all the muscles above still engaged, come to the top. Squat Form toes out slightly, legs pretty wide, find your squat position... too narrow ruins the squat, i am starting to understand mine, pretty wide. form is good, want to get a deeper dip at the bottom of the squat do normal calf extension stretches every day to get some more flexibility stay well hydrated to prevent muscle tightness Goblet Squats use kettle bells upside down goblet squats to practice going deeper. you can goblet squat a lot, but start gradual. i did 17 KG before, but can probably raise that a lot. trainer mentions very heavy goblet squats. Barbell \"Landmine\" rotation thingie squats keep it nice and slow to properly engage each muscle group do 4 x 12 of these to work on squat depth, squat form, and support muscles barbell with 1 end in the landmine allowing it to rotate up, put a 45 lb plate on it put your hands on the top of the bar standing in a good squat position, lower down all the way into a very deep squat. you will find your proper distance when squatting, adjust accordingly complete the squat with good form, but keep going, all the way up to your tippie toes with your head going under your shoulders and arms fully extended repeat Squat on a Slant Board This engages the quads, good for support do a bunch of these to build up your squat in the quads Reverse Lunges Can be done onto the ankle support pad bar, or a 12\" soft balance pad / plyometrix box start with kettle bell by handle in right hand and right foot forwards and up drop right foot back and hook right ankle on the box/pad lower the body into the reverse lunge, briefly tapping the knee on the ground reverse back up into stance with right foot hovering in front of its resting position use the first to find your proper distance for the left foot make sure the left knee does not go forwards, it should stay behind the left toe repeat 12 times, then switch to left foot Upper ap lying leg raises and twists repeat for 4 sets of 12 reps Lay on the bench and grip the behind-head hand grips for this exercise raise legs to about 70-90 degrees, this is the resting position raise the butt off the mat by kicking legs up, this should engage the upper abs lower the butt, keeping the legs up in the resting position Upper ab and oblique twists when kicking up, twist the body to the left next twist the body to the right repeat for 10 cycles (alternate each side, totaling 10 on each side) i felt very weak at this, need to do it a lot modification: hook the knee onto the side you want to twist and pull the body up","title":"20230803"},{"location":"docs/praxes/training/20230803/#personal-training-20230803","text":"Focused on: romanian deadlifts exercises for squats balance muscles upper abs raises (both raises and twists) Future: will this help me get off my right big toe when walking/running? i am feeling optimisitic might still need someone to help me specifically with this GOAL: get off right big toe during walking/running, prevent damage/arthritis explosiveness any additional mobility stuff? more core - obliques, upper abs, what else? more compound exercises reviewing existing routines","title":"Personal Training 20230803"},{"location":"docs/praxes/training/20230803/#questions","text":"In RDLs, how low should I eventually go? Always just beneath the knees or further? If so is there a limit? How long is the pause at the bottom of a RDL? 1 second? 2 seconds? matters?","title":"Questions"},{"location":"docs/praxes/training/20230803/#romanian-deadlifts-rdls-barbell","text":"Legs hip width apart hands are at natural resting place of hands when standing typically outside of hips a bit back is always rigid (breathe in at the top to support the trunk) the exhale comes halfway up, with the power throughout the movement, especially at the bottom, you should be able to tap your toes up and down, the weight should be distributed in the meat of foot, never the toes","title":"Romanian Deadlifts (RDLs) (barbell)"},{"location":"docs/praxes/training/20230803/#muscle-engagement","text":"keep the lats engaged, pull the bar against your legs at all times keep the traps engaged, like if you were trying to hold a pencil between them keep the core engaged at all times to protect the back which is rigid engage the glutes, which will create a tension pushing out down into the knees/feet don't move the knees/feet, just feel the tension from glutes pushing out","title":"Muscle Engagement"},{"location":"docs/praxes/training/20230803/#starting-position","text":"bend all the way down to bring the weight up, this is a first deadlift but also the starting position. grip the bar using the meat of your hand and thumb, DO NOT dangle from your fingers (damage) high weights you might use a clip in glove/grip so you can lift from your wrist","title":"Starting Position"},{"location":"docs/praxes/training/20230803/#romanian-deadlift-movement","text":"starting at the top, bend as hinge from the hip, sticking your butt out the back should be completely rigid, abs remain engaged keep the barbell against your legs slowly lower the barbell down to just below your knees you are holding your breath, engaging your abs and trunk, engaging your lats and traps, engaging your arms, engaging your glutes to keep force in back of feet, pushing the barbell into your legs brief pause at the bottom, 1-2 seconds (which is it?) maintaining your muscle engagement, raise it back up, especially engaging the glutes and whole posterior change with rigid back, all the muscles above still engaged, come to the top.","title":"Romanian Deadlift Movement"},{"location":"docs/praxes/training/20230803/#squat-form","text":"toes out slightly, legs pretty wide, find your squat position... too narrow ruins the squat, i am starting to understand mine, pretty wide. form is good, want to get a deeper dip at the bottom of the squat do normal calf extension stretches every day to get some more flexibility stay well hydrated to prevent muscle tightness","title":"Squat Form"},{"location":"docs/praxes/training/20230803/#goblet-squats","text":"use kettle bells upside down goblet squats to practice going deeper. you can goblet squat a lot, but start gradual. i did 17 KG before, but can probably raise that a lot. trainer mentions very heavy goblet squats.","title":"Goblet Squats"},{"location":"docs/praxes/training/20230803/#barbell-landmine-rotation-thingie-squats","text":"keep it nice and slow to properly engage each muscle group do 4 x 12 of these to work on squat depth, squat form, and support muscles barbell with 1 end in the landmine allowing it to rotate up, put a 45 lb plate on it put your hands on the top of the bar standing in a good squat position, lower down all the way into a very deep squat. you will find your proper distance when squatting, adjust accordingly complete the squat with good form, but keep going, all the way up to your tippie toes with your head going under your shoulders and arms fully extended repeat","title":"Barbell \"Landmine\" rotation thingie squats"},{"location":"docs/praxes/training/20230803/#squat-on-a-slant-board","text":"This engages the quads, good for support do a bunch of these to build up your squat in the quads","title":"Squat on a Slant Board"},{"location":"docs/praxes/training/20230803/#reverse-lunges","text":"Can be done onto the ankle support pad bar, or a 12\" soft balance pad / plyometrix box start with kettle bell by handle in right hand and right foot forwards and up drop right foot back and hook right ankle on the box/pad lower the body into the reverse lunge, briefly tapping the knee on the ground reverse back up into stance with right foot hovering in front of its resting position use the first to find your proper distance for the left foot make sure the left knee does not go forwards, it should stay behind the left toe repeat 12 times, then switch to left foot","title":"Reverse Lunges"},{"location":"docs/praxes/training/20230803/#upper-ap-lying-leg-raises-and-twists","text":"repeat for 4 sets of 12 reps Lay on the bench and grip the behind-head hand grips for this exercise raise legs to about 70-90 degrees, this is the resting position raise the butt off the mat by kicking legs up, this should engage the upper abs lower the butt, keeping the legs up in the resting position","title":"Upper ap lying leg raises and twists"},{"location":"docs/praxes/training/20230803/#upper-ab-and-oblique-twists","text":"when kicking up, twist the body to the left next twist the body to the right repeat for 10 cycles (alternate each side, totaling 10 on each side) i felt very weak at this, need to do it a lot modification: hook the knee onto the side you want to twist and pull the body up","title":"Upper ab and oblique twists"},{"location":"docs/praxes/training/20230907_training/","text":"Training Session Deadlifts with Viper Grips Was able to do bar+25s easily, with good form Keel the shoulders down and back, pinch a pencil between your shoulderblades Inhale on the way down, exhale on the way up, each of 10 reps Was able to do bar+35s pretty easily as well Feel confident this weight will go up as I keep practicing The gloves should put a lot of the weight onto the wrists be sure to keep the bar tight against the hand and avoid holding it too tight with pinkies the pain I had without was in the left ulnar side (electric shock from pinkie to outside of wrist) Farmer's Walk Did 60s in each hand, used the viper hand grips for this as well. Smaller steps are better! Lower the weights by squatting down with a straight back Walk about 10 meters, turn to the left or right (alternate) and walk back. Keep your chest up and powerful (confident chest) Each step should be well controlled When I was getting tired I really started to feel the same engagement as a squat what I mean is squeezing the knees out and feeling the outsides of the hips engaged I really like this one, but I don't know exactly where the engagement should come from yet spend more time on this next week Hand position is at rest at the sides Avoid - Alternate hand position is hands in front of shoulders at a 45 degree angle to the head, weight nearly over shoulders - max weight for this position was only 35-40 lbs, not sure) Avoid this due to pressure on the wrists Mobility Plank with arms, keep the chest over the hands for a good plankl Weight should NOT be in the legs. To keep yourself honest, plank in socks on a slippery floor. No friction on feet bc no feet support should be used.","title":"20230907 Training"},{"location":"docs/praxes/training/20230907_training/#training-session","text":"","title":"Training Session"},{"location":"docs/praxes/training/20230907_training/#deadlifts-with-viper-grips","text":"Was able to do bar+25s easily, with good form Keel the shoulders down and back, pinch a pencil between your shoulderblades Inhale on the way down, exhale on the way up, each of 10 reps Was able to do bar+35s pretty easily as well Feel confident this weight will go up as I keep practicing The gloves should put a lot of the weight onto the wrists be sure to keep the bar tight against the hand and avoid holding it too tight with pinkies the pain I had without was in the left ulnar side (electric shock from pinkie to outside of wrist)","title":"Deadlifts with Viper Grips"},{"location":"docs/praxes/training/20230907_training/#farmers-walk","text":"Did 60s in each hand, used the viper hand grips for this as well. Smaller steps are better! Lower the weights by squatting down with a straight back Walk about 10 meters, turn to the left or right (alternate) and walk back. Keep your chest up and powerful (confident chest) Each step should be well controlled When I was getting tired I really started to feel the same engagement as a squat what I mean is squeezing the knees out and feeling the outsides of the hips engaged I really like this one, but I don't know exactly where the engagement should come from yet spend more time on this next week Hand position is at rest at the sides Avoid - Alternate hand position is hands in front of shoulders at a 45 degree angle to the head, weight nearly over shoulders - max weight for this position was only 35-40 lbs, not sure) Avoid this due to pressure on the wrists","title":"Farmer's Walk"},{"location":"docs/praxes/training/20230907_training/#mobility","text":"Plank with arms, keep the chest over the hands for a good plankl Weight should NOT be in the legs. To keep yourself honest, plank in socks on a slippery floor. No friction on feet bc no feet support should be used.","title":"Mobility"},{"location":"docs/recipes/Coconut_Chicken_Curry/","text":"Coconut Chicken Curry From: https://www.theendlessmeal.com/creamy-coconut-chicken-curry/ Modification Ideas I used canned chicken (meh) but would prefer to use sliced chicken breast Try replacing the chicken with tofu and vegetable boullion Try replacing olive oil with coconut oil. Why? Might be able to shorten the cook time before adding the coconut milk Ingredients 2 tbsp olive oil 1 yellow onion, diced 1 bulb (10-12 cloves) Garlic, minced or crushed 2 tbsp ginger, diced 28 oz tomatoes, diced - 8x 3.5oz tomatoes 8-16 oz chicken - 1 can chicken Curry Mix Grind the spices together in a coffee grinder. 1 tbsp turmeric 1 tbsp cumin seeds 1 tbsp coriander seed 1 tsp fenugreek seed 1 tsp fennel Additional Spices 2 tsp salt 1 tsp cayenne powder Directions I recommended cooking 2 cups basmati rice. I used a ricemaker. Saute the diced onion, garlic, and ginger in 2 tbsp olive oil Stir in the Curry Mix and Additonal Spices and saute for 1 minute Stir in chicken coating with spices, then stir in the diced tomato fully Cook on low for 20 minutes with a lid, stirring frequently Add a can of coconut milk, cook for an additional 5 minutes Serve on a plate","title":"Coconut Chicken Curry"},{"location":"docs/recipes/Coconut_Chicken_Curry/#coconut-chicken-curry","text":"From: https://www.theendlessmeal.com/creamy-coconut-chicken-curry/","title":"Coconut Chicken Curry"},{"location":"docs/recipes/Coconut_Chicken_Curry/#modification-ideas","text":"I used canned chicken (meh) but would prefer to use sliced chicken breast Try replacing the chicken with tofu and vegetable boullion Try replacing olive oil with coconut oil. Why? Might be able to shorten the cook time before adding the coconut milk","title":"Modification Ideas"},{"location":"docs/recipes/Coconut_Chicken_Curry/#ingredients","text":"2 tbsp olive oil 1 yellow onion, diced 1 bulb (10-12 cloves) Garlic, minced or crushed 2 tbsp ginger, diced 28 oz tomatoes, diced - 8x 3.5oz tomatoes 8-16 oz chicken - 1 can chicken","title":"Ingredients"},{"location":"docs/recipes/Coconut_Chicken_Curry/#curry-mix","text":"Grind the spices together in a coffee grinder. 1 tbsp turmeric 1 tbsp cumin seeds 1 tbsp coriander seed 1 tsp fenugreek seed 1 tsp fennel","title":"Curry Mix"},{"location":"docs/recipes/Coconut_Chicken_Curry/#additional-spices","text":"2 tsp salt 1 tsp cayenne powder","title":"Additional Spices"},{"location":"docs/recipes/Coconut_Chicken_Curry/#directions","text":"I recommended cooking 2 cups basmati rice. I used a ricemaker. Saute the diced onion, garlic, and ginger in 2 tbsp olive oil Stir in the Curry Mix and Additonal Spices and saute for 1 minute Stir in chicken coating with spices, then stir in the diced tomato fully Cook on low for 20 minutes with a lid, stirring frequently Add a can of coconut milk, cook for an additional 5 minutes Serve on a plate","title":"Directions"},{"location":"docs/references/2018_election_information/","text":"2018 Election Information How do I best reduce which elections exist in all USA governments in 2018? Census of Governments (COG): https://www.census.gov/govs A census of governments is run by the US federal government every 5 years, in years ending in 2 and 7 . I will be using derivative data sources, so this may not be used, or may be used to validate completeness. Each government is assigned a GID, the 2007 GID lookup is here . The 2017 COG is expected to conclude in September 2018 . Code for America has outlined a project attempting to work with this data , and may still be working with this. Wikipedia historically keeps good records For streaming changes, Wikipedia might be the best bet. United States Elections, 2018 Reddit Politics - https://www.reddit.com/r/politics Biased view, but generally in my direction. Has good data. Reddit Calendar of Primaries 2018 Politico Election Results - https://www.politico.com Midterm Election Schedule 2018: Primary and Registration Dates They don't even have CA Lieutenant Governor, why?","title":"2018 Election Information"},{"location":"docs/references/2018_election_information/#2018-election-information","text":"How do I best reduce which elections exist in all USA governments in 2018?","title":"2018 Election Information"},{"location":"docs/references/2018_election_information/#census-of-governments-cog-httpswwwcensusgovgovs","text":"A census of governments is run by the US federal government every 5 years, in years ending in 2 and 7 . I will be using derivative data sources, so this may not be used, or may be used to validate completeness. Each government is assigned a GID, the 2007 GID lookup is here . The 2017 COG is expected to conclude in September 2018 . Code for America has outlined a project attempting to work with this data , and may still be working with this.","title":"Census of Governments (COG): https://www.census.gov/govs"},{"location":"docs/references/2018_election_information/#wikipedia-historically-keeps-good-records","text":"For streaming changes, Wikipedia might be the best bet. United States Elections, 2018","title":"Wikipedia historically keeps good records"},{"location":"docs/references/2018_election_information/#reddit-politics-httpswwwredditcomrpolitics","text":"Biased view, but generally in my direction. Has good data. Reddit Calendar of Primaries 2018","title":"Reddit Politics - https://www.reddit.com/r/politics"},{"location":"docs/references/2018_election_information/#politico-election-results-httpswwwpoliticocom","text":"Midterm Election Schedule 2018: Primary and Registration Dates They don't even have CA Lieutenant Governor, why?","title":"Politico Election Results - https://www.politico.com"},{"location":"docs/references/BranchPythonOperator_Concepts/","text":"BranchPythonOperator There isn't very good documentation for this feature yet. Why? The BranchPythonOperator is used to create control flow in a DAG . Towards Automating Changes to Data If there is unexpected input from a data source, then automate preprocessing the new data format so the automation can be improved. NB: This type of branch would probably trigger another DAG. Inter-task communication There are two options: variables XComs Variables sit in a global variables object, where as XComs are pushed and pulled between tasks. For task-to-task communication, we will use XComs . Passing Context to BranchPythonOperator BranchPythonOperator inherits from PythonOperator and is defined in the same module. Both share use of provide_context=True as a keyword argument. If this is passed, the python_callable function must receive **kwargs . The context includes task_instance.xcom_pull which pulls information from other tasks. Notes Each branch must point to a task; if there isn't anything to do, use a DummyOperator . References General apache-airflow on git Airflow 'gitter' chat Common Pitfalls (Official) medium/handy-tech: Airflow Tips, Tricks, and Pitfalls Branching & XComs NB: subdags are being deprecated in the future in favor of triggering another dag Examples Example: XCom Example: Branch Operator Concepts & Tutorials Concepts Concepts: Branching Concepts: XComs Tutorial: Instantiate a DAG Default Arguments Template Variables & Macros ETL with Airflow: Principles Airflow CLI - Command Line Interface API Reference BaseOperator TaskInstance.xcom_pull BaseOperator.xcom_pull imports TaskInstance.xcom_pull from context You must pass key=None or any desired key/value to get tasks that are from xcom_push By default tasks from xcom_push are ignored Source Code BashOperator BaseOperator PythonOperator & BranchPythonOperator SSHExecuteOperator xcom_push inherited from BaseOperator BaseOperator imports TaskInstance.xcom_push from context","title":"Branchpythonoperator Concepts"},{"location":"docs/references/BranchPythonOperator_Concepts/#branchpythonoperator","text":"There isn't very good documentation for this feature yet.","title":"BranchPythonOperator"},{"location":"docs/references/BranchPythonOperator_Concepts/#why","text":"The BranchPythonOperator is used to create control flow in a DAG .","title":"Why?"},{"location":"docs/references/BranchPythonOperator_Concepts/#towards-automating-changes-to-data","text":"If there is unexpected input from a data source, then automate preprocessing the new data format so the automation can be improved. NB: This type of branch would probably trigger another DAG.","title":"Towards Automating Changes to Data"},{"location":"docs/references/BranchPythonOperator_Concepts/#inter-task-communication","text":"There are two options: variables XComs Variables sit in a global variables object, where as XComs are pushed and pulled between tasks. For task-to-task communication, we will use XComs .","title":"Inter-task communication"},{"location":"docs/references/BranchPythonOperator_Concepts/#passing-context-to-branchpythonoperator","text":"BranchPythonOperator inherits from PythonOperator and is defined in the same module. Both share use of provide_context=True as a keyword argument. If this is passed, the python_callable function must receive **kwargs . The context includes task_instance.xcom_pull which pulls information from other tasks.","title":"Passing Context to BranchPythonOperator"},{"location":"docs/references/BranchPythonOperator_Concepts/#notes","text":"Each branch must point to a task; if there isn't anything to do, use a DummyOperator .","title":"Notes"},{"location":"docs/references/BranchPythonOperator_Concepts/#references","text":"","title":"References"},{"location":"docs/references/BranchPythonOperator_Concepts/#general","text":"apache-airflow on git Airflow 'gitter' chat Common Pitfalls (Official) medium/handy-tech: Airflow Tips, Tricks, and Pitfalls Branching & XComs NB: subdags are being deprecated in the future in favor of triggering another dag","title":"General"},{"location":"docs/references/BranchPythonOperator_Concepts/#examples","text":"Example: XCom Example: Branch Operator","title":"Examples"},{"location":"docs/references/BranchPythonOperator_Concepts/#concepts-tutorials","text":"Concepts Concepts: Branching Concepts: XComs Tutorial: Instantiate a DAG Default Arguments Template Variables & Macros ETL with Airflow: Principles Airflow CLI - Command Line Interface","title":"Concepts & Tutorials"},{"location":"docs/references/BranchPythonOperator_Concepts/#api-reference","text":"BaseOperator TaskInstance.xcom_pull BaseOperator.xcom_pull imports TaskInstance.xcom_pull from context You must pass key=None or any desired key/value to get tasks that are from xcom_push By default tasks from xcom_push are ignored","title":"API Reference"},{"location":"docs/references/BranchPythonOperator_Concepts/#source-code","text":"BashOperator BaseOperator PythonOperator & BranchPythonOperator SSHExecuteOperator xcom_push inherited from BaseOperator BaseOperator imports TaskInstance.xcom_push from context","title":"Source Code"},{"location":"docs/references/aws-certs-and-trainings/","text":"AWS Certifications A redux for navigating the world of AWS certification. Canonical Certification Resource Certification Benefits Learning Paths Optional \"foundational certification\": AWS Certified Cloud Practitioner Certification FAQ There are 4 learning paths Cloud Practitioner (foundational) Solutions Architect Developer Operations Associate Level Certificates AWS Certified Solutions Architect \u2013 Associate AWS Certified Developer - Associate AWS Certified SysOps Administrator - Associate Other Certificates Check the available certificates There are no prerequisites for any certificates. Currently there are the following quantity of certificates: 1 foundational 3 associate 2 professional 5 specialty Recertification Certificates are valid for 3 years, recertification is apparently half price. professional recertifications also cover the associate certificate for the learning path path. It isn't clear -- it looks like the \"Devops Engineer - Professional\" certificate renews either, or both, SysOps Administrator - Associate and Developer - Associate certificates. Is it either or is it both? Validation You can validate someone's certificate number here Training Resources There are free training resources on the learning paths page . aws.training [Primary resource]((https://www.aws.training/) for scheduling in-person trainings and exams. Schedule online practice exams or in-person real exams Schedule courses aws.training Learning Library This can be tough to search, the filters don't seem super accurate. Free: Exam Readiness: AWS Certified Developer \u2013 Associate (Digital) https://www.aws.training/LearningLibrary Filters: Free, Developer Role, English AWS Resources Canonical Training Resource APN Training - Amazon Partner Network AWS Academy This is for post-secondary institutions (universities) AWS Educate Another academic gateway... AWS Free Courses AWS Cloud Practitioner Essentials (Second Edition Free 6 hour course offered by AWS The free courses are designed to be supplements to APN courses. Udemy Courses Udemy has a ton of competing courses on their platform. Sorting by most reviewed seems helpful... Third party Udemy FAQ Courses are supposedly often about $15 with some 90% off discount applied 1 Most popular Courses (updated 2019-08-23) Stephane Maarek Ultimate AWS Certified Developer Associate 2019 - NEW! Ultimate AWS Certified Solutions Architect Associate 2019 Ryan Kroonenburg & Faye Ellis AWS Certified Developer - Associate 2019 AWS Certified Solutions Architect - Associate 2019 AWS Certified SysOps Administrator - Associate 2019 Backspace Academy Amazon Web Services (AWS) Certified 2019 - 4 Certifications! DolfinEd AWS Certified Solutions Architect - Associate [New Exam] Practice Exams Jon Bonso & Tutorials Dojo AWS Certified Solutions Architect Associate Practice Exams AWS Certified Developer Associate Practice Exams AWS Certified SysOps Administrator Associate Practice Exams AWS Certified Solutions Architect Professional Practice Exam 2018 Developer Course - Freshstart Links JSON {\"title\":\"aws developer cert - current links\",\"date\":\"23/8/2019\",\"tabs\":[{\"title\":\"AWS Cloud Practitioner\",\"url\":\"https://aws.amazon.com/training/path-cloudpractitioner/?tccta=icon\",\"win\":\"406\"},{\"title\":\"Exam Readiness: AWS Certified Developer \u2013 Associate (Digital) | AWS Training & Certification\",\"url\":\"https://www.aws.training/Details/Curriculum?id=19185\",\"win\":\"406\"},{\"title\":\"AWS Cloud Practitioner Essentials (Second Edition) | AWS Training & Certification\",\"url\":\"https://www.aws.training/Details/Curriculum?id=27076\",\"win\":\"406\"},{\"title\":\"Learning Path - Operations\",\"url\":\"https://aws.amazon.com/training/path-operations/\",\"win\":\"406\"},{\"title\":\"AWS Training FAQs\",\"url\":\"https://aws.amazon.com/training/faqs/?nav=tc&loc=8\",\"win\":\"406\"},{\"title\":\"AWS Certified Cloud Practitioner\",\"url\":\"https://aws.amazon.com/certification/certified-cloud-practitioner/\",\"win\":\"406\"},{\"title\":\"Learning Path - Developer\",\"url\":\"https://aws.amazon.com/training/path-developing/\",\"win\":\"406\"},{\"title\":\"APN Partner Training and Certification\",\"url\":\"https://aws.amazon.com/partners/training/\",\"win\":\"406\"}],\"created\":1566600444391}","title":"Aws Certs And Trainings"},{"location":"docs/references/aws-certs-and-trainings/#aws-certifications","text":"A redux for navigating the world of AWS certification. Canonical Certification Resource Certification Benefits","title":"AWS Certifications"},{"location":"docs/references/aws-certs-and-trainings/#learning-paths","text":"Optional \"foundational certification\": AWS Certified Cloud Practitioner Certification FAQ There are 4 learning paths Cloud Practitioner (foundational) Solutions Architect Developer Operations","title":"Learning Paths"},{"location":"docs/references/aws-certs-and-trainings/#associate-level-certificates","text":"AWS Certified Solutions Architect \u2013 Associate AWS Certified Developer - Associate AWS Certified SysOps Administrator - Associate","title":"Associate Level Certificates"},{"location":"docs/references/aws-certs-and-trainings/#other-certificates","text":"Check the available certificates There are no prerequisites for any certificates. Currently there are the following quantity of certificates: 1 foundational 3 associate 2 professional 5 specialty","title":"Other Certificates"},{"location":"docs/references/aws-certs-and-trainings/#recertification","text":"Certificates are valid for 3 years, recertification is apparently half price. professional recertifications also cover the associate certificate for the learning path path. It isn't clear -- it looks like the \"Devops Engineer - Professional\" certificate renews either, or both, SysOps Administrator - Associate and Developer - Associate certificates. Is it either or is it both?","title":"Recertification"},{"location":"docs/references/aws-certs-and-trainings/#validation","text":"You can validate someone's certificate number here","title":"Validation"},{"location":"docs/references/aws-certs-and-trainings/#training-resources","text":"There are free training resources on the learning paths page .","title":"Training Resources"},{"location":"docs/references/aws-certs-and-trainings/#awstraining","text":"[Primary resource]((https://www.aws.training/) for scheduling in-person trainings and exams. Schedule online practice exams or in-person real exams Schedule courses","title":"aws.training"},{"location":"docs/references/aws-certs-and-trainings/#awstraining-learning-library","text":"This can be tough to search, the filters don't seem super accurate. Free: Exam Readiness: AWS Certified Developer \u2013 Associate (Digital) https://www.aws.training/LearningLibrary Filters: Free, Developer Role, English","title":"aws.training Learning Library"},{"location":"docs/references/aws-certs-and-trainings/#aws-resources","text":"Canonical Training Resource APN Training - Amazon Partner Network AWS Academy This is for post-secondary institutions (universities) AWS Educate Another academic gateway...","title":"AWS Resources"},{"location":"docs/references/aws-certs-and-trainings/#aws-free-courses","text":"AWS Cloud Practitioner Essentials (Second Edition Free 6 hour course offered by AWS The free courses are designed to be supplements to APN courses.","title":"AWS Free Courses"},{"location":"docs/references/aws-certs-and-trainings/#udemy-courses","text":"Udemy has a ton of competing courses on their platform. Sorting by most reviewed seems helpful... Third party Udemy FAQ Courses are supposedly often about $15 with some 90% off discount applied 1","title":"Udemy Courses"},{"location":"docs/references/aws-certs-and-trainings/#most-popular-courses-updated-2019-08-23","text":"Stephane Maarek Ultimate AWS Certified Developer Associate 2019 - NEW! Ultimate AWS Certified Solutions Architect Associate 2019 Ryan Kroonenburg & Faye Ellis AWS Certified Developer - Associate 2019 AWS Certified Solutions Architect - Associate 2019 AWS Certified SysOps Administrator - Associate 2019 Backspace Academy Amazon Web Services (AWS) Certified 2019 - 4 Certifications! DolfinEd AWS Certified Solutions Architect - Associate [New Exam]","title":"Most popular Courses (updated 2019-08-23)"},{"location":"docs/references/aws-certs-and-trainings/#practice-exams","text":"Jon Bonso & Tutorials Dojo AWS Certified Solutions Architect Associate Practice Exams AWS Certified Developer Associate Practice Exams AWS Certified SysOps Administrator Associate Practice Exams AWS Certified Solutions Architect Professional Practice Exam 2018","title":"Practice Exams"},{"location":"docs/references/aws-certs-and-trainings/#developer-course-freshstart-links-json","text":"{\"title\":\"aws developer cert - current links\",\"date\":\"23/8/2019\",\"tabs\":[{\"title\":\"AWS Cloud Practitioner\",\"url\":\"https://aws.amazon.com/training/path-cloudpractitioner/?tccta=icon\",\"win\":\"406\"},{\"title\":\"Exam Readiness: AWS Certified Developer \u2013 Associate (Digital) | AWS Training & Certification\",\"url\":\"https://www.aws.training/Details/Curriculum?id=19185\",\"win\":\"406\"},{\"title\":\"AWS Cloud Practitioner Essentials (Second Edition) | AWS Training & Certification\",\"url\":\"https://www.aws.training/Details/Curriculum?id=27076\",\"win\":\"406\"},{\"title\":\"Learning Path - Operations\",\"url\":\"https://aws.amazon.com/training/path-operations/\",\"win\":\"406\"},{\"title\":\"AWS Training FAQs\",\"url\":\"https://aws.amazon.com/training/faqs/?nav=tc&loc=8\",\"win\":\"406\"},{\"title\":\"AWS Certified Cloud Practitioner\",\"url\":\"https://aws.amazon.com/certification/certified-cloud-practitioner/\",\"win\":\"406\"},{\"title\":\"Learning Path - Developer\",\"url\":\"https://aws.amazon.com/training/path-developing/\",\"win\":\"406\"},{\"title\":\"APN Partner Training and Certification\",\"url\":\"https://aws.amazon.com/partners/training/\",\"win\":\"406\"}],\"created\":1566600444391}","title":"Developer Course - Freshstart Links JSON"},{"location":"docs/references/bash_and_gnu_tricks/","text":"Tricks in GNU and bash These are combined because you usually mash them together into a result. History Taken from https://www.washington.edu/computing/unix/history.html It is also possible to use certain words from commands and do a regular expression type modifier. This may not be worth learning. !! repeat last command !-n repeat n commands ago, examples: !-2 , repeat 2 commands ago !-1 == !! , repeat last command !n repeat nth command as indexed in history command ! repeats most recent command beginning with strace - trace system calls and signals Example: sudo strace -f -o slack.trace su robbintt -c 'slack' I used this to trace where my ubuntu 16.04 slack app was silently failing. I thought it must be a file permissions error because the command slack would run for root but not for user. Strace showed me the files touched before failing. reverse-I Search Use ctrl+r and start typing. This 'reverse-I-search' is a more convenient way to search history. It is also a nice trick to tag commands you will need. For example: ls -la /some/long/directory # mytag Then just search the tag in reverse i search","title":"Bash And Gnu Tricks"},{"location":"docs/references/bash_and_gnu_tricks/#tricks-in-gnu-and-bash","text":"These are combined because you usually mash them together into a result.","title":"Tricks in GNU and bash"},{"location":"docs/references/bash_and_gnu_tricks/#history","text":"Taken from https://www.washington.edu/computing/unix/history.html It is also possible to use certain words from commands and do a regular expression type modifier. This may not be worth learning. !! repeat last command !-n repeat n commands ago, examples: !-2 , repeat 2 commands ago !-1 == !! , repeat last command !n repeat nth command as indexed in history command ! repeats most recent command beginning with ","title":"History"},{"location":"docs/references/bash_and_gnu_tricks/#strace-trace-system-calls-and-signals","text":"Example: sudo strace -f -o slack.trace su robbintt -c 'slack' I used this to trace where my ubuntu 16.04 slack app was silently failing. I thought it must be a file permissions error because the command slack would run for root but not for user. Strace showed me the files touched before failing.","title":"strace - trace system calls and signals"},{"location":"docs/references/bash_and_gnu_tricks/#reverse-i-search","text":"Use ctrl+r and start typing. This 'reverse-I-search' is a more convenient way to search history. It is also a nice trick to tag commands you will need. For example: ls -la /some/long/directory # mytag Then just search the tag in reverse i search","title":"reverse-I Search"},{"location":"docs/references/bazel_java/","text":"Bazel and Java Installed bazel and adoptopenjdk via homebrew for now. Goal Get a java env up suitable for modern java dev. Make something interesting. Subgoals: easily use tmux+vim to navigate and work build on file change follow modern java patterns maven bazel deploy to aws lambda, ecs, or to local k3s How do I target AWS java No idea, guess I install it and specify it in the bazel build? amazon-corretto-11 amazon-corretto-8 java-1.8.0-openjdk References bazelbuild/rules_jvm_external bazelbuild/bazel: Java and Bazel Bazel Tutorial: Build a Java Project aws lambda: java aws sample java handlers","title":"Bazel Java"},{"location":"docs/references/bazel_java/#bazel-and-java","text":"Installed bazel and adoptopenjdk via homebrew for now.","title":"Bazel and Java"},{"location":"docs/references/bazel_java/#goal","text":"Get a java env up suitable for modern java dev. Make something interesting.","title":"Goal"},{"location":"docs/references/bazel_java/#subgoals","text":"easily use tmux+vim to navigate and work build on file change follow modern java patterns maven bazel deploy to aws lambda, ecs, or to local k3s","title":"Subgoals:"},{"location":"docs/references/bazel_java/#how-do-i-target-aws-java","text":"No idea, guess I install it and specify it in the bazel build? amazon-corretto-11 amazon-corretto-8 java-1.8.0-openjdk","title":"How do I target AWS java"},{"location":"docs/references/bazel_java/#references","text":"bazelbuild/rules_jvm_external bazelbuild/bazel: Java and Bazel Bazel Tutorial: Build a Java Project aws lambda: java aws sample java handlers","title":"References"},{"location":"docs/references/c_programming/","text":"Notes - K&R - The C Programming Language How to read \"statements\" in C (k&r: p. 19) One \"statement\" can be a single statement, like int c; , or a group of statements inside braces A control flow keyword also initiates a single statement: /* this is one statement, even though it is two nested control flow keywords */ while ((c = getchar()) != EOF) if (c == '\\n') ++nl; Assignments associate from right-to-left The following are equivalent: nl = nw = nc = 0 nl = (nw = (nc = 0)) Evaluations with && and || are left-to-right if (c == ' ' || c == '\\n' || c == '\\t') Evaluation stops as soon as truth or falsehood is known, \"short-circuit\" or \"minimal\" evaluation Resources A list of resources, subdivide as it grows. The slideshow that got me started here Originally found here comp.lang.c guide C Standard Library C POSIX Library C++ STL - Standard Template Library gcc docs LLVM Sanitizers (Google) What is the datatype of a pointer in c? henner says: a long in any particular system should be able to hold a pointer Tips on printf (escape sequences) Wikipedia \"Escape sequences in C\" a make guide gnu make guide Ascii table: man ascii Learn x in y minutes: C Definitions gcc - gnu compiler collection gnu binutils - sister project of gcc avr-gcc - version of gcc for the avr class of microcontrollers has 3 available compilers: c , c++ , ada compiler does not assemble or link the final code gas - gnu assembler GNU Libc - GNU C Standard Library AVR Libc - AVR GCC C Standard Library GNU Make - Building software / Makefile stuff Some distributions of the toolchains, and other AVR tools such as MFile, contain a Makefile template written for the AVR toolchain and AVR applications that you can copy and modify for your application. AVRDUDE - program your device avr-gdb , avr-insight , and ddd avr versions of common make tools. AVaRICE - AVaRICE is a back-end program to AVR GDB and interfaces to the Atmel JTAG In-Circuit Emulator (ICE), to provide emulation capabilities. SimulAVR - SimulAVR is an AVR simulator used as a back-end with AVR GDB. SRecord is a collection of powerful tools for manipulating EPROM load files. It reads and writes numerous EPROM file formats, and can perform many different manipulations. MFile is a simple Makefile generator is meant as an aid to quickly customize a Makefile to use for your AVR application. Codebases to read and participate in sqlite3 python3 how 2 be 1337 Knuth Reward Check - In the preface of each of his books and on his website,[7] Knuth offers a reward of $2.56 (USD) to the first person to find each error in his published books, whether it be technical, typographical, or historical. Knuth explains that $2.56, or 256 cents, corresponds to one hexadecimal dollar.[8] \"Valuable suggestions\" are worth 32 cents, or about \u200a1\u20448 of the errors in the book (0.001 hexadecimal dollars or 0.1 hexadecimal cents). In his earlier books a smaller reward was offered. For example, the 2nd edition of The Art of Computer Programming, Volume 1, offered $2.00. Learn C The Hard Way (Zed Shaw) Some notes as I read through lcthw. Quickref : ? (same category as && || ! ) is logical ternary . Expression a:b?c maps to if a then b else c Keywords - Alphabetical case: A branch in a switch-statement. char: Character data type. const: Make a variable unmodifiable. continue: Continue to the top of a loop. default: Default branch in a switch-statement. do: Start a do-while loop. double: A double floating point data type. else: An else branch of an if-statement. enum: Define a set of int constants. extern: Declare an identifier is defined externally. float: A floating point data type. for: Start a for-loop. goto: Jump to a label. if: Starts an if-statement. int: An integer data type. long: A long integer data type. register: Declare a variable be stored in a CPU register. return: Return from a function. short: A short integer data type. signed: A signed modifier for integer data types. sizeof: Determine the size of data. static: Preserve variable value after its scope exits. struct: Combine variables into a single record. switch: Start a switch-statement. typedef: Create a new type. union: Start a union-statement. unsigned: An unsigned modifier for integer data types. void: Declare a data type empty. volatile: Declare a variable might be modified elsewhere. while: Start a while-loop. Keywords - Grouped Note: keywords in C only fall into two categories: data management and control flow Data Types & Modifiers int: An integer data type. long: A long integer data type. short: A short integer data type. signed: A signed modifier for integer data types. unsigned: An unsigned modifier for integer data types. char: Character data type. float: A floating point data type. double: A double floating point data type. const: Make a variable unmodifiable. volatile: Declare a variable might be modified elsewhere. extern: Declare an identifier is defined externally. void: Declare a data type empty. static: Preserve variable value after its scope exits. register: Declare a variable be stored in a CPU register. auto: Give a local variable a local lifetime. Compound Data Types struct: Combine variables into a single record. union: Start a union-statement. enum: Define a set of int constants. typedef: Create a new type. Data Introspection sizeof: Determine the size of data. Control Flow if: Starts an if-statement. else: An else branch of an if-statement. for: Start a for-loop. do: Start a do-while loop. while: Start a while-loop. continue: Continue to the top of a loop. break: Exit out of a compound statement. switch: Start a switch-statement. case: A branch in a switch-statement. default: Default branch in a switch-statement. goto: Jump to a label. return: Return from a function. LCTHW References man 3 printf gdb quickref - learn c the hard way page 36-37 mentions: run, break, backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach pid, detach, list lldb quickref - learn c the hard way page 37-38 mentions: run [args], breakpint set, thread backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach -p pid, detach, list use gdb or lldb to debug your compiled program type run in the debugger command line to run the application a bunch of helpful gdb debugging flags from zed gdb --args ./ex3 myarg1 myarg2 myargetc pass args to program apple: lldb has the same commands available but you have to read the manpages for the llvm names valgrind - track all your memory and tell you when you messed it up gotta know how to work with the heap valgrind ./ex3 apple does not have valgrind: gdb --batch --ex run --ex bt --ex q --args ./ex3 \"a very lame alternative to valgrind, the most useful command for debugging c code\" splint linter address sanitizer - asan new alternative to valgrind that works on osx github.com/google/sanitizers/wiki/AddressSanitizer LCTHW Makefile References always use tabs in Makefile s. Never spaces. -g generate debug information -Wall (gnu gcc) From the manpage: This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. Macros (source) A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls. You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator defined (see Defined) can never be defined as a macro, and C++'s named operators (see C++ Named Operators) cannot be macros when you are compiling C++. Others' Resources zv says: man ld.so - it's worth your time in my view to at least skim the ld.so manpage Mitch says: \"The C Programming Language by Kernighan and Ritchie\" TheAceOfHearts says: \"C is a very small and simple language but the tooling and patterns are old and mysterious.\" make autoconf how the compiler + preprocessors work what do all the flags even mean!?!?! how making cross platform stuff works how to pull in and use c \"libraries\" C-isms how to test etc some platform standards autotools in GNU, msbuild on win Lizzie says: make - Some people do it strangely but ime 90% of makefiles do the exact same thing: \"compile .c files to .o files with CFLAGS. link all the relevant .o files with LDFLAGS\" learn to use asan and ubsan right off the bat. They are compiler extensions for dynamic bounds / overflow checking . asan: Address Sanitizer ubsan: GCC Undefined Behavior Sanitizer -fsanitize=address -fsanitize=undefined learning gdb also helps a lot gdb klib - a fast generic datastructure library for c c Language Lawyer perspective Programming Lanugages - C // International Standard 9899:201x Draft April 2011 Check out struct initializers - not a common pattern but been around for 20 years. c struct mystruct mydata = {.b = c, .d = e}; vs c struct mystruct mydata; memset(&mydata, 0, sizeof(mydata)); mydata.b = c; mydata.d = e; - removes potential bugs: - passing the wrong size to memset - getting the size and value arguments to memset reversed on accident. - using mydata before it's initialized - memsetting a pointer, which is UB - note from henner: - > I am always annoyed that the designated initializers ( { .a = 42} ) don't work in C++. Sometimes I just sprinkle in a C file for initializers","title":"C Programming"},{"location":"docs/references/c_programming/#notes-kr-the-c-programming-language","text":"How to read \"statements\" in C (k&r: p. 19) One \"statement\" can be a single statement, like int c; , or a group of statements inside braces A control flow keyword also initiates a single statement: /* this is one statement, even though it is two nested control flow keywords */ while ((c = getchar()) != EOF) if (c == '\\n') ++nl; Assignments associate from right-to-left The following are equivalent: nl = nw = nc = 0 nl = (nw = (nc = 0)) Evaluations with && and || are left-to-right if (c == ' ' || c == '\\n' || c == '\\t') Evaluation stops as soon as truth or falsehood is known, \"short-circuit\" or \"minimal\" evaluation","title":"Notes - K&R - The C Programming Language"},{"location":"docs/references/c_programming/#resources","text":"A list of resources, subdivide as it grows. The slideshow that got me started here Originally found here comp.lang.c guide C Standard Library C POSIX Library C++ STL - Standard Template Library gcc docs LLVM Sanitizers (Google) What is the datatype of a pointer in c? henner says: a long in any particular system should be able to hold a pointer Tips on printf (escape sequences) Wikipedia \"Escape sequences in C\" a make guide gnu make guide Ascii table: man ascii Learn x in y minutes: C","title":"Resources"},{"location":"docs/references/c_programming/#definitions","text":"gcc - gnu compiler collection gnu binutils - sister project of gcc avr-gcc - version of gcc for the avr class of microcontrollers has 3 available compilers: c , c++ , ada compiler does not assemble or link the final code gas - gnu assembler GNU Libc - GNU C Standard Library AVR Libc - AVR GCC C Standard Library GNU Make - Building software / Makefile stuff Some distributions of the toolchains, and other AVR tools such as MFile, contain a Makefile template written for the AVR toolchain and AVR applications that you can copy and modify for your application. AVRDUDE - program your device avr-gdb , avr-insight , and ddd avr versions of common make tools. AVaRICE - AVaRICE is a back-end program to AVR GDB and interfaces to the Atmel JTAG In-Circuit Emulator (ICE), to provide emulation capabilities. SimulAVR - SimulAVR is an AVR simulator used as a back-end with AVR GDB. SRecord is a collection of powerful tools for manipulating EPROM load files. It reads and writes numerous EPROM file formats, and can perform many different manipulations. MFile is a simple Makefile generator is meant as an aid to quickly customize a Makefile to use for your AVR application.","title":"Definitions"},{"location":"docs/references/c_programming/#codebases-to-read-and-participate-in","text":"sqlite3 python3","title":"Codebases to read and participate in"},{"location":"docs/references/c_programming/#how-2-be-1337","text":"Knuth Reward Check - In the preface of each of his books and on his website,[7] Knuth offers a reward of $2.56 (USD) to the first person to find each error in his published books, whether it be technical, typographical, or historical. Knuth explains that $2.56, or 256 cents, corresponds to one hexadecimal dollar.[8] \"Valuable suggestions\" are worth 32 cents, or about \u200a1\u20448 of the errors in the book (0.001 hexadecimal dollars or 0.1 hexadecimal cents). In his earlier books a smaller reward was offered. For example, the 2nd edition of The Art of Computer Programming, Volume 1, offered $2.00.","title":"how 2 be 1337"},{"location":"docs/references/c_programming/#learn-c-the-hard-way-zed-shaw","text":"Some notes as I read through lcthw.","title":"Learn C The Hard Way (Zed Shaw)"},{"location":"docs/references/c_programming/#quickref","text":": ? (same category as && || ! ) is logical ternary . Expression a:b?c maps to if a then b else c","title":"Quickref"},{"location":"docs/references/c_programming/#keywords-alphabetical","text":"case: A branch in a switch-statement. char: Character data type. const: Make a variable unmodifiable. continue: Continue to the top of a loop. default: Default branch in a switch-statement. do: Start a do-while loop. double: A double floating point data type. else: An else branch of an if-statement. enum: Define a set of int constants. extern: Declare an identifier is defined externally. float: A floating point data type. for: Start a for-loop. goto: Jump to a label. if: Starts an if-statement. int: An integer data type. long: A long integer data type. register: Declare a variable be stored in a CPU register. return: Return from a function. short: A short integer data type. signed: A signed modifier for integer data types. sizeof: Determine the size of data. static: Preserve variable value after its scope exits. struct: Combine variables into a single record. switch: Start a switch-statement. typedef: Create a new type. union: Start a union-statement. unsigned: An unsigned modifier for integer data types. void: Declare a data type empty. volatile: Declare a variable might be modified elsewhere. while: Start a while-loop.","title":"Keywords - Alphabetical"},{"location":"docs/references/c_programming/#keywords-grouped","text":"Note: keywords in C only fall into two categories: data management and control flow","title":"Keywords - Grouped"},{"location":"docs/references/c_programming/#data-types-modifiers","text":"int: An integer data type. long: A long integer data type. short: A short integer data type. signed: A signed modifier for integer data types. unsigned: An unsigned modifier for integer data types. char: Character data type. float: A floating point data type. double: A double floating point data type. const: Make a variable unmodifiable. volatile: Declare a variable might be modified elsewhere. extern: Declare an identifier is defined externally. void: Declare a data type empty. static: Preserve variable value after its scope exits. register: Declare a variable be stored in a CPU register. auto: Give a local variable a local lifetime.","title":"Data Types & Modifiers"},{"location":"docs/references/c_programming/#compound-data-types","text":"struct: Combine variables into a single record. union: Start a union-statement. enum: Define a set of int constants. typedef: Create a new type.","title":"Compound Data Types"},{"location":"docs/references/c_programming/#data-introspection","text":"sizeof: Determine the size of data.","title":"Data Introspection"},{"location":"docs/references/c_programming/#control-flow","text":"if: Starts an if-statement. else: An else branch of an if-statement. for: Start a for-loop. do: Start a do-while loop. while: Start a while-loop. continue: Continue to the top of a loop. break: Exit out of a compound statement. switch: Start a switch-statement. case: A branch in a switch-statement. default: Default branch in a switch-statement. goto: Jump to a label. return: Return from a function.","title":"Control Flow"},{"location":"docs/references/c_programming/#lcthw-references","text":"man 3 printf gdb quickref - learn c the hard way page 36-37 mentions: run, break, backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach pid, detach, list lldb quickref - learn c the hard way page 37-38 mentions: run [args], breakpint set, thread backtrace, print expr, continue, next, step, quit, help, cd, pwd, make, shell, clear, info break, info watch, attach -p pid, detach, list use gdb or lldb to debug your compiled program type run in the debugger command line to run the application a bunch of helpful gdb debugging flags from zed gdb --args ./ex3 myarg1 myarg2 myargetc pass args to program apple: lldb has the same commands available but you have to read the manpages for the llvm names valgrind - track all your memory and tell you when you messed it up gotta know how to work with the heap valgrind ./ex3 apple does not have valgrind: gdb --batch --ex run --ex bt --ex q --args ./ex3 \"a very lame alternative to valgrind, the most useful command for debugging c code\" splint linter address sanitizer - asan new alternative to valgrind that works on osx github.com/google/sanitizers/wiki/AddressSanitizer","title":"LCTHW References"},{"location":"docs/references/c_programming/#lcthw-makefile-references","text":"always use tabs in Makefile s. Never spaces. -g generate debug information -Wall (gnu gcc) From the manpage: This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.","title":"LCTHW Makefile References"},{"location":"docs/references/c_programming/#macros-source","text":"A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls. You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator defined (see Defined) can never be defined as a macro, and C++'s named operators (see C++ Named Operators) cannot be macros when you are compiling C++.","title":"Macros (source)"},{"location":"docs/references/c_programming/#others-resources","text":"zv says: man ld.so - it's worth your time in my view to at least skim the ld.so manpage","title":"Others' Resources"},{"location":"docs/references/c_programming/#mitch-says","text":"\"The C Programming Language by Kernighan and Ritchie\"","title":"Mitch says:"},{"location":"docs/references/c_programming/#theaceofhearts-says","text":"\"C is a very small and simple language but the tooling and patterns are old and mysterious.\" make autoconf how the compiler + preprocessors work what do all the flags even mean!?!?! how making cross platform stuff works how to pull in and use c \"libraries\" C-isms how to test etc some platform standards autotools in GNU, msbuild on win","title":"TheAceOfHearts says:"},{"location":"docs/references/c_programming/#lizzie-says","text":"make - Some people do it strangely but ime 90% of makefiles do the exact same thing: \"compile .c files to .o files with CFLAGS. link all the relevant .o files with LDFLAGS\" learn to use asan and ubsan right off the bat. They are compiler extensions for dynamic bounds / overflow checking . asan: Address Sanitizer ubsan: GCC Undefined Behavior Sanitizer -fsanitize=address -fsanitize=undefined learning gdb also helps a lot gdb klib - a fast generic datastructure library for c c Language Lawyer perspective Programming Lanugages - C // International Standard 9899:201x Draft April 2011 Check out struct initializers - not a common pattern but been around for 20 years. c struct mystruct mydata = {.b = c, .d = e}; vs c struct mystruct mydata; memset(&mydata, 0, sizeof(mydata)); mydata.b = c; mydata.d = e; - removes potential bugs: - passing the wrong size to memset - getting the size and value arguments to memset reversed on accident. - using mydata before it's initialized - memsetting a pointer, which is UB - note from henner: - > I am always annoyed that the designated initializers ( { .a = 42} ) don't work in C++. Sometimes I just sprinkle in a C file for initializers","title":"Lizzie says:"},{"location":"docs/references/corewar/","text":"Core War References corewar.info evolving see 5 articles at the bottom strategy examples pmars ares, zeus, hermes corewin: windows simulator and visualizer Core War: fandom programmer's wiki Corewar: C2 wiki The beginners' guide to Redcode corewars.co.uk tutorials corewar.atspace.com KOTH.org Corewar FAQ Annotated Draft of the Proposed 1994 Core War Standard Includes recommended impementations for using genetic algorithms Also Python mars pycorewar","title":"Corewar"},{"location":"docs/references/corewar/#core-war","text":"","title":"Core War"},{"location":"docs/references/corewar/#references","text":"corewar.info evolving see 5 articles at the bottom strategy examples pmars ares, zeus, hermes corewin: windows simulator and visualizer Core War: fandom programmer's wiki Corewar: C2 wiki The beginners' guide to Redcode corewars.co.uk tutorials corewar.atspace.com KOTH.org Corewar FAQ Annotated Draft of the Proposed 1994 Core War Standard Includes recommended impementations for using genetic algorithms Also Python mars pycorewar","title":"References"},{"location":"docs/references/django-general/","text":"Razzi's Class Django is used in industry! Pinterest, NASA, Venmo, Sighten, Instagram, etc. Overview Django is designed to make development fast... Razzi: \"Django is the present, not the future.\" If you choose an unsupported database, you will be fighting the framework. BUT - Django keeps up with internet trends! So it could end up being the future. If you are not using a relational database, you may not need Django. It's for working with RDBMS. Django can serve REST or GraphQL APIs as well, great backend for modern frontend. For example, Razzi's company switched to Single Page Apps (SPAs) on the frontend with their same django app on the backend (kept old django templates at the time probably) Django Benefits Out-of-the-box functionality: don't reinvent security, authentication sessions, database access, email... Ease of prototyping: easier to start and deploy your project using a well-supported framework Scales well to large teams, large projects Django apps make it easy to split up and reuse functionality django is the present, not the future Designed around rendering html pages If you chose an unsupported database, you'll be fighting the framework The django framework keeps up with internet trends, though, and now supports asynchronous programming Django can serve REST and GraphQL APIs as well, making it a great backend for a modern frontend Django has some premade social networks, we will roll our own Vataxia https://github.com/buckyroberts/Vataxia Bootcamp https://github.com/vitorfs/bootcamp Our Class Schedule Signup / login / logout (today) Posting (March 5, next Monday) Messaging (March 12) API, static frontend (March 19) First Time Setup The manage.py is executable by default in Python 3. Simply ./manage.py runserver or any other argument. You can python manage.py runserver 80 for example, to run on any port. Python 3 in a virtualenv pip install django django-admin startproject python manage.py migrate python manage.py createsuperuser python manage.py startapp social Specific Technologies DocRaptor for html to pdf in Django - Razzi used it at a company. stack overflow","title":"Django General"},{"location":"docs/references/django-general/#razzis-class","text":"Django is used in industry! Pinterest, NASA, Venmo, Sighten, Instagram, etc.","title":"Razzi's Class"},{"location":"docs/references/django-general/#overview","text":"Django is designed to make development fast... Razzi: \"Django is the present, not the future.\" If you choose an unsupported database, you will be fighting the framework. BUT - Django keeps up with internet trends! So it could end up being the future. If you are not using a relational database, you may not need Django. It's for working with RDBMS. Django can serve REST or GraphQL APIs as well, great backend for modern frontend. For example, Razzi's company switched to Single Page Apps (SPAs) on the frontend with their same django app on the backend (kept old django templates at the time probably)","title":"Overview"},{"location":"docs/references/django-general/#django-benefits","text":"Out-of-the-box functionality: don't reinvent security, authentication sessions, database access, email... Ease of prototyping: easier to start and deploy your project using a well-supported framework Scales well to large teams, large projects Django apps make it easy to split up and reuse functionality","title":"Django Benefits"},{"location":"docs/references/django-general/#django-is-the-present-not-the-future","text":"Designed around rendering html pages If you chose an unsupported database, you'll be fighting the framework The django framework keeps up with internet trends, though, and now supports asynchronous programming Django can serve REST and GraphQL APIs as well, making it a great backend for a modern frontend","title":"django is the present, not the future"},{"location":"docs/references/django-general/#django-has-some-premade-social-networks-we-will-roll-our-own","text":"Vataxia https://github.com/buckyroberts/Vataxia Bootcamp https://github.com/vitorfs/bootcamp","title":"Django has some premade social networks, we will roll our own"},{"location":"docs/references/django-general/#our-class-schedule","text":"Signup / login / logout (today) Posting (March 5, next Monday) Messaging (March 12) API, static frontend (March 19)","title":"Our Class Schedule"},{"location":"docs/references/django-general/#first-time-setup","text":"The manage.py is executable by default in Python 3. Simply ./manage.py runserver or any other argument. You can python manage.py runserver 80 for example, to run on any port. Python 3 in a virtualenv pip install django django-admin startproject python manage.py migrate python manage.py createsuperuser python manage.py startapp social","title":"First Time Setup"},{"location":"docs/references/django-general/#specific-technologies","text":"DocRaptor for html to pdf in Django - Razzi used it at a company. stack overflow","title":"Specific Technologies"},{"location":"docs/references/emacs/","text":"Simpler Emacs I intend to install a number of packages from spacemacs. Quickref M-x : get a prompt At the prompt nb: RET is return key , the whitespace is for readability. package-list-packages RET : list packages package-install RET : get a package install prompt evil RET : i did not find evil-mode in the packages, so installed evil Installing Packages The emacs wiki has a guide . Installing use-package An easier way to install packages? People like it. Seems heavy to me... init.el example with use-package code Customize Group M-x customize-group seems to have context for customizing stuff try it and choose undo-tree Notes M- : You can press escape then the key instead of meta. Future Evil Plugins lots of additional features Undo Tree should go to a directory in $HOME? right now it goes to $TMPDIR in macos which may be deleted?? Undo Tree & Persistent Buffer - done? emacswiki.org: Category Undo UndoTree : like vim? apparently has a corruption bug with this feature, a fork is incomplete apparently undo-tree does this but it has a major corruption bug with this specific feature, and the solution right now is to use emacs server, so i'm going to do that emacs server - the only way to get persistent undo for now as you never exit the session Desired Spacemacs Packages helm evil-mode Resources Aaron Bieber's \"Vim to Emacs in 14 days\" post this was pretty out of date but a good general guide took lots of googling to find the right command for evil-mode stuff emacswiki.org: evil evil plugins","title":"Emacs"},{"location":"docs/references/emacs/#simpler-emacs","text":"I intend to install a number of packages from spacemacs.","title":"Simpler Emacs"},{"location":"docs/references/emacs/#quickref","text":"M-x : get a prompt","title":"Quickref"},{"location":"docs/references/emacs/#at-the-prompt","text":"nb: RET is return key , the whitespace is for readability. package-list-packages RET : list packages package-install RET : get a package install prompt evil RET : i did not find evil-mode in the packages, so installed evil","title":"At the prompt"},{"location":"docs/references/emacs/#installing-packages","text":"The emacs wiki has a guide .","title":"Installing Packages"},{"location":"docs/references/emacs/#installing-use-package","text":"An easier way to install packages? People like it. Seems heavy to me... init.el example with use-package code","title":"Installing use-package"},{"location":"docs/references/emacs/#customize-group","text":"M-x customize-group seems to have context for customizing stuff try it and choose undo-tree","title":"Customize Group"},{"location":"docs/references/emacs/#notes","text":"M- : You can press escape then the key instead of meta.","title":"Notes"},{"location":"docs/references/emacs/#future","text":"Evil Plugins lots of additional features Undo Tree should go to a directory in $HOME? right now it goes to $TMPDIR in macos which may be deleted?? Undo Tree & Persistent Buffer - done? emacswiki.org: Category Undo UndoTree : like vim? apparently has a corruption bug with this feature, a fork is incomplete apparently undo-tree does this but it has a major corruption bug with this specific feature, and the solution right now is to use emacs server, so i'm going to do that emacs server - the only way to get persistent undo for now as you never exit the session","title":"Future"},{"location":"docs/references/emacs/#desired-spacemacs-packages","text":"helm evil-mode","title":"Desired Spacemacs Packages"},{"location":"docs/references/emacs/#resources","text":"Aaron Bieber's \"Vim to Emacs in 14 days\" post this was pretty out of date but a good general guide took lots of googling to find the right command for evil-mode stuff emacswiki.org: evil evil plugins","title":"Resources"},{"location":"docs/references/fight-global-internet-propaganda-review/","text":"Fighting Global Internet Propaganda Review Some people are fighting online trolls as a team online, essentially as a campaign. This is some information about this movement. Intentions of Propaganda This section could use some well researched information, but there are some obvious ones: Remove thoughtful people from the political process Polarize the political process to create deeper fractures in ideology Overfocus people on literally anything prevent them from seeing the big picture Appeal to emotion Apply self-consistency logic (you agree to this, therefore you must agree to that) Self consistency is the primary driver for human motivation. Primary Targets for Propaganda reddit twitter facebook Potential Tactics for Distributing Propaganda Networks of trolls with simulated traffic 'record and playback' real account activity using real network topography as a template to evade detection build many disjoint layers of fake networks that can be activated for particular purposes Recruit vulnerable people identify more intimate online forums for people seeking more personal attention: 4chan, something awful create new online forums to cultivate this: voat, gab, PewTube, WrongThink, Infogalactic, GoyFundMe, wasp.love \"The Alt-Right Created a Parallel Internet. It's an unholy mess.\" - NYT Article misdirected people can exert influence on real social networks viral sharing is already addictive use narrative storytelling to move people further than the mainstream pool of facts Trollfare the purpose of this sub is, for a start, to have free-form discussions about how american or allied reddit users can more effectively combat RU and other hostile propaganda on reddit and elsewhere on the internet. site: trollfare subreddit resources compendium Securing Democracy Tracking Russian influenced twitter hashtags. site: securing democracy dashboard Twitter banned 70 million accounts How do bots still exert influence over twitter after this? Twitter has 336 million monthly active users (MAU). So this means 20% of accounts were banned? Or is there a massive network of inactives, or is it a problem with the trending algorithm? source: reuters - Twitter suspends over 70 million accounts in two months: Washington Post","title":"Fight Global Internet Propaganda Review"},{"location":"docs/references/fight-global-internet-propaganda-review/#fighting-global-internet-propaganda-review","text":"Some people are fighting online trolls as a team online, essentially as a campaign. This is some information about this movement.","title":"Fighting Global Internet Propaganda Review"},{"location":"docs/references/fight-global-internet-propaganda-review/#intentions-of-propaganda","text":"This section could use some well researched information, but there are some obvious ones: Remove thoughtful people from the political process Polarize the political process to create deeper fractures in ideology Overfocus people on literally anything prevent them from seeing the big picture Appeal to emotion Apply self-consistency logic (you agree to this, therefore you must agree to that) Self consistency is the primary driver for human motivation.","title":"Intentions of Propaganda"},{"location":"docs/references/fight-global-internet-propaganda-review/#primary-targets-for-propaganda","text":"reddit twitter facebook","title":"Primary Targets for Propaganda"},{"location":"docs/references/fight-global-internet-propaganda-review/#potential-tactics-for-distributing-propaganda","text":"Networks of trolls with simulated traffic 'record and playback' real account activity using real network topography as a template to evade detection build many disjoint layers of fake networks that can be activated for particular purposes Recruit vulnerable people identify more intimate online forums for people seeking more personal attention: 4chan, something awful create new online forums to cultivate this: voat, gab, PewTube, WrongThink, Infogalactic, GoyFundMe, wasp.love \"The Alt-Right Created a Parallel Internet. It's an unholy mess.\" - NYT Article misdirected people can exert influence on real social networks viral sharing is already addictive use narrative storytelling to move people further than the mainstream pool of facts","title":"Potential Tactics for Distributing Propaganda"},{"location":"docs/references/fight-global-internet-propaganda-review/#trollfare","text":"the purpose of this sub is, for a start, to have free-form discussions about how american or allied reddit users can more effectively combat RU and other hostile propaganda on reddit and elsewhere on the internet. site: trollfare subreddit resources compendium","title":"Trollfare"},{"location":"docs/references/fight-global-internet-propaganda-review/#securing-democracy","text":"Tracking Russian influenced twitter hashtags. site: securing democracy dashboard","title":"Securing Democracy"},{"location":"docs/references/fight-global-internet-propaganda-review/#twitter-banned-70-million-accounts","text":"How do bots still exert influence over twitter after this? Twitter has 336 million monthly active users (MAU). So this means 20% of accounts were banned? Or is there a massive network of inactives, or is it a problem with the trending algorithm? source: reuters - Twitter suspends over 70 million accounts in two months: Washington Post","title":"Twitter banned 70 million accounts"},{"location":"docs/references/git/","text":"Git References Removing files from a repository history github help","title":"Git"},{"location":"docs/references/git/#git-references","text":"","title":"Git References"},{"location":"docs/references/git/#removing-files-from-a-repository-history","text":"github help","title":"Removing files from a repository history"},{"location":"docs/references/html5-game-dev/","text":"Learning HTML5 Native Game Dev It looks like there are a lot of different ways to do this, and games are typically packaged for ios using phonegap or cordova. Goals Make some simple games in html5 Somehow translate the games to mobile native (Android & iOS) Otherwise I may have to relearn a lot of platform specific knowledge... Leverage existing javascript libraries for multiplayer, maybe even run a server/api for play between phone and browser users Trajectory Package someone else's game for iOS with Phonegap (or Cordova) just to see it happen. I plan to use the default phonegap hello world app to test this out. Make modifications to the game and package again to iOS. More Engines! This site https://html5gameengine.com/ has way more engines! This llst https://github.com/collections/javascript-game-engines has a lot more js frameworks... Notes SVG Keyframe animations may be sort of restricted to data visualization, not games Game Engines tend to use webgl and fallback to canvas Converting to iOS still done with phonegap or cordova can be done (partially, not full POC) without a conversion framework Option: phaser.js They offer a community edition and a paid product. They claim it is intended to be packaged for native apps. I wonder if many examples of this exist. I should get it up and running for ios and android. It is the 2nd most starred on github after pixi.js. Phase is a 2d game engine. Resources Option: react-game-kit Pitch from the dev: Use the same game code for web, iOS, android Use react Hot reload game logic Don't have to learn unity References source interactive guide Recommendations Jeffrey built this ( source ). i made this once. this uses matter.js as well as react-game-kit , the status of which i\u2019m unaware. seems straightforward enough, although it uses the DOM instead of canvas, which i\u2019m iffy about - Jeffrey Formidable Labs does great stuff - Nick Option: PlayCanvas I signed up for this with a google account. It seems to provide an environment for pretty rich 3d art. I doubt you would develop the assets in playcanvas, but I don't know that much about it. It doesn't seem like quite what I am looking for. PlayCanvas is a suite of products: PlayCanvas Engine Open Source / MIT Licensed on Github: PlayCanvas Engine \"The open-source PlayCanvas Engine is the world's most advanced WebGL game engine. Use JavaScript to program anything from simple 2D games to advanced 3D graphics simulations. All written in standards-compliant, cross-platform HTML5 for every major browser and device.\" Tiny footprint, mobile optimized: \"The PlayCanvas Engine has a tiny footprint that loads and executes incredibly quickly. The PlayCanvas Engine gives incredible performance, even on devices such as the iPhone 4S.\" a webgl authoring tool, with a UI similar to adobe products. Option: pixi.js 2D Sprite Managment. PixiJS is a rendering library, so you still need the game framework. It's sounding like there is a standard way to pack javascript into a native app, so that might not be important. References learning pixi source Option: Unreal Engine 4 Does html5, maybe overkill.","title":"Html5 Game Dev"},{"location":"docs/references/html5-game-dev/#learning-html5-native-game-dev","text":"It looks like there are a lot of different ways to do this, and games are typically packaged for ios using phonegap or cordova.","title":"Learning HTML5 Native Game Dev"},{"location":"docs/references/html5-game-dev/#goals","text":"Make some simple games in html5 Somehow translate the games to mobile native (Android & iOS) Otherwise I may have to relearn a lot of platform specific knowledge... Leverage existing javascript libraries for multiplayer, maybe even run a server/api for play between phone and browser users","title":"Goals"},{"location":"docs/references/html5-game-dev/#trajectory","text":"Package someone else's game for iOS with Phonegap (or Cordova) just to see it happen. I plan to use the default phonegap hello world app to test this out. Make modifications to the game and package again to iOS.","title":"Trajectory"},{"location":"docs/references/html5-game-dev/#more-engines","text":"This site https://html5gameengine.com/ has way more engines! This llst https://github.com/collections/javascript-game-engines has a lot more js frameworks...","title":"More Engines!"},{"location":"docs/references/html5-game-dev/#notes","text":"SVG Keyframe animations may be sort of restricted to data visualization, not games Game Engines tend to use webgl and fallback to canvas Converting to iOS still done with phonegap or cordova can be done (partially, not full POC) without a conversion framework","title":"Notes"},{"location":"docs/references/html5-game-dev/#option-phaserjs","text":"They offer a community edition and a paid product. They claim it is intended to be packaged for native apps. I wonder if many examples of this exist. I should get it up and running for ios and android. It is the 2nd most starred on github after pixi.js. Phase is a 2d game engine.","title":"Option: phaser.js"},{"location":"docs/references/html5-game-dev/#resources","text":"","title":"Resources"},{"location":"docs/references/html5-game-dev/#option-react-game-kit","text":"Pitch from the dev: Use the same game code for web, iOS, android Use react Hot reload game logic Don't have to learn unity","title":"Option: react-game-kit"},{"location":"docs/references/html5-game-dev/#references","text":"source interactive guide","title":"References"},{"location":"docs/references/html5-game-dev/#recommendations","text":"Jeffrey built this ( source ). i made this once. this uses matter.js as well as react-game-kit , the status of which i\u2019m unaware. seems straightforward enough, although it uses the DOM instead of canvas, which i\u2019m iffy about - Jeffrey Formidable Labs does great stuff - Nick","title":"Recommendations"},{"location":"docs/references/html5-game-dev/#option-playcanvas","text":"I signed up for this with a google account. It seems to provide an environment for pretty rich 3d art. I doubt you would develop the assets in playcanvas, but I don't know that much about it. It doesn't seem like quite what I am looking for. PlayCanvas is a suite of products: PlayCanvas Engine Open Source / MIT Licensed on Github: PlayCanvas Engine \"The open-source PlayCanvas Engine is the world's most advanced WebGL game engine. Use JavaScript to program anything from simple 2D games to advanced 3D graphics simulations. All written in standards-compliant, cross-platform HTML5 for every major browser and device.\" Tiny footprint, mobile optimized: \"The PlayCanvas Engine has a tiny footprint that loads and executes incredibly quickly. The PlayCanvas Engine gives incredible performance, even on devices such as the iPhone 4S.\" a webgl authoring tool, with a UI similar to adobe products.","title":"Option: PlayCanvas"},{"location":"docs/references/html5-game-dev/#option-pixijs","text":"2D Sprite Managment. PixiJS is a rendering library, so you still need the game framework. It's sounding like there is a standard way to pack javascript into a native app, so that might not be important.","title":"Option: pixi.js"},{"location":"docs/references/html5-game-dev/#references_1","text":"learning pixi source","title":"References"},{"location":"docs/references/html5-game-dev/#option-unreal-engine-4","text":"Does html5, maybe overkill.","title":"Option: Unreal Engine 4"},{"location":"docs/references/html5-phaser-pixi-phonegap/","text":"Phaser3, Pixi, and Phonegap This build toolchain is easy to set up, with practice. Questions What version of pixi.js does phaser3 use? Check phaser3 source. What pixi.js plugins does phaser3 use? - Check phaser3 source. How do canvas sizes interact with platform builds? Is there a dynamic canvas size or some canvassize detection method? Or is it done another way? what is this: game.scale.setGameSize(x, y) renderer.resize may be relevant Look into 'scalemanager' which may still be in dev, see issue #3148 Here is an article on scaling in phaser Question for later: Do I need to be using phonegap? Why not just use cordova? Well... how would I build the IPA? Figure this out later... Phonegap Phonegap build is a webapp that will build from your hosted repos, but you do need to provide an app key from Apple, which takes awhile to set up. Set Up You can build and test directly in phonegap. This development environment is intended to be faithful to all platforms What issues exist and can be checked for, and how? Apple Developer account + $99+tax fee Register devices for testing Generate a key and get it signed for your account and device Build, Download, and Install the app on your device (phone, tablet, even laptop via steam??) Build Use the phaser + phonegap framework managed by Adobe (see trello to fill this in). npm install -g phonegap@latest phonegap create ./MyPhaserApp --template phonegap-template-phaser You can then use phonegap (I used the macos app ui) to test the project. You can also use phonegap (I used the phonegap-build webapp) to build the project for target devices. Build from a custom/local phonegap app template I replaced the phonegap-template-phaser , which I guess defaults to the NPM package, and I used a filepath instead. It copied everything over, but didn't create everything that the node app created. It seemed to skip three folders: . phonegap --template` just wraps cordova --template . The above worked fine but when building my phaser .ipa demo, I actually copied a phaser2 project (the project created from the phonegap --template command), then added the phaser 3.10.1 files to that. My Phaser3 retrofit app runs with the Phaser3 \"hello world\" demo ! Issues I think you can also use a git remote with cordova because of the phonegap source code . However, I tried to specify one and it told me it can't find the package.json, so something seems to be going wrong? Install Drop the .ipa file into your phone with the Apple official app: Apple Configurator 2 Using Phaser3 and Pixi Both phaser.js and pixi.js are MIT licensed, so bundle away. Phaser3 is under active development, and phaser3 has already been released. Pixi.js is also actively developed. Phaser 2 Examples here Phaser 3 Examples Phaser 2 Sandbox There's a Phaser 2 sandbox for quick and dirty testing. Phaser 3 Sandbox If this is broken you can get a phaser 3 sandbox in the phaser examples app. This also exists . Use pixi.js in phaser2 This is from 2016 All Phaser display objects (group, sprites...) are based on PIXI ones. PIXI objects can be rendered in phaser render tree. the only problem is the update and postUpdate function. I solved it adding this simple patch: PIXI.DisplayObject.prototype.update = function () { }; PIXI.DisplayObject.prototype.postUpdate = function () { }; this patch adds a empty function for \"update\" and \"postUpdate\" methods in PIXI displayObjects prototype. In that case Phaser update tree founds a function to execute. Input in Phaser We want mobile-first multiplatform, which means we really only have multitouch events to go off of, and the relationship of those events to regions of the screen... some info Building for Multiple platforms Discuss how to build for android and ios, or multiple iphones. stub Emulating platforms Discuss stub","title":"Html5 Phaser Pixi Phonegap"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phaser3-pixi-and-phonegap","text":"This build toolchain is easy to set up, with practice.","title":"Phaser3, Pixi, and Phonegap"},{"location":"docs/references/html5-phaser-pixi-phonegap/#questions","text":"What version of pixi.js does phaser3 use? Check phaser3 source. What pixi.js plugins does phaser3 use? - Check phaser3 source. How do canvas sizes interact with platform builds? Is there a dynamic canvas size or some canvassize detection method? Or is it done another way? what is this: game.scale.setGameSize(x, y) renderer.resize may be relevant Look into 'scalemanager' which may still be in dev, see issue #3148 Here is an article on scaling in phaser Question for later: Do I need to be using phonegap? Why not just use cordova? Well... how would I build the IPA? Figure this out later...","title":"Questions"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phonegap","text":"Phonegap build is a webapp that will build from your hosted repos, but you do need to provide an app key from Apple, which takes awhile to set up.","title":"Phonegap"},{"location":"docs/references/html5-phaser-pixi-phonegap/#set-up","text":"You can build and test directly in phonegap. This development environment is intended to be faithful to all platforms What issues exist and can be checked for, and how? Apple Developer account + $99+tax fee Register devices for testing Generate a key and get it signed for your account and device Build, Download, and Install the app on your device (phone, tablet, even laptop via steam??)","title":"Set Up"},{"location":"docs/references/html5-phaser-pixi-phonegap/#build","text":"Use the phaser + phonegap framework managed by Adobe (see trello to fill this in). npm install -g phonegap@latest phonegap create ./MyPhaserApp --template phonegap-template-phaser You can then use phonegap (I used the macos app ui) to test the project. You can also use phonegap (I used the phonegap-build webapp) to build the project for target devices.","title":"Build"},{"location":"docs/references/html5-phaser-pixi-phonegap/#build-from-a-customlocal-phonegap-app-template","text":"I replaced the phonegap-template-phaser , which I guess defaults to the NPM package, and I used a filepath instead. It copied everything over, but didn't create everything that the node app created. It seemed to skip three folders: . phonegap --template` just wraps cordova --template . The above worked fine but when building my phaser .ipa demo, I actually copied a phaser2 project (the project created from the phonegap --template command), then added the phaser 3.10.1 files to that. My Phaser3 retrofit app runs with the Phaser3 \"hello world\" demo !","title":"Build from a custom/local phonegap app template"},{"location":"docs/references/html5-phaser-pixi-phonegap/#issues","text":"I think you can also use a git remote with cordova because of the phonegap source code . However, I tried to specify one and it told me it can't find the package.json, so something seems to be going wrong?","title":"Issues"},{"location":"docs/references/html5-phaser-pixi-phonegap/#install","text":"Drop the .ipa file into your phone with the Apple official app: Apple Configurator 2","title":"Install"},{"location":"docs/references/html5-phaser-pixi-phonegap/#using-phaser3-and-pixi","text":"Both phaser.js and pixi.js are MIT licensed, so bundle away. Phaser3 is under active development, and phaser3 has already been released. Pixi.js is also actively developed.","title":"Using Phaser3 and Pixi"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phaser-2-examples","text":"here","title":"Phaser 2 Examples"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phaser-3-examples","text":"","title":"Phaser 3 Examples"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phaser-2-sandbox","text":"There's a Phaser 2 sandbox for quick and dirty testing.","title":"Phaser 2 Sandbox"},{"location":"docs/references/html5-phaser-pixi-phonegap/#phaser-3-sandbox","text":"If this is broken you can get a phaser 3 sandbox in the phaser examples app. This also exists .","title":"Phaser 3 Sandbox"},{"location":"docs/references/html5-phaser-pixi-phonegap/#use-pixijs-in-phaser2","text":"This is from 2016 All Phaser display objects (group, sprites...) are based on PIXI ones. PIXI objects can be rendered in phaser render tree. the only problem is the update and postUpdate function. I solved it adding this simple patch: PIXI.DisplayObject.prototype.update = function () { }; PIXI.DisplayObject.prototype.postUpdate = function () { }; this patch adds a empty function for \"update\" and \"postUpdate\" methods in PIXI displayObjects prototype. In that case Phaser update tree founds a function to execute.","title":"Use pixi.js in phaser2"},{"location":"docs/references/html5-phaser-pixi-phonegap/#input-in-phaser","text":"We want mobile-first multiplatform, which means we really only have multitouch events to go off of, and the relationship of those events to regions of the screen... some info","title":"Input in Phaser"},{"location":"docs/references/html5-phaser-pixi-phonegap/#building-for-multiple-platforms","text":"Discuss how to build for android and ios, or multiple iphones.","title":"Building for Multiple platforms"},{"location":"docs/references/html5-phaser-pixi-phonegap/#stub","text":"","title":"stub"},{"location":"docs/references/html5-phaser-pixi-phonegap/#emulating-platforms","text":"Discuss","title":"Emulating platforms"},{"location":"docs/references/html5-phaser-pixi-phonegap/#stub_1","text":"","title":"stub"},{"location":"docs/references/html5-phonegap-for-ios/","text":"HTML5 Use PhoneGap to build a html5 app to iOS I read somewhere that phonegap CLI is easier once you downaload the ios and android SDKs. Issues (All heresay at this point) These issues are mostly around game dev focusing on 60fps games. There is less criticism for business apps. a lot of intermittent problems (sound issues, android issues) issues with having a high number of elements issues on phones older than iphone 6 and similar android generations may not use canvas and webgl due to the type of iphone browser emulation? Alternatives for game dev Get an apple developer account - individual is faster enroll you have to pay $99 + tax (no tax if you have a ADUNS, TIN) individual can do apple ID company can use ADUNS number to get company apple id other requirements listed at the link (above) Get an apple iOS signing certificate lots to this, follow phonegap instructions Build the app in phonegap attach the github link, it will build i have no idea what the app needs to build properly... lol Download the .ipa file! iPhone apps are .ipa files, cool. Install Apple Configurator 2 by Apple (in the app store) This can be used to configure apple devices Drag the .ipa file onto Apple Configurator 2 Open the app by pressing the new icon on your phone Future - TestFlight It would be nice to distribute beta apps to testers via TestFlight Resource: https://medium.com/@dmathewwws/steps-to-put-your-app-on-testflight-and-then-the-ios-app-store-10a7996411b1 How to set up a HTML5 project to work on Phonegap/iOS Ionic has some sort of descriptive (html-like) language for native-like components . Ionic also has released capacitor which is similar to cordova . The phonegap project is also based on cordova . Install phonegap for macos. also checkout phonegap-cli Open phonegap and make a new project (build your app in this project template, using phaser.js?) Guidelines for what Apple will accept as a mobile app Found here If you\u2019re building an application to be distributed through the Apple and Google Play app stores, you need to play by their rules. Make sure you comply with the Apple App Store Review Guidelines and the Google Play Developer Program Policies. This is where the benefit of distributing your application as a Progressive Web Application comes in \u2013 using the open web means we don\u2019t need to jump through somebody else\u2019s hoops. Apple especially can be a bit fickle with their application of the guidelines, but if you break any of them (sometimes even if you don\u2019t) your application may be rejected and you will have to fix the problem and resubmit. Here are a few gotchas to watch out for that might see your application be rejected: Your app is more like a web page than a mobile application You don\u2019t handle online/offline states Your app is slow or unresponsive Your application doesn\u2019t make use of native features (i.e. there isn\u2019t really a reason for it to be > distributed as a native app instead of a website)","title":"Html5 Phonegap For Ios"},{"location":"docs/references/html5-phonegap-for-ios/#html5","text":"","title":"HTML5"},{"location":"docs/references/html5-phonegap-for-ios/#use-phonegap-to-build-a-html5-app-to-ios","text":"I read somewhere that phonegap CLI is easier once you downaload the ios and android SDKs.","title":"Use PhoneGap to build a html5 app to iOS"},{"location":"docs/references/html5-phonegap-for-ios/#issues-all-heresay-at-this-point","text":"These issues are mostly around game dev focusing on 60fps games. There is less criticism for business apps. a lot of intermittent problems (sound issues, android issues) issues with having a high number of elements issues on phones older than iphone 6 and similar android generations may not use canvas and webgl due to the type of iphone browser emulation?","title":"Issues (All heresay at this point)"},{"location":"docs/references/html5-phonegap-for-ios/#alternatives-for-game-dev","text":"Get an apple developer account - individual is faster enroll you have to pay $99 + tax (no tax if you have a ADUNS, TIN) individual can do apple ID company can use ADUNS number to get company apple id other requirements listed at the link (above) Get an apple iOS signing certificate lots to this, follow phonegap instructions Build the app in phonegap attach the github link, it will build i have no idea what the app needs to build properly... lol Download the .ipa file! iPhone apps are .ipa files, cool. Install Apple Configurator 2 by Apple (in the app store) This can be used to configure apple devices Drag the .ipa file onto Apple Configurator 2 Open the app by pressing the new icon on your phone","title":"Alternatives for game dev"},{"location":"docs/references/html5-phonegap-for-ios/#future-testflight","text":"It would be nice to distribute beta apps to testers via TestFlight Resource: https://medium.com/@dmathewwws/steps-to-put-your-app-on-testflight-and-then-the-ios-app-store-10a7996411b1","title":"Future - TestFlight"},{"location":"docs/references/html5-phonegap-for-ios/#how-to-set-up-a-html5-project-to-work-on-phonegapios","text":"Ionic has some sort of descriptive (html-like) language for native-like components . Ionic also has released capacitor which is similar to cordova . The phonegap project is also based on cordova . Install phonegap for macos. also checkout phonegap-cli Open phonegap and make a new project (build your app in this project template, using phaser.js?)","title":"How to set up a HTML5 project to work on Phonegap/iOS"},{"location":"docs/references/html5-phonegap-for-ios/#guidelines-for-what-apple-will-accept-as-a-mobile-app","text":"Found here If you\u2019re building an application to be distributed through the Apple and Google Play app stores, you need to play by their rules. Make sure you comply with the Apple App Store Review Guidelines and the Google Play Developer Program Policies. This is where the benefit of distributing your application as a Progressive Web Application comes in \u2013 using the open web means we don\u2019t need to jump through somebody else\u2019s hoops. Apple especially can be a bit fickle with their application of the guidelines, but if you break any of them (sometimes even if you don\u2019t) your application may be rejected and you will have to fix the problem and resubmit. Here are a few gotchas to watch out for that might see your application be rejected: Your app is more like a web page than a mobile application You don\u2019t handle online/offline states Your app is slow or unresponsive Your application doesn\u2019t make use of native features (i.e. there isn\u2019t really a reason for it to be > distributed as a native app instead of a website)","title":"Guidelines for what Apple will accept as a mobile app"},{"location":"docs/references/http1.1/","text":"Modern HTTP/1.1 RFCs HTTP/1.1 RFC2616 replaced in 2014 by RFCs 7230-7237 Any connection , port , protocol can be used and is out of scope of the RFC. The HTTP URI scheme http indicates TCP over IP with default tcp port 80. This document highlights rfc7230 , rfc7231 , and rfc7232 as of January 2019. Future Digesting the cacheing RFC will take some time (rfc7234). Range requests are used for multi-part downloads, particularly in the browser. MDN on Range Requests This has some good curl examples that help to show how range requests are done in the app backend Primary RFCs Summarized Below These are the eight HTTP/1.1 RFCs. Other RFCs are discussed inside these RFCs. Message Syntax and Routing Semantics and Content Conditional Requests Range Requests Caching Authentication Authentication Scheme Registrations Method Registrations rfc7230 Highlights Four distinct formats for request-target UgRI Client w/ 2+ requests must maintain a time-ordered list and correlate first response to first request Intermediaries may transform some message body. Sender can specify not to transform. Avoid for medical imaging etc. Payload Semantics e.g. PUT request vs POST request vs GET response Persistence - HTTP/1.1 defaults to persistence \"close\" connection option specifies a connection will not persist after current request/response. related to HTTP/1.0 keep-alive Pipelining client can send mult. simulatenous requests, server can process requests with safe methods in parallel, must respond in order Idempotent methods - don't pipeline after non-idempotent methods (see rfc7231 highlights in this document) Tear-down & using the \"Connection\" header field \"close\" option If client sends a \"close\" option, server response should have a \"close\" option Server must close that connection after that response Client must not use that connection again and must close the connection If server sends \"close\" option in response Client SHOULD NOT assume additional pipelined requests will be processed by server (no obligation to process by server) TCP reset problem and half-closed connections (close write then close read) discussed inside rfc7231 Highlights This contains request methods , method header fields , and content representation , among other things. Representation Headers data type of representation data is determined by header fields Content-Type and Content-Encoding two-layer encoding model: representation-data := Content-Encoding( Content-Type( bits ) ) Content Negotation proactive or reactive for negotiating formats , languages , or encodings could influence which representation, among those available, would be best to deliver Request Methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE All general purpose servers must support GET and HEAD (all others optional) See IANA HTTP Methods Registry in this document's References for an up to date index of HTTP methods and their RFCs. Concept of safe methods Safe methods must be implemented in a safe way, beyond scope of spec Of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. Request methods are considered \"safe\" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server. This definition of safe methods does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it. idempotent Request methods: PUT, DELETE, safe request methods Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response. Method Definitions - for all methods Request Header Fields Response Status Codes Range is 1xx-5xx, extensible See IANA Status Code Registry URL in References in this document for an up-to-date list of Status Codes and their: Description RFC Reference URL Details on each status code through the link Cacheable by default: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 Responses with status codes that are defined as cacheable by default (e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in this specification) can be reused by a cache with heuristic expiration unless otherwise indicated by the method definition or explicit cache controls [RFC7234]; all other status codes are not cacheable by default. Response Header Fields detailed index to be aware of if parsing responses HTTP Semantics - Security Considerations be aware of these, read them over rfc7232 Highlights This specification defines two forms of metadata that are commonly used to observe resource state and test for preconditions: modification dates (Section 2.2) and opaque entity tags (Section 2.3). Additional metadata that reflects resource state has been defined by various extensions of HTTP, such as Web Distributed Authoring and Versioning (WebDAV, [RFC4918]), that are beyond the scope of this specification. A resource metadata value is referred to as a \"validator\" when it is used within a precondition. Header Fields Defined by this RFC ETag If-Match If-Modified-Since If-None-Match If-Unmodified-Since Last-Modified Last-Modified Header Field The \"Last-Modified\" header field in a response provides a timestamp indicating the date and time at which the origin server believes the selected representation was last modified, as determined at the conclusion of handling the request. ETag == entity-tag An entity-tag can be more reliable for validation than a modification date in situations where it is inconvenient to store modification dates, where the one-second resolution of HTTP date values is not sufficient, or where modification dates are not consistently maintained. rfc7233 Highlights rfc7234 Highlights rfc7235 Highlights oauth2/bearer Authorization is covered in rfc7235 and its spec resides in rfc6750 Note that oauth2/bearer aka The OAuth 2.0 Authorization Framework, supercedes outh rfc6749 . oauth2 Authorization headers are very common for HTTP APIs , particularly modern JSON APIs There is a IANA Authentication Scheme Registry in the References of this document. rfc7235 supercedes rfc2617 . rfc7236 Highlights This document is a sparse reference to grandfather HTTP Authentication Methods established before the IANA HTTP Authentication Scheme Registry was established. rfc7237 Highlights This document is a sparse reference to grandfather HTTP Methods established in RFCs other than RFC7231 before the IANA HTTP Scheme Registry was established. References IANA Authentication Scheme Registry Of note is oauth2/bearer IANA HTTP Methods Registry table contains: methods if they are safe if they are idempotent current URL to RFC describing the method (many not in rfc7230 or rfc7231 IANA Status Code Registry REST in rfc7231: references Fielding 2000 Ch. 5 REST: \"REpresentational State Transfer\" architectural style for distributed hypermedia systems Obsolete https://tools.ietf.org/html/rfc1945 https://tools.ietf.org/html/rfc2068 https://tools.ietf.org/html/rfc2145 https://tools.ietf.org/html/rfc2616","title":"Http1.1"},{"location":"docs/references/http1.1/#modern-http11-rfcs","text":"HTTP/1.1 RFC2616 replaced in 2014 by RFCs 7230-7237 Any connection , port , protocol can be used and is out of scope of the RFC. The HTTP URI scheme http indicates TCP over IP with default tcp port 80. This document highlights rfc7230 , rfc7231 , and rfc7232 as of January 2019.","title":"Modern HTTP/1.1 RFCs"},{"location":"docs/references/http1.1/#future","text":"Digesting the cacheing RFC will take some time (rfc7234). Range requests are used for multi-part downloads, particularly in the browser. MDN on Range Requests This has some good curl examples that help to show how range requests are done in the app backend","title":"Future"},{"location":"docs/references/http1.1/#primary-rfcs-summarized-below","text":"These are the eight HTTP/1.1 RFCs. Other RFCs are discussed inside these RFCs. Message Syntax and Routing Semantics and Content Conditional Requests Range Requests Caching Authentication Authentication Scheme Registrations Method Registrations","title":"Primary RFCs Summarized Below"},{"location":"docs/references/http1.1/#rfc7230-highlights","text":"Four distinct formats for request-target UgRI Client w/ 2+ requests must maintain a time-ordered list and correlate first response to first request Intermediaries may transform some message body. Sender can specify not to transform. Avoid for medical imaging etc. Payload Semantics e.g. PUT request vs POST request vs GET response Persistence - HTTP/1.1 defaults to persistence \"close\" connection option specifies a connection will not persist after current request/response. related to HTTP/1.0 keep-alive Pipelining client can send mult. simulatenous requests, server can process requests with safe methods in parallel, must respond in order Idempotent methods - don't pipeline after non-idempotent methods (see rfc7231 highlights in this document) Tear-down & using the \"Connection\" header field \"close\" option If client sends a \"close\" option, server response should have a \"close\" option Server must close that connection after that response Client must not use that connection again and must close the connection If server sends \"close\" option in response Client SHOULD NOT assume additional pipelined requests will be processed by server (no obligation to process by server) TCP reset problem and half-closed connections (close write then close read) discussed inside","title":"rfc7230 Highlights"},{"location":"docs/references/http1.1/#rfc7231-highlights","text":"This contains request methods , method header fields , and content representation , among other things. Representation Headers data type of representation data is determined by header fields Content-Type and Content-Encoding two-layer encoding model: representation-data := Content-Encoding( Content-Type( bits ) ) Content Negotation proactive or reactive for negotiating formats , languages , or encodings could influence which representation, among those available, would be best to deliver Request Methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE All general purpose servers must support GET and HEAD (all others optional) See IANA HTTP Methods Registry in this document's References for an up to date index of HTTP methods and their RFCs. Concept of safe methods Safe methods must be implemented in a safe way, beyond scope of spec Of the request methods defined by this specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. Request methods are considered \"safe\" if their defined semantics are essentially read-only; i.e., the client does not request, and does not expect, any state change on the origin server as a result of applying a safe method to a target resource. Likewise, reasonable use of a safe method is not expected to cause any harm, loss of property, or unusual burden on the origin server. This definition of safe methods does not prevent an implementation from including behavior that is potentially harmful, that is not entirely read-only, or that causes side effects while invoking a safe method. What is important, however, is that the client did not request that additional behavior and cannot be held accountable for it. idempotent Request methods: PUT, DELETE, safe request methods Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response. Method Definitions - for all methods Request Header Fields Response Status Codes Range is 1xx-5xx, extensible See IANA Status Code Registry URL in References in this document for an up-to-date list of Status Codes and their: Description RFC Reference URL Details on each status code through the link Cacheable by default: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 Responses with status codes that are defined as cacheable by default (e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in this specification) can be reused by a cache with heuristic expiration unless otherwise indicated by the method definition or explicit cache controls [RFC7234]; all other status codes are not cacheable by default. Response Header Fields detailed index to be aware of if parsing responses HTTP Semantics - Security Considerations be aware of these, read them over","title":"rfc7231 Highlights"},{"location":"docs/references/http1.1/#rfc7232-highlights","text":"This specification defines two forms of metadata that are commonly used to observe resource state and test for preconditions: modification dates (Section 2.2) and opaque entity tags (Section 2.3). Additional metadata that reflects resource state has been defined by various extensions of HTTP, such as Web Distributed Authoring and Versioning (WebDAV, [RFC4918]), that are beyond the scope of this specification. A resource metadata value is referred to as a \"validator\" when it is used within a precondition. Header Fields Defined by this RFC ETag If-Match If-Modified-Since If-None-Match If-Unmodified-Since Last-Modified Last-Modified Header Field The \"Last-Modified\" header field in a response provides a timestamp indicating the date and time at which the origin server believes the selected representation was last modified, as determined at the conclusion of handling the request. ETag == entity-tag An entity-tag can be more reliable for validation than a modification date in situations where it is inconvenient to store modification dates, where the one-second resolution of HTTP date values is not sufficient, or where modification dates are not consistently maintained.","title":"rfc7232 Highlights"},{"location":"docs/references/http1.1/#rfc7233-highlights","text":"","title":"rfc7233 Highlights"},{"location":"docs/references/http1.1/#rfc7234-highlights","text":"","title":"rfc7234 Highlights"},{"location":"docs/references/http1.1/#rfc7235-highlights","text":"oauth2/bearer Authorization is covered in rfc7235 and its spec resides in rfc6750 Note that oauth2/bearer aka The OAuth 2.0 Authorization Framework, supercedes outh rfc6749 . oauth2 Authorization headers are very common for HTTP APIs , particularly modern JSON APIs There is a IANA Authentication Scheme Registry in the References of this document. rfc7235 supercedes rfc2617 .","title":"rfc7235 Highlights"},{"location":"docs/references/http1.1/#rfc7236-highlights","text":"This document is a sparse reference to grandfather HTTP Authentication Methods established before the IANA HTTP Authentication Scheme Registry was established.","title":"rfc7236 Highlights"},{"location":"docs/references/http1.1/#rfc7237-highlights","text":"This document is a sparse reference to grandfather HTTP Methods established in RFCs other than RFC7231 before the IANA HTTP Scheme Registry was established.","title":"rfc7237 Highlights"},{"location":"docs/references/http1.1/#references","text":"IANA Authentication Scheme Registry Of note is oauth2/bearer IANA HTTP Methods Registry table contains: methods if they are safe if they are idempotent current URL to RFC describing the method (many not in rfc7230 or rfc7231 IANA Status Code Registry REST in rfc7231: references Fielding 2000 Ch. 5 REST: \"REpresentational State Transfer\" architectural style for distributed hypermedia systems","title":"References"},{"location":"docs/references/http1.1/#obsolete","text":"https://tools.ietf.org/html/rfc1945 https://tools.ietf.org/html/rfc2068 https://tools.ietf.org/html/rfc2145 https://tools.ietf.org/html/rfc2616","title":"Obsolete"},{"location":"docs/references/icestick_setup/","text":"Lattice Icestick Evaluation Board - Resources & Information My \"Lattice Semiconductor\" Icestick iCE40 HX1K-TQ144 \"iCEstick Evaluation Kit\" Offical Resources Documentation You must create an account with an email and login to download the software. Official Icestick Landing Page iCEcube2 Software Design, Synthesis, Simulation, and Programming Windows and Linux versions available Project IceStorm Project IceStorm aims at reverse engineering and documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. The IceStorm flow (Yosys, Arachne-pnr, and IceStorm) is a fully open source Verilog-to-Bitstream flow for iCE40 FPGAs. The focus of the project is on the iCE40 LP/HX 1K/4K/8K chips. (Most of the work was done on HX1K-TQ144 and HX8K-CT256 parts.) Icestorm flow Project Icestorm flow presentation content 32c2 Icestorm flow talk on Youtube","title":"Icestick Setup"},{"location":"docs/references/icestick_setup/#lattice-icestick-evaluation-board-resources-information","text":"","title":"Lattice Icestick Evaluation Board - Resources & Information"},{"location":"docs/references/icestick_setup/#my-lattice-semiconductor-icestick","text":"iCE40 HX1K-TQ144 \"iCEstick Evaluation Kit\"","title":"My \"Lattice Semiconductor\" Icestick"},{"location":"docs/references/icestick_setup/#offical-resources","text":"","title":"Offical Resources"},{"location":"docs/references/icestick_setup/#documentation","text":"You must create an account with an email and login to download the software. Official Icestick Landing Page iCEcube2 Software Design, Synthesis, Simulation, and Programming Windows and Linux versions available","title":"Documentation"},{"location":"docs/references/icestick_setup/#project-icestorm","text":"Project IceStorm aims at reverse engineering and documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. The IceStorm flow (Yosys, Arachne-pnr, and IceStorm) is a fully open source Verilog-to-Bitstream flow for iCE40 FPGAs. The focus of the project is on the iCE40 LP/HX 1K/4K/8K chips. (Most of the work was done on HX1K-TQ144 and HX8K-CT256 parts.) Icestorm flow Project Icestorm flow presentation content 32c2 Icestorm flow talk on Youtube","title":"Project IceStorm"},{"location":"docs/references/infopages/","text":"info pages info pages are like man pages. They apparently have hypertext before web type hyperlinks, and are emacs style documentation. Henner says info pages are good references for C. I should probably read all of coreutils.info and info info FUTURE Take notes on info info and include below. Running info Info can be used a few different ways info to get the directory root node for info files. info printf to get info on the node \"printf\". `info --apropos=\"printf\" to search for \"printf\" on all nodes of all info pages on the info page path. Navigation space : page down Also carries you to the next node regardless of level backspace : page up Also carries you to the previous node regardless of level b : go to the top of the current node C-l : redraw the page (control-L) ? : open a quick reference (close it with C-x 0 ) [ : go to the next node in the current document ] : go to the previous node in the current document n : go to the next node at the same level in the current document p : go to the previous node at the same level in the current document u : go the parent node l : go to the last node follow a link: move cursor over a link, a word preceded by an asterisk, press enter q : quit m : go to the menu item you write if it exists Try searching for a menu to quickly find the menu's options? f Cross : follow a cross-reference starting with 'Cross' f? : fetch a list of cross references for the current node C-g : give up when fetching cross references (instead of typing one of the options) a cross reference can lead to another manual, even on a remote machine i Cross : automate - go to index for info manual, search node for 'Cross', and go there d : go to the directory t : go to the top node in a manual n n : go directly to info for experts Using vi type keybindings $ info --vi-keys printf : use vi type keybindings FUTURE: map out exactly what varies between standard nav and vi mode Notes from info info Many notes on info info are integrated elsewhere in this outline. The ? reference is very large and worth further study. info calls its hyperlinks Cross References . Check out the 'info for experts' section by typing n n or type d i and type 'Advanced'. Notes from man info Notes on man info are integrated elsewhere in this outline. info coreutils printf : get printf in coreutils (if there are more than one printf files) I read that there are some flags to store and restore keystrokes pressed in an info file. References info (Unix) on Wikipedia man info info info","title":"Infopages"},{"location":"docs/references/infopages/#info-pages","text":"info pages are like man pages. They apparently have hypertext before web type hyperlinks, and are emacs style documentation. Henner says info pages are good references for C. I should probably read all of coreutils.info and info info","title":"info pages"},{"location":"docs/references/infopages/#future","text":"Take notes on info info and include below.","title":"FUTURE"},{"location":"docs/references/infopages/#running-info","text":"Info can be used a few different ways info to get the directory root node for info files. info printf to get info on the node \"printf\". `info --apropos=\"printf\" to search for \"printf\" on all nodes of all info pages on the info page path.","title":"Running info"},{"location":"docs/references/infopages/#navigation","text":"space : page down Also carries you to the next node regardless of level backspace : page up Also carries you to the previous node regardless of level b : go to the top of the current node C-l : redraw the page (control-L) ? : open a quick reference (close it with C-x 0 ) [ : go to the next node in the current document ] : go to the previous node in the current document n : go to the next node at the same level in the current document p : go to the previous node at the same level in the current document u : go the parent node l : go to the last node follow a link: move cursor over a link, a word preceded by an asterisk, press enter q : quit m : go to the menu item you write if it exists Try searching for a menu to quickly find the menu's options? f Cross : follow a cross-reference starting with 'Cross' f? : fetch a list of cross references for the current node C-g : give up when fetching cross references (instead of typing one of the options) a cross reference can lead to another manual, even on a remote machine i Cross : automate - go to index for info manual, search node for 'Cross', and go there d : go to the directory t : go to the top node in a manual n n : go directly to info for experts","title":"Navigation"},{"location":"docs/references/infopages/#using-vi-type-keybindings","text":"$ info --vi-keys printf : use vi type keybindings FUTURE: map out exactly what varies between standard nav and vi mode","title":"Using vi type keybindings"},{"location":"docs/references/infopages/#notes-from-info-info","text":"Many notes on info info are integrated elsewhere in this outline. The ? reference is very large and worth further study. info calls its hyperlinks Cross References . Check out the 'info for experts' section by typing n n or type d i and type 'Advanced'.","title":"Notes from info info"},{"location":"docs/references/infopages/#notes-from-man-info","text":"Notes on man info are integrated elsewhere in this outline. info coreutils printf : get printf in coreutils (if there are more than one printf files) I read that there are some flags to store and restore keystrokes pressed in an info file.","title":"Notes from man info"},{"location":"docs/references/infopages/#references","text":"info (Unix) on Wikipedia man info info info","title":"References"},{"location":"docs/references/iptables/","text":"Managing traffic: iptables and ip6tables iptables is used to manage IPv4. ip6tables is used to manage IPv6. Using iptables rules Ubuntu recommends using ufw to easily manage iptables rules . View current rules: iptables -L Rules are applied in order One a rule ACCEPT s or DROP s a packet, no further rules are applied Three chain s: INPUT , FORWARD , OUTPUT Saving & Restoring iptables rules iptables-save dumps the current iptables to stdout. iptables-restore flushes iptables and restores a iptables-save dump. Procedure When your iptables is correct, run as root: $ iptables-save > dump.iptables To flush iptables and reload, run as root: $ iptables-restore < dump.iptables There are additional options to maintain packet/byte counters, skip flushing, or save only one table by name. Permanently modifying iptables in a debian/ubuntu system By default, iptables is only stored in memory. Management tools exist for iptables including ufw and the iptables service. iptables initial ruleset comes from /etc/network/interfaces (may be /etc/sysconfig/iptables ) Resources help.ubuntu.com IptablesHowTo nixCraft: How Do I Save Iptables Rules and Settings? askubuntu managing iptables with ip6tables manpages: iptables , iptables-save , iptables-restore","title":"Iptables"},{"location":"docs/references/iptables/#managing-traffic-iptables-and-ip6tables","text":"iptables is used to manage IPv4. ip6tables is used to manage IPv6.","title":"Managing traffic: iptables and ip6tables"},{"location":"docs/references/iptables/#using-iptables-rules","text":"Ubuntu recommends using ufw to easily manage iptables rules . View current rules: iptables -L Rules are applied in order One a rule ACCEPT s or DROP s a packet, no further rules are applied Three chain s: INPUT , FORWARD , OUTPUT","title":"Using iptables rules"},{"location":"docs/references/iptables/#saving-restoring-iptables-rules","text":"iptables-save dumps the current iptables to stdout. iptables-restore flushes iptables and restores a iptables-save dump. Procedure When your iptables is correct, run as root: $ iptables-save > dump.iptables To flush iptables and reload, run as root: $ iptables-restore < dump.iptables There are additional options to maintain packet/byte counters, skip flushing, or save only one table by name.","title":"Saving & Restoring iptables rules"},{"location":"docs/references/iptables/#permanently-modifying-iptables-in-a-debianubuntu-system","text":"By default, iptables is only stored in memory. Management tools exist for iptables including ufw and the iptables service. iptables initial ruleset comes from /etc/network/interfaces (may be /etc/sysconfig/iptables )","title":"Permanently modifying iptables in a debian/ubuntu system"},{"location":"docs/references/iptables/#resources","text":"help.ubuntu.com IptablesHowTo nixCraft: How Do I Save Iptables Rules and Settings? askubuntu managing iptables with ip6tables manpages: iptables , iptables-save , iptables-restore","title":"Resources"},{"location":"docs/references/javascript_notes/","text":"Javascript Reference Notes Understanding: JavaScript Versions When you say Client-Side JavaScript , people are thinking ES5 . When you say node.js , people think Google's V8 Engine-> Gradual ES6 Coverage . ES6 seems to be a superset of ES5. I'm not 100% on this one. Another ES6 vs. ES5 resource ECMAScript 5 was released in December 2009. ECMAScript 6 was released in June 2015. ECMAScript 7 is slated for Summer 2016. ES6 Changes and Comparison ES6 can be transpiled back to ES5 in a build toolchain . This sounds like a great approach to using ES6 with gulp. Understanding: Modern node.js In September 2015, Node.js v0.12 and io.js v3.3 were merged back together into Node v4.0.[36] This brought V8 ES6 features into Node.js, and a long-term support release cycle.[37] As of 2016, the io.js website recommends that developers switch back to Node.js.[38] Understanding: JavaScript Engines Nitro (in webkit) supports most of ES6. V8 supports most of ES6. SpiderMonkey is Firefox's javascript engine and it is competing hard against V8 and seems to be winning. arewefastyet 'compare os' tracks some js engines. There are a lot of active javascript engines . Understanding: ES6 Browser Support Each browser just depends on its JavaScript Engine. Edge 14, Firefox 45, and Chrome 51 support most of ES6. Safari 6.1/7 seems to have almost no support. Safari 7.1/8 seems to have only 20% coverage. Safari 9 has 50% coverage. Safari TP supports most of ES6. What is safari TP? Javascript Refresher: ES6 Reserved Words JavaScript 'String' type and String Escapes ES6 Template Literals (previously template strings) MDN JavaScript Reference Comparison Operators Use strict equals and not equals as much as possible: === and !== Expressions and Operators (advanced operators) Functions Reference Error handling: throw, try, catch, finally Arrays myarray.push(thingy); to append thingy to the end. var shifted_thingy = myarray.pop(); to remove the last (rightmost) thingy. myarray.unshift(thingy); to left-append thingy to the beginning. var shifted_thingy = myarray.shift(); to remove the leftmost thingy. shift and pop return the removed value. push and unshift return the new length of the array. push and unshift can take multiple arguments. Join array values to make a long string: myarray.join(', '); Combine arrays: new_array = myarray.concat(another_array); Find the index of a value in an array: i = myarray.indexOf('apple'); . If apple doesn't exist, return -1 . Objects var shifted_thingy = myarray.shift(); for... in loop for objects. for (var key in myobject) { console.log(key, \" : \", myobject[key]); } window is the global object in the browser. document and screen exist inside window but are aliased in the global scope, as far as I understand. View these in the browser console by typing window or document to view the objects. Also check out window.location or window.location.host etc. Also: window.document.head === document.head . THUS: Document Object Model . The document object is your .html, .php, .aspx, etc object. Ellipses / ... / Spread Syntax Ellipses are the same as a * operator in python on an argument list. Ellipses supports both modes, in functions and when passing arrays to functions. JavaScript Browser API: MDN Web API Reference The Document Object Model is the major Browser API. Global Objects Three DOM Actions Manipulation: manipulate the elements Traversal: Select a element based on its relation with another element. Events: Listen to a specific event like a mouseclick or keypress and have something execute. Create, Remove, and Modify elements: createElement appendChild removeChild textContent className HTMLInputElement.type (for adding the type of input to provide, e.g. checkbox etc.) Traverse Elements: node.parentNode querySelector parentnode.children getElementById getElementsByTagname getElementsByClassName Use thingy.addEventListener to add events e.g. 'click' event instead of using onclick . Element.classList (add, remove, update, check, index an element's classes Special Note on innerText/textContent (from treehouse docs): Mozilla didn't implement innerText but has implemented textContent. innerText can be used in older versions of Internet Explorer and all versions of Chrome and Safari. textContent can be used in Internet Explorer 9 onwards and all other browsers. Here's some cross-browser compatible code for the edit button: // cross compatible code if ( typeof editButton . innerText === \"undefined\" ) { editButton . textContent = \"Edit\" ; } else { editButton . innerText = \"Edit\" ; } [The four-P's Problem Solving Method] (https://medium.com/@MatHelme/the-four-ps-of-problem-solving-6e15a39a0712#.u6oj4sst7): - Preparation: Understand the problem. Think up a high-level solution. - Plan: Plan out the solution. - Perform: Perform what is required. - Perfect: Perfect our solution incrementally. Nothing is ever 'perfect'. Arrow Functions - ` var myfunc = ( param1 , param2 , \u2026 , paramN ) => { // multiline - statements } ` event.preventDefault - Cancels the default action bound to the element , e . g . onClick submit a form is cancelled . - See plotly react tutorial Part II for a use case and example . Resources JavaScript Engine in WebKit browsers","title":"Javascript Notes"},{"location":"docs/references/javascript_notes/#javascript-reference-notes","text":"","title":"Javascript Reference Notes"},{"location":"docs/references/javascript_notes/#understanding-javascript-versions","text":"When you say Client-Side JavaScript , people are thinking ES5 . When you say node.js , people think Google's V8 Engine-> Gradual ES6 Coverage . ES6 seems to be a superset of ES5. I'm not 100% on this one. Another ES6 vs. ES5 resource ECMAScript 5 was released in December 2009. ECMAScript 6 was released in June 2015. ECMAScript 7 is slated for Summer 2016. ES6 Changes and Comparison ES6 can be transpiled back to ES5 in a build toolchain . This sounds like a great approach to using ES6 with gulp.","title":"Understanding: JavaScript Versions"},{"location":"docs/references/javascript_notes/#understanding-modern-nodejs","text":"In September 2015, Node.js v0.12 and io.js v3.3 were merged back together into Node v4.0.[36] This brought V8 ES6 features into Node.js, and a long-term support release cycle.[37] As of 2016, the io.js website recommends that developers switch back to Node.js.[38]","title":"Understanding: Modern node.js"},{"location":"docs/references/javascript_notes/#understanding-javascript-engines","text":"Nitro (in webkit) supports most of ES6. V8 supports most of ES6. SpiderMonkey is Firefox's javascript engine and it is competing hard against V8 and seems to be winning. arewefastyet 'compare os' tracks some js engines. There are a lot of active javascript engines .","title":"Understanding: JavaScript Engines"},{"location":"docs/references/javascript_notes/#understanding-es6-browser-support","text":"Each browser just depends on its JavaScript Engine. Edge 14, Firefox 45, and Chrome 51 support most of ES6. Safari 6.1/7 seems to have almost no support. Safari 7.1/8 seems to have only 20% coverage. Safari 9 has 50% coverage. Safari TP supports most of ES6. What is safari TP?","title":"Understanding: ES6 Browser Support"},{"location":"docs/references/javascript_notes/#javascript-refresher","text":"ES6 Reserved Words JavaScript 'String' type and String Escapes ES6 Template Literals (previously template strings) MDN JavaScript Reference Comparison Operators Use strict equals and not equals as much as possible: === and !== Expressions and Operators (advanced operators) Functions Reference Error handling: throw, try, catch, finally Arrays myarray.push(thingy); to append thingy to the end. var shifted_thingy = myarray.pop(); to remove the last (rightmost) thingy. myarray.unshift(thingy); to left-append thingy to the beginning. var shifted_thingy = myarray.shift(); to remove the leftmost thingy. shift and pop return the removed value. push and unshift return the new length of the array. push and unshift can take multiple arguments. Join array values to make a long string: myarray.join(', '); Combine arrays: new_array = myarray.concat(another_array); Find the index of a value in an array: i = myarray.indexOf('apple'); . If apple doesn't exist, return -1 . Objects var shifted_thingy = myarray.shift(); for... in loop for objects. for (var key in myobject) { console.log(key, \" : \", myobject[key]); } window is the global object in the browser. document and screen exist inside window but are aliased in the global scope, as far as I understand. View these in the browser console by typing window or document to view the objects. Also check out window.location or window.location.host etc. Also: window.document.head === document.head . THUS: Document Object Model . The document object is your .html, .php, .aspx, etc object. Ellipses / ... / Spread Syntax Ellipses are the same as a * operator in python on an argument list. Ellipses supports both modes, in functions and when passing arrays to functions.","title":"Javascript Refresher:"},{"location":"docs/references/javascript_notes/#javascript-browser-api-mdn-web-api-reference","text":"The Document Object Model is the major Browser API. Global Objects Three DOM Actions Manipulation: manipulate the elements Traversal: Select a element based on its relation with another element. Events: Listen to a specific event like a mouseclick or keypress and have something execute. Create, Remove, and Modify elements: createElement appendChild removeChild textContent className HTMLInputElement.type (for adding the type of input to provide, e.g. checkbox etc.) Traverse Elements: node.parentNode querySelector parentnode.children getElementById getElementsByTagname getElementsByClassName Use thingy.addEventListener to add events e.g. 'click' event instead of using onclick . Element.classList (add, remove, update, check, index an element's classes Special Note on innerText/textContent (from treehouse docs): Mozilla didn't implement innerText but has implemented textContent. innerText can be used in older versions of Internet Explorer and all versions of Chrome and Safari. textContent can be used in Internet Explorer 9 onwards and all other browsers. Here's some cross-browser compatible code for the edit button: // cross compatible code if ( typeof editButton . innerText === \"undefined\" ) { editButton . textContent = \"Edit\" ; } else { editButton . innerText = \"Edit\" ; }","title":"JavaScript Browser API: MDN Web API Reference"},{"location":"docs/references/javascript_notes/#the-four-ps-problem-solving-method-httpsmediumcommathelmethe-four-ps-of-problem-solving-6e15a39a0712u6oj4sst7","text":"- Preparation: Understand the problem. Think up a high-level solution. - Plan: Plan out the solution. - Perform: Perform what is required. - Perfect: Perfect our solution incrementally. Nothing is ever 'perfect'.","title":"[The four-P's Problem Solving Method] (https://medium.com/@MatHelme/the-four-ps-of-problem-solving-6e15a39a0712#.u6oj4sst7):"},{"location":"docs/references/javascript_notes/#arrow-functions","text":"- ` var myfunc = ( param1 , param2 , \u2026 , paramN ) => { // multiline - statements } `","title":"Arrow Functions"},{"location":"docs/references/javascript_notes/#eventpreventdefault","text":"- Cancels the default action bound to the element , e . g . onClick submit a form is cancelled . - See plotly react tutorial Part II for a use case and example .","title":"event.preventDefault"},{"location":"docs/references/javascript_notes/#resources","text":"JavaScript Engine in WebKit browsers","title":"Resources"},{"location":"docs/references/kali_vm_setup/","text":"Noisebridge infosec meetup 2017.08.31 Organizer: Kelly Albrink Topic: Kiopatrix 3 (kiopatrix 1.2) VirtualBox I installed vmware but I used VirtualBox because I am more familiar with it. Network: NatNetwork In virtualbox->preferences->network I added a new NatNetwork called PartyTime . I attached both the attacker and kiopatrix1.2 virtual machines to the PartyTime network. Both attacker and defender must be on the same VirtualBox NatNetwork . You can change this for machine in its settings->network . Getting internet connectivity After setting up the host-only network, the route might be messed up in the attacker machine. You have to fix your routing: Run: dhclient eth0 Get ssh server up on attacker So I can use my native terminal. - https://lmgsecurity.com/blog/enable-start-ssh-kali-linux/ Attacker VM The VM can be ssh'd into from the host. It's got a DHCP IP on 192.168.56.0/24. Setting up the attacker vm for native terminal (no virtualbox window) Install sshd and set it up. Make sure root can login with a password From host: ssh root@192.168.1. you should just have to accept the host key and give the password: toor I set up kali linux light .ova file as my attacker machine. It seems to work just like an ovm machine (you import it as an appliance in VirtualBox. username: root password: toor Defender VM I set up the Kiopatrix vmdk file as my defender by making a new vm and adding the VMDK as the attached drive. I specified ubuntu but it didn't seem to take that setting. I assume I could have set anything and it would just use the VMDK and do nothing. Weird. Kiopatrix says: set up your /etc/hosts in your attacker VM: kioptrix3.com Resources Kali Linux VMs kiopatrix 3","title":"Kali Vm Setup"},{"location":"docs/references/kali_vm_setup/#noisebridge-infosec-meetup-20170831","text":"Organizer: Kelly Albrink Topic: Kiopatrix 3 (kiopatrix 1.2)","title":"Noisebridge infosec meetup 2017.08.31"},{"location":"docs/references/kali_vm_setup/#virtualbox","text":"I installed vmware but I used VirtualBox because I am more familiar with it.","title":"VirtualBox"},{"location":"docs/references/kali_vm_setup/#network-natnetwork","text":"In virtualbox->preferences->network I added a new NatNetwork called PartyTime . I attached both the attacker and kiopatrix1.2 virtual machines to the PartyTime network. Both attacker and defender must be on the same VirtualBox NatNetwork . You can change this for machine in its settings->network .","title":"Network: NatNetwork"},{"location":"docs/references/kali_vm_setup/#getting-internet-connectivity","text":"After setting up the host-only network, the route might be messed up in the attacker machine. You have to fix your routing: Run: dhclient eth0","title":"Getting internet connectivity"},{"location":"docs/references/kali_vm_setup/#get-ssh-server-up-on-attacker","text":"So I can use my native terminal.","title":"Get ssh server up on attacker"},{"location":"docs/references/kali_vm_setup/#-httpslmgsecuritycomblogenable-start-ssh-kali-linux","text":"","title":"- https://lmgsecurity.com/blog/enable-start-ssh-kali-linux/"},{"location":"docs/references/kali_vm_setup/#attacker-vm","text":"The VM can be ssh'd into from the host. It's got a DHCP IP on 192.168.56.0/24.","title":"Attacker VM"},{"location":"docs/references/kali_vm_setup/#setting-up-the-attacker-vm-for-native-terminal-no-virtualbox-window","text":"Install sshd and set it up. Make sure root can login with a password From host: ssh root@192.168.1. you should just have to accept the host key and give the password: toor I set up kali linux light .ova file as my attacker machine. It seems to work just like an ovm machine (you import it as an appliance in VirtualBox. username: root password: toor","title":"Setting up the attacker vm for native terminal (no virtualbox window)"},{"location":"docs/references/kali_vm_setup/#defender-vm","text":"I set up the Kiopatrix vmdk file as my defender by making a new vm and adding the VMDK as the attached drive. I specified ubuntu but it didn't seem to take that setting. I assume I could have set anything and it would just use the VMDK and do nothing. Weird. Kiopatrix says: set up your /etc/hosts in your attacker VM: kioptrix3.com","title":"Defender VM"},{"location":"docs/references/kali_vm_setup/#resources","text":"Kali Linux VMs kiopatrix 3","title":"Resources"},{"location":"docs/references/learning_methods/","text":"Learning Methods References and notes for learning and memory. SuperMemo Effective Learning: Twenty rules of formulating knowledge Incremental Reading Devouring Knowledge Flow of knowledge in SuperMemo concept: tasklists","title":"Learning Methods"},{"location":"docs/references/learning_methods/#learning-methods","text":"References and notes for learning and memory.","title":"Learning Methods"},{"location":"docs/references/learning_methods/#supermemo","text":"Effective Learning: Twenty rules of formulating knowledge Incremental Reading Devouring Knowledge Flow of knowledge in SuperMemo concept: tasklists","title":"SuperMemo"},{"location":"docs/references/linksys_wrt160n_info/","text":"Information on the Linksys WRT 160N Router My router Probably a v1.1 router. It has 16 MB ram according to DD-WRT. The v1.0 is supposed to have 32 MB ram. Patrick offered me this router https://wiki.openwrt.org/toh/netgear/wndr3800 DD-WRT Info https://www.dd-wrt.com/wiki/index.php/Telnet/SSH_and_the_Command_Line#Overview 160N v3 condensed thread http://www.dd-wrt.com/phpBB2/viewtopic.php?t=63444&start=15 OpenWRT Info https://wiki.openwrt.org/doc/howto/build https://wiki.openwrt.org/doc/howto/buildroot.exigence https://github.com/openwrt/openwrt/releases https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm47xx https://wireless.wiki.kernel.org/en/users/Drivers/b43/soc https://wiki.openwrt.org/toh/hwdata/linksys/linksys_wrt160n_v3 https://wiki.openwrt.org/toh/linksys/wrt160nl Resources https://wikidevi.com/wiki/Linksys_WRT160N_v1.0 https://wikidevi.com/wiki/Linksys_WRT160N_v1.1 https://wikidevi.com/wiki/Linksys_WRT160N_v3#Upgrading https://www.dd-wrt.com/wiki/index.php/WRT150N https://en.wikipedia.org/wiki/Linksys_routers#WRT160N Modifications External Antenna https://wikidevi.com/wiki/WikiDevi:Network/Hardware_modifications/Linksys_WRT160N_v1.0_Modified_with_External_Antenna","title":"Linksys Wrt160N Info"},{"location":"docs/references/linksys_wrt160n_info/#information-on-the-linksys-wrt-160n-router","text":"","title":"Information on the Linksys WRT 160N Router"},{"location":"docs/references/linksys_wrt160n_info/#my-router","text":"Probably a v1.1 router. It has 16 MB ram according to DD-WRT. The v1.0 is supposed to have 32 MB ram.","title":"My router"},{"location":"docs/references/linksys_wrt160n_info/#patrick-offered-me-this-router","text":"https://wiki.openwrt.org/toh/netgear/wndr3800","title":"Patrick offered me this router"},{"location":"docs/references/linksys_wrt160n_info/#dd-wrt-info","text":"https://www.dd-wrt.com/wiki/index.php/Telnet/SSH_and_the_Command_Line#Overview 160N v3 condensed thread http://www.dd-wrt.com/phpBB2/viewtopic.php?t=63444&start=15","title":"DD-WRT Info"},{"location":"docs/references/linksys_wrt160n_info/#openwrt-info","text":"https://wiki.openwrt.org/doc/howto/build https://wiki.openwrt.org/doc/howto/buildroot.exigence https://github.com/openwrt/openwrt/releases https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm47xx https://wireless.wiki.kernel.org/en/users/Drivers/b43/soc https://wiki.openwrt.org/toh/hwdata/linksys/linksys_wrt160n_v3 https://wiki.openwrt.org/toh/linksys/wrt160nl","title":"OpenWRT Info"},{"location":"docs/references/linksys_wrt160n_info/#resources","text":"https://wikidevi.com/wiki/Linksys_WRT160N_v1.0 https://wikidevi.com/wiki/Linksys_WRT160N_v1.1 https://wikidevi.com/wiki/Linksys_WRT160N_v3#Upgrading https://www.dd-wrt.com/wiki/index.php/WRT150N https://en.wikipedia.org/wiki/Linksys_routers#WRT160N","title":"Resources"},{"location":"docs/references/linksys_wrt160n_info/#modifications","text":"","title":"Modifications"},{"location":"docs/references/linksys_wrt160n_info/#external-antenna","text":"https://wikidevi.com/wiki/WikiDevi:Network/Hardware_modifications/Linksys_WRT160N_v1.0_Modified_with_External_Antenna","title":"External Antenna"},{"location":"docs/references/manpages/","text":"Using manpages Ever wonder if \"man\" has a man page? Ever stare deep into man's soul? Now you don't have to type \"man man\" to see man's deepest features. This document is derived mostly from man man and its references. Viewing all related man pages Use man -wa to see all manpages that would be opened Another option: man -aW man | xargs ls -l See what manpage files would be opened man -w or man --path Supposedly -W gives one per line with no description Use man -a to sequentially view all manpages with the given title man checks $PATH for manpages If an application is on $PATH, man finds it on system path. Specify folders: man man -M /usr/share/man:/usr/local/share/man Can search and open local manpages this way Or specify MANPATH in your man config.` Configuration Check out $ man man.conf for config file details man -C config_file : Specify a configuration file Default is /private/etc/man.conf See also: roff , groff , nroff , troff , ditroff Using a custom 'Pager' This is probably best set in either $PAGER or $MANPAGER in .bashrc default pager: /usr/bin/less -is override: man man -P \"/usr/bin/less -Nis gives you line numbers overrides MANPAGER environment variable MANPAGER overrides PAGER environment variable Consider setting this in .bashrc Supporting and Coordinating Applications man -k - same as apropos likely man -k is the most convenient method, \"equivalent to apropos\" apropos - search the whatis database for \"strings\". man -f - same as whatis whatis - search the whatis database for \"complete keywords\". only displays complete word matches the whatis database is created with the command /usr/libexec/makewhatis man -K Search for a specified string in all man pages. Continues search even after you say 'y' and open a manpage still pretty slow, tested with man -K vimtutor","title":"Manpages"},{"location":"docs/references/manpages/#using-manpages","text":"Ever wonder if \"man\" has a man page? Ever stare deep into man's soul? Now you don't have to type \"man man\" to see man's deepest features. This document is derived mostly from man man and its references.","title":"Using manpages"},{"location":"docs/references/manpages/#viewing-all-related-man-pages","text":"Use man -wa to see all manpages that would be opened Another option: man -aW man | xargs ls -l See what manpage files would be opened man -w or man --path Supposedly -W gives one per line with no description Use man -a to sequentially view all manpages with the given title","title":"Viewing all related man pages"},{"location":"docs/references/manpages/#man-checks-path-for-manpages","text":"If an application is on $PATH, man finds it on system path. Specify folders: man man -M /usr/share/man:/usr/local/share/man Can search and open local manpages this way Or specify MANPATH in your man config.`","title":"man checks $PATH for manpages"},{"location":"docs/references/manpages/#configuration","text":"Check out $ man man.conf for config file details man -C config_file : Specify a configuration file Default is /private/etc/man.conf See also: roff , groff , nroff , troff , ditroff","title":"Configuration"},{"location":"docs/references/manpages/#using-a-custom-pager","text":"This is probably best set in either $PAGER or $MANPAGER in .bashrc default pager: /usr/bin/less -is override: man man -P \"/usr/bin/less -Nis gives you line numbers overrides MANPAGER environment variable MANPAGER overrides PAGER environment variable Consider setting this in .bashrc","title":"Using a custom 'Pager'"},{"location":"docs/references/manpages/#supporting-and-coordinating-applications","text":"man -k - same as apropos likely man -k is the most convenient method, \"equivalent to apropos\" apropos - search the whatis database for \"strings\". man -f - same as whatis whatis - search the whatis database for \"complete keywords\". only displays complete word matches the whatis database is created with the command /usr/libexec/makewhatis man -K Search for a specified string in all man pages. Continues search even after you say 'y' and open a manpage still pretty slow, tested with man -K vimtutor","title":"Supporting and Coordinating Applications"},{"location":"docs/references/migrate_mysql_to_postgresql/","text":"Migrating from MySQL to PostgreSQL There are a number of guides for this. MediaWiki-Vagrant Test Environment This environment was setup. The git/gerrit user given was anonymous during setup.sh . MediaWiki specific migration Note that the postgres backend is volunteer supported. Official Page Specific section, seems out of date The perl script seems to proscribe (in its header notes) just spinning up a postgres database and attaching it to a working mediawiki instance then importing a mediawiki backup created with maintenance/dumpBackup.php . \"Moving a wiki\" postgres issues: phabricator.org MediaWiki Test Environment This env probably starts with a MySQL database, so it will need reconfigured Official howto Configuring for PostgreSQL todo... Postgres Wiki wiki.postgres.org: high level planning wiki.postgres.org: general converting guide Specific Tooling: pgloader pgloader github project pgloader howto","title":"Migrate Mysql To Postgresql"},{"location":"docs/references/migrate_mysql_to_postgresql/#migrating-from-mysql-to-postgresql","text":"There are a number of guides for this.","title":"Migrating from MySQL to PostgreSQL"},{"location":"docs/references/migrate_mysql_to_postgresql/#mediawiki-vagrant-test-environment","text":"This environment was setup. The git/gerrit user given was anonymous during setup.sh .","title":"MediaWiki-Vagrant Test Environment"},{"location":"docs/references/migrate_mysql_to_postgresql/#mediawiki-specific-migration","text":"Note that the postgres backend is volunteer supported. Official Page Specific section, seems out of date The perl script seems to proscribe (in its header notes) just spinning up a postgres database and attaching it to a working mediawiki instance then importing a mediawiki backup created with maintenance/dumpBackup.php . \"Moving a wiki\" postgres issues: phabricator.org","title":"MediaWiki specific migration"},{"location":"docs/references/migrate_mysql_to_postgresql/#mediawiki-test-environment","text":"This env probably starts with a MySQL database, so it will need reconfigured Official howto","title":"MediaWiki Test Environment"},{"location":"docs/references/migrate_mysql_to_postgresql/#configuring-for-postgresql","text":"todo...","title":"Configuring for PostgreSQL"},{"location":"docs/references/migrate_mysql_to_postgresql/#postgres-wiki","text":"wiki.postgres.org: high level planning wiki.postgres.org: general converting guide","title":"Postgres Wiki"},{"location":"docs/references/migrate_mysql_to_postgresql/#specific-tooling-pgloader","text":"pgloader github project pgloader howto","title":"Specific Tooling: pgloader"},{"location":"docs/references/molecular_geometry/","text":"Molecular Geometry A redux of molecular geometry intended for writing a software module for describing the properties. Key Principles Mathematical Chemistry wikipedia: Mathematical Chemistry Topology wikipedia: Topology (chemistry) In chemistry, topology provides a convenient way of describing and predicting the molecular structure within the constraints of three-dimensional (3-D) space. Given the determinants of chemical bonding and the chemical properties of the atoms, topology provides a model for explaining how the atoms ethereal wave functions must fit together. Molecular topology is a part of mathematical chemistry dealing with the algebraic description of chemical compounds so allowing a unique and easy characterization of them. Topology is insensitive to the details of a scalar field, and can often be determined using simplified calculations. Scalar fields such as electron density, Madelung field, covalent field and the electrostatic potential can be used to model topology.[1] Each scalar field has its own distinctive topology and each provides different information about the nature of chemical bonding and structure. The analysis of these topologies, when combined with simple electrostatic theory and a few empirical observations, leads to a quantitative model of localized chemical bonding. In the process, the analysis provides insights into the nature of chemical bonding. Applied topology explains how large molecules reach their final shapes and how biological molecules achieve their activity. Circuit topology is a topological property of folded linear polymers. This notion has been applied to structural analysis of biomolecules such as proteins and RNAs. Topological Index wikipedia: Topological Index In the fields of chemical graph theory, molecular topology, and mathematical chemistry, a topological index also known as a connectivity index is a type of a molecular descriptor that is calculated based on the molecular graph of a chemical compound.[1] Topological indices are numerical parameters of a graph which characterize its topology and are usually graph invariant. Topological indices are used for example in the development of quantitative structure-activity relationships (QSARs) in which the biological activity or other properties of molecules are correlated with their chemical structure.[2] Chemical Graph Theory wikipedia: Chemical Graph Theory Chemical graph theory is the topology branch of mathematical chemistry which applies graph theory to mathematical modelling of chemical phenomena.[1] The pioneers of the chemical graph theory are Alexandru Balaban, Ante Graovac, Ivan Gutman, Haruo Hosoya, Milan Randi\u0107 and Nenad Trinajsti\u0107[2] (also Harry Wiener and others). In 1988, it was reported that several hundred researchers worked in this area producing about 500 articles annually. A number of monographs have been written in the area, including the two-volume comprehensive text by Trinajstic, Chemical Graph Theory, that summarized the field up to mid-1980s.[3] The adherents of the theory maintain that the properties of a chemical graph (i.e., a graph-theoretical representation of a molecule) give valuable insights into the chemical phenomena. The opponents contend that graphs play only a fringe role in chemical research.[4] One variant of the theory is the representation of materials as infinite Euclidean graphs, particularly crystals by periodic graphs. Cheminformatics wikipedia: Cheminformatics Cheminformatics (also known as chemoinformatics, chemioinformatics and chemical informatics) is the use of computer and informational techniques applied to a range of problems in the field of chemistry. These in silico techniques are used, for example, in pharmaceutical companies in the process of drug discovery. These methods can also be used in chemical and allied industries in various other forms. Cheminformatics combines the scientific working fields of chemistry, computer science and information science for example in the areas of topology, chemical graph theory, information retrieval and data mining in the chemical space.[5][6][7][8] Cheminformatics can also be applied to data analysis for various industries like paper and pulp, dyes and such allied industries. Chemical Space Concept: Theoretical Space vs. Concrete Space . wikipedioa: Chemical Space Chemical space is a concept in cheminformatics referring to the property space spanned by all possible molecules and chemical compounds adhering to a given set of construction principles and boundary conditions. Molecule Mining This article lists 20 different computer programming models for mining molecules. wikipedia: molecule mining Molecular query methods: Warmr[12][13], AGM[14][15], PolyFARM[16], FSG[17][18], MolFea[19], MoFa/MoSS[20][21][22], Gaston[23], LAZAR[24], ParMol[25] (contains MoFa, FFSM, gSpan, and Gaston), optimized gSpan[26][27], SMIREP[28], DMax[29], SAm/AIm/RHC[30], AFGen[31], gRed[32], G-Hash[33] Methods based on special architectures of neural networks BPZ[34][35], ChemNet[36], CCS[37][38], MolNet[39], Graph machines[40] This page describes mining for molecules. Since molecules may be represented by molecular graphs this is strongly related to graph mining and structured data mining. The main problem is how to represent molecules while discriminating the data instances. One way to do this is chemical similarity metrics, which has a long tradition in the field of cheminformatics. Typical approaches to calculate chemical similarities use chemical fingerprints, but this loses the underlying information about the molecule topology. Mining the molecular graphs directly avoids this problem. So does the inverse QSAR problem which is preferable for vectorial mappings. Molecular Query Language wikipedia: Molecular Query Language The Molecular Query Language (MQL) was designed to allow more complex, problem-specific search methods in chemoinformatics. In contrast to the widely used SMARTS queries, MQL provides for the specification of spatial and physicochemical properties of atoms and bonds. Additionally, it can easily be extended to handle non-atom-based graphs, also known as \"reduced feature\" graphs. The query language is based on an extended Backus\u2013Naur form (EBNF) using JavaCC. SMARTS: Smiles arbitrary target specification The article has tons of detail about SMARTS which is apparently a contrasting method to MQL (Molecular Query Language). wikipedia: Smiles arbitrary target specification SMiles ARbitrary Target Specification (SMARTS) is a language for specifying substructural patterns in molecules. The SMARTS line notation is expressive and allows extremely precise and transparent substructural specification and atom typing. SMARTS is related to the SMILES line notation[1] that is used to encode molecular structures and like SMILES was originally developed by David Weininger and colleagues at Daylight Chemical Information Systems. The most comprehensive descriptions of the SMARTS language can be found in Daylight's SMARTS theory manual,[2] tutorial [3] and examples.[4] OpenEye Scientific Software has developed their own version of SMARTS which differs from the original Daylight version in how the R descriptor (see cyclicity below) is defined. The standard may require updates to accommodate for new the elements named in 2016.[5] Transferability Both bond length and bond angle are transferable. The opposite of transferable is conserved e.g. standard atomic weight. From: wikipedia: Tranferability (chemistry) Transferability, in chemistry, is the assumption that a chemical property that is associated with an atom or a functional group in a molecule will have a similar (but not identical) value in a variety of different circumstances. My ideas about constraints you could use experimental bond angle ranges predictively how much synthesis/prediction can really be done how often do symmetric molecules 'flip flop' or are they really static? what effect from/on brownian motion? Resources wikipedia: Molecular Geometry","title":"Molecular Geometry"},{"location":"docs/references/molecular_geometry/#molecular-geometry","text":"A redux of molecular geometry intended for writing a software module for describing the properties.","title":"Molecular Geometry"},{"location":"docs/references/molecular_geometry/#key-principles","text":"","title":"Key Principles"},{"location":"docs/references/molecular_geometry/#mathematical-chemistry","text":"wikipedia: Mathematical Chemistry","title":"Mathematical Chemistry"},{"location":"docs/references/molecular_geometry/#topology","text":"wikipedia: Topology (chemistry) In chemistry, topology provides a convenient way of describing and predicting the molecular structure within the constraints of three-dimensional (3-D) space. Given the determinants of chemical bonding and the chemical properties of the atoms, topology provides a model for explaining how the atoms ethereal wave functions must fit together. Molecular topology is a part of mathematical chemistry dealing with the algebraic description of chemical compounds so allowing a unique and easy characterization of them. Topology is insensitive to the details of a scalar field, and can often be determined using simplified calculations. Scalar fields such as electron density, Madelung field, covalent field and the electrostatic potential can be used to model topology.[1] Each scalar field has its own distinctive topology and each provides different information about the nature of chemical bonding and structure. The analysis of these topologies, when combined with simple electrostatic theory and a few empirical observations, leads to a quantitative model of localized chemical bonding. In the process, the analysis provides insights into the nature of chemical bonding. Applied topology explains how large molecules reach their final shapes and how biological molecules achieve their activity. Circuit topology is a topological property of folded linear polymers. This notion has been applied to structural analysis of biomolecules such as proteins and RNAs.","title":"Topology"},{"location":"docs/references/molecular_geometry/#topological-index","text":"wikipedia: Topological Index In the fields of chemical graph theory, molecular topology, and mathematical chemistry, a topological index also known as a connectivity index is a type of a molecular descriptor that is calculated based on the molecular graph of a chemical compound.[1] Topological indices are numerical parameters of a graph which characterize its topology and are usually graph invariant. Topological indices are used for example in the development of quantitative structure-activity relationships (QSARs) in which the biological activity or other properties of molecules are correlated with their chemical structure.[2]","title":"Topological Index"},{"location":"docs/references/molecular_geometry/#chemical-graph-theory","text":"wikipedia: Chemical Graph Theory Chemical graph theory is the topology branch of mathematical chemistry which applies graph theory to mathematical modelling of chemical phenomena.[1] The pioneers of the chemical graph theory are Alexandru Balaban, Ante Graovac, Ivan Gutman, Haruo Hosoya, Milan Randi\u0107 and Nenad Trinajsti\u0107[2] (also Harry Wiener and others). In 1988, it was reported that several hundred researchers worked in this area producing about 500 articles annually. A number of monographs have been written in the area, including the two-volume comprehensive text by Trinajstic, Chemical Graph Theory, that summarized the field up to mid-1980s.[3] The adherents of the theory maintain that the properties of a chemical graph (i.e., a graph-theoretical representation of a molecule) give valuable insights into the chemical phenomena. The opponents contend that graphs play only a fringe role in chemical research.[4] One variant of the theory is the representation of materials as infinite Euclidean graphs, particularly crystals by periodic graphs.","title":"Chemical Graph Theory"},{"location":"docs/references/molecular_geometry/#cheminformatics","text":"wikipedia: Cheminformatics Cheminformatics (also known as chemoinformatics, chemioinformatics and chemical informatics) is the use of computer and informational techniques applied to a range of problems in the field of chemistry. These in silico techniques are used, for example, in pharmaceutical companies in the process of drug discovery. These methods can also be used in chemical and allied industries in various other forms. Cheminformatics combines the scientific working fields of chemistry, computer science and information science for example in the areas of topology, chemical graph theory, information retrieval and data mining in the chemical space.[5][6][7][8] Cheminformatics can also be applied to data analysis for various industries like paper and pulp, dyes and such allied industries.","title":"Cheminformatics"},{"location":"docs/references/molecular_geometry/#chemical-space","text":"Concept: Theoretical Space vs. Concrete Space . wikipedioa: Chemical Space Chemical space is a concept in cheminformatics referring to the property space spanned by all possible molecules and chemical compounds adhering to a given set of construction principles and boundary conditions.","title":"Chemical Space"},{"location":"docs/references/molecular_geometry/#molecule-mining","text":"This article lists 20 different computer programming models for mining molecules. wikipedia: molecule mining Molecular query methods: Warmr[12][13], AGM[14][15], PolyFARM[16], FSG[17][18], MolFea[19], MoFa/MoSS[20][21][22], Gaston[23], LAZAR[24], ParMol[25] (contains MoFa, FFSM, gSpan, and Gaston), optimized gSpan[26][27], SMIREP[28], DMax[29], SAm/AIm/RHC[30], AFGen[31], gRed[32], G-Hash[33] Methods based on special architectures of neural networks BPZ[34][35], ChemNet[36], CCS[37][38], MolNet[39], Graph machines[40] This page describes mining for molecules. Since molecules may be represented by molecular graphs this is strongly related to graph mining and structured data mining. The main problem is how to represent molecules while discriminating the data instances. One way to do this is chemical similarity metrics, which has a long tradition in the field of cheminformatics. Typical approaches to calculate chemical similarities use chemical fingerprints, but this loses the underlying information about the molecule topology. Mining the molecular graphs directly avoids this problem. So does the inverse QSAR problem which is preferable for vectorial mappings.","title":"Molecule Mining"},{"location":"docs/references/molecular_geometry/#molecular-query-language","text":"wikipedia: Molecular Query Language The Molecular Query Language (MQL) was designed to allow more complex, problem-specific search methods in chemoinformatics. In contrast to the widely used SMARTS queries, MQL provides for the specification of spatial and physicochemical properties of atoms and bonds. Additionally, it can easily be extended to handle non-atom-based graphs, also known as \"reduced feature\" graphs. The query language is based on an extended Backus\u2013Naur form (EBNF) using JavaCC.","title":"Molecular Query Language"},{"location":"docs/references/molecular_geometry/#smarts-smiles-arbitrary-target-specification","text":"The article has tons of detail about SMARTS which is apparently a contrasting method to MQL (Molecular Query Language). wikipedia: Smiles arbitrary target specification SMiles ARbitrary Target Specification (SMARTS) is a language for specifying substructural patterns in molecules. The SMARTS line notation is expressive and allows extremely precise and transparent substructural specification and atom typing. SMARTS is related to the SMILES line notation[1] that is used to encode molecular structures and like SMILES was originally developed by David Weininger and colleagues at Daylight Chemical Information Systems. The most comprehensive descriptions of the SMARTS language can be found in Daylight's SMARTS theory manual,[2] tutorial [3] and examples.[4] OpenEye Scientific Software has developed their own version of SMARTS which differs from the original Daylight version in how the R descriptor (see cyclicity below) is defined. The standard may require updates to accommodate for new the elements named in 2016.[5]","title":"SMARTS: Smiles arbitrary target specification"},{"location":"docs/references/molecular_geometry/#transferability","text":"Both bond length and bond angle are transferable. The opposite of transferable is conserved e.g. standard atomic weight. From: wikipedia: Tranferability (chemistry) Transferability, in chemistry, is the assumption that a chemical property that is associated with an atom or a functional group in a molecule will have a similar (but not identical) value in a variety of different circumstances.","title":"Transferability"},{"location":"docs/references/molecular_geometry/#my-ideas-about-constraints","text":"you could use experimental bond angle ranges predictively how much synthesis/prediction can really be done how often do symmetric molecules 'flip flop' or are they really static? what effect from/on brownian motion?","title":"My ideas about constraints"},{"location":"docs/references/molecular_geometry/#resources","text":"wikipedia: Molecular Geometry","title":"Resources"},{"location":"docs/references/pinebook/","text":"Suspend Two methods... you have to adjust the brightness afterwards Press Fn-Esc Type $ systemctl suspend Adjusting brightness stack overflow says any value 0 to 20 works, but it was at 255 after suspend sudo su -c 'echo 255 > /sys/class/backlight/lcd0/brightness' sudo su -c 'echo 0 > /sys/class/backlight/lcd0/brightness'","title":"Pinebook"},{"location":"docs/references/pinebook/#suspend","text":"Two methods... you have to adjust the brightness afterwards Press Fn-Esc Type $ systemctl suspend","title":"Suspend"},{"location":"docs/references/pinebook/#adjusting-brightness","text":"","title":"Adjusting brightness"},{"location":"docs/references/pinebook/#stack-overflow-says-any-value-0-to-20-works-but-it-was-at-255-after-suspend","text":"","title":"stack overflow says any value 0 to 20 works, but it was at 255 after suspend"},{"location":"docs/references/pinebook/#sudo-su-c-echo-255-sysclassbacklightlcd0brightness","text":"sudo su -c 'echo 0 > /sys/class/backlight/lcd0/brightness'","title":"sudo su -c 'echo 255 > /sys/class/backlight/lcd0/brightness'"},{"location":"docs/references/pivot_tables/","text":"Pivot Tables Resources Wikipedia Overview Google Sheets Pivot Tables postgres Pivot Tables postgres pivot table gist OLAP - a superset and 'precursor' to modern data formats First OLAP system from 1970, term began use in 1993. OLAP Cube Druid - Open Source Data Store different spreadsheet softwares pyspread","title":"Pivot Tables"},{"location":"docs/references/pivot_tables/#pivot-tables","text":"","title":"Pivot Tables"},{"location":"docs/references/pivot_tables/#resources","text":"Wikipedia Overview Google Sheets Pivot Tables postgres Pivot Tables postgres pivot table gist OLAP - a superset and 'precursor' to modern data formats First OLAP system from 1970, term began use in 1993. OLAP Cube Druid - Open Source Data Store different spreadsheet softwares pyspread","title":"Resources"},{"location":"docs/references/python-reference/","text":"Python Reference Materials Try to migrate the key component of these reference materials into this document. Links will inevitably become unavailable and the document should preserve the information. Most information here will likely be from a derivative source anyways, so some long term effort could be made to resubstantiate each section with a primary reference in the Python reference, library, PEPs, source code, etc. Sections Quick HTTP Server python -m http.server Python Operator Precedence Original Source Helpful and and or Idioms Set a default value with or python `def thing(foo, *, opt=None): opt = opt or {}` Avoid a zero division error with and when adding if statements python b = 0 a = (b and 100 / b) a 'sqlite3' Context Manager PyCon 2016 SQLite Class Video PyCon 2016 SQLite Class Code","title":"Python Reference"},{"location":"docs/references/python-reference/#python-reference-materials","text":"Try to migrate the key component of these reference materials into this document. Links will inevitably become unavailable and the document should preserve the information. Most information here will likely be from a derivative source anyways, so some long term effort could be made to resubstantiate each section with a primary reference in the Python reference, library, PEPs, source code, etc.","title":"Python Reference Materials"},{"location":"docs/references/python-reference/#sections","text":"","title":"Sections"},{"location":"docs/references/python-reference/#quick-http-server","text":"python -m http.server","title":"Quick HTTP Server"},{"location":"docs/references/python-reference/#python-operator-precedence","text":"Original Source","title":"Python Operator Precedence"},{"location":"docs/references/python-reference/#helpful-and-and-or-idioms","text":"Set a default value with or python `def thing(foo, *, opt=None): opt = opt or {}` Avoid a zero division error with and when adding if statements python b = 0 a = (b and 100 / b) a","title":"Helpful and and or Idioms"},{"location":"docs/references/python-reference/#sqlite3-context-manager","text":"PyCon 2016 SQLite Class Video PyCon 2016 SQLite Class Code","title":"'sqlite3' Context Manager"},{"location":"docs/references/python_generator_pattern/","text":"Python Generators from Principles Outline notes come from here . The code has been slightly modified to sum to the first n inclusive. Future: Include information about converting list comprehensions into generator comprehensions. A simple use case for a generator, described without any generators def firstn ( n ): \"\"\" The code works. Problem: the function sends the entire list at once (using memory). Memory constrained applications need a different way. \"\"\" num = 0 nums = [] while num <= n : nums . append ( num ) num += 1 return nums for i in range ( 10 ): print ( i , sum ( firstn ( i ))) Constructing a generator from scratch class firstn ( object ): \"\"\" The generator pattern (an iterable) From: https://wiki.python.org/moin/Generators Notes: This pattern is compacted into the Python `generator function` and can be accessed by using the `yield` keyword in a function. \"\"\" def __init__ ( self , n ): self . n = n self . num = 0 self . nums = [] def __iter__ ( self ): return self # Python 3 compatibility def __next__ ( self ): return self . next () def next ( self ): if self . num <= self . n : cur = self . num self . num += 1 return cur else : raise StopIteration () for i in range ( 10 ): print ( i , sum ( firstn ( i ))) Using the generator pattern and yield keyword def firstn ( n ): \"\"\" The same code as a generator. From: https://wiki.python.org/moin/Generators \"\"\" num = 0 while num <= n : yield num num += 1 for i in range ( 10 ): print ( i , sum ( firstn ( i ))) Problem: How do we get a list out of a generator? # Python 2 `xrange` generator example, Python 3 would use `range` in the `for` loop. items = [] for i in xrange ( 10 ): # generate the list items . append ( i ) print ( items ) Generator Comprehensions Generators can be composed from other generators Open question: why not use Python 2 xrange or Python 3 range in a generator composition? def irange ( start , stop = None , step = 1 ): \"\"\" Implementation of irange from Python wiki (https://wiki.python.org/moin/RangeGenerator) \"\"\" if step == 0 : raise ValueError ( \"irange() step argument must not be zero\" ) if stop is None : stop = start start = 0 continue_cmp = ( step < 0 ) * 2 - i while cmp ( start , stop ) == continue_cmp : yield start start += step square = ( i * i for i in irange ( 1000000 )) total = 0 for i in square : total += i","title":"Python Generator Pattern"},{"location":"docs/references/python_generator_pattern/#python-generators-from-principles","text":"Outline notes come from here . The code has been slightly modified to sum to the first n inclusive.","title":"Python Generators from Principles"},{"location":"docs/references/python_generator_pattern/#future","text":"Include information about converting list comprehensions into generator comprehensions.","title":"Future:"},{"location":"docs/references/python_generator_pattern/#a-simple-use-case-for-a-generator-described-without-any-generators","text":"def firstn ( n ): \"\"\" The code works. Problem: the function sends the entire list at once (using memory). Memory constrained applications need a different way. \"\"\" num = 0 nums = [] while num <= n : nums . append ( num ) num += 1 return nums for i in range ( 10 ): print ( i , sum ( firstn ( i )))","title":"A simple use case for a generator, described without any generators"},{"location":"docs/references/python_generator_pattern/#constructing-a-generator-from-scratch","text":"class firstn ( object ): \"\"\" The generator pattern (an iterable) From: https://wiki.python.org/moin/Generators Notes: This pattern is compacted into the Python `generator function` and can be accessed by using the `yield` keyword in a function. \"\"\" def __init__ ( self , n ): self . n = n self . num = 0 self . nums = [] def __iter__ ( self ): return self # Python 3 compatibility def __next__ ( self ): return self . next () def next ( self ): if self . num <= self . n : cur = self . num self . num += 1 return cur else : raise StopIteration () for i in range ( 10 ): print ( i , sum ( firstn ( i )))","title":"Constructing a generator from scratch"},{"location":"docs/references/python_generator_pattern/#using-the-generator-pattern-and-yield-keyword","text":"def firstn ( n ): \"\"\" The same code as a generator. From: https://wiki.python.org/moin/Generators \"\"\" num = 0 while num <= n : yield num num += 1 for i in range ( 10 ): print ( i , sum ( firstn ( i )))","title":"Using the generator pattern and yield keyword"},{"location":"docs/references/python_generator_pattern/#problem-how-do-we-get-a-list-out-of-a-generator","text":"# Python 2 `xrange` generator example, Python 3 would use `range` in the `for` loop. items = [] for i in xrange ( 10 ): # generate the list items . append ( i ) print ( items )","title":"Problem: How do we get a list out of a generator?"},{"location":"docs/references/python_generator_pattern/#generator-comprehensions","text":"","title":"Generator Comprehensions"},{"location":"docs/references/python_generator_pattern/#generators-can-be-composed-from-other-generators","text":"Open question: why not use Python 2 xrange or Python 3 range in a generator composition? def irange ( start , stop = None , step = 1 ): \"\"\" Implementation of irange from Python wiki (https://wiki.python.org/moin/RangeGenerator) \"\"\" if step == 0 : raise ValueError ( \"irange() step argument must not be zero\" ) if stop is None : stop = start start = 0 continue_cmp = ( step < 0 ) * 2 - i while cmp ( start , stop ) == continue_cmp : yield start start += step square = ( i * i for i in irange ( 1000000 )) total = 0 for i in square : total += i","title":"Generators can be composed from other generators"},{"location":"docs/references/react-basic/","text":"React Basics This is a draft version of a react outline from basics. Send PRs to correct any misconceptions. Resources react-boilerplate React official docs plot.ly React Tutorial Part 1: This section is confusingly written but the example is quite nice. See below. Part 2-6: The weather app seems like a nice example, but I don't plan to use create-react-app Plan: Try building this part in a static file with a transpiler service? Result: Parts 2, 3 are complete, using babel-standalone transpiler served from cdnjs Babel is the de facto JSX transpiler. babel-standalone - might be used as a static site transpiler? Official React Tutorial Getting Started Basics Capabilities - React Official Docs React can be used in: Frontend Stack React Native (mobile) Server Side (node) React Components: Keep state out of DOM Encapsulated Compose them to make complex UIs Build them Declarative Views Design Simple Views for each state in your application React efficiently updates and renders just the right components when the data changes Plot.ly Introduction - Weather App Who uses react? Netflix, Airbnb, etc. Why React? For \"building large applications with data that changes over time\" Components: composable, reusable, encapsulated Lets Build: A Counter that updates state. react.jsbin.com - a fully featured react environment React is 2 Libraries: React - allows you to create ReactElements ReactDOM - renders the ReactElements Why the split? You could theoretically render those ReactElements anywhere Boilerplate HTML for this section html React
    Example javascript ReactDOM.render( React.createElement('h1', {className: 'heading'}, 'Hello World!'), document.getElementById('container') ); ReactDOM.render() will render a ReactElement created by React.createElement() The DOM node we want to render (2nd argument) is called the entry point ReactElements take three arguments: The node we want to create (HTML Element) A JavaScript Object of information (like 'type') Optionally a child such as innerText or another ReactElement A child element like this does get null for the second argument Components: Creating a ReactComponent Component is a function that receives props - short for properties ```javascript // What is the purpose of props here? Does it allow us to pass the child ReactElement? var Wrapper = function(props) { return( React.createElement('div', { className: 'wrapper'}, props.children); ); } React.createElement(Wrapper, {}, 'Hello World!'); ReactDOM.render( React.createElement(Wrapper, null, React.createElement('h1', { className: 'heading' }, 'Hello World!') ), document.getElementById('container') ); ``` Converting our ReactComponent to JSX JSX is 'nothing but a wrapper on React.createElement To use Javascript in JSX, wrap it in curly braces. JSX always must be transpiled with a build tool. How to transpile JSX in your build environment? - Babel / Gulp - npm install --save-dev babel-cli babel-preset-react javascript var Wrapper = function(props) { return (
    { props.children }
    ); }; ReactDOM.render(

    Hello World!

    , document.getElementById('container') ); 7. Classes - 1. Event handlers like onClick , onMouseOver , etc. CANNOT go in a ReactComponent. - These handlers must be attached to an actual DOM node. - This 'Counter' object actually demonstrates passing Event Handlers. ``` javascript class Counter extends React . Component { render () { return ( < div > < p > This is a Counter component ! < Button text = \"Click me!\" onClick = { function () { console . log ( 'click!' ) }} /> ); } } // Button pulls ` props ` from ReactComponent JSX ( React . CreateElement ) var Button = function ( props ) { return ( < button onClick = { props . onClick } > { props . text } ); } ReactDOM . render ( < Counter /> document . getElementById ( 'container' ) ); ``` Handling State - State is a plain object in react, with any number of properties. constructor is used to assign initial state Lets make counter do what it is supposed to do with state. The { } JSX notation works with any variable, example { myPotato } ``javascript class Counter extends React.Component { constructor() { super(); this.state = { clicks: 0 }; // \" this is undefined in increment because of the way ES6 Classes work // This explanation is terrible. Why again must we bind this ? // Trent: According to MDN, bind will make a new bound function and bind whatever you pass as this` for that function. The bound function wraps the original function object. // Trent: But why is increment set in the constructor? Is increment constructed before the constructor? Maybe... not sure. Alternative idea: Can you bind a function and then define it? this.increment = this.increment.bind(this); } increment() { this.setState({ clicks: this.state.clicks + 1 }); }; render() { return (

    This is a Counter component! The button was clicked { this.state.clicks } times.

    ); } } // Button pulls props from ReactComponent JSX (React.CreateElement) var Button = function(props) { return ( { props.text } ); } ReactDOM.render( document.getElementById('container') ); ``` Whenever the state changes, the

    element is updated. Plot.ly Part II - Your First App New Concepts XMLHttpRequest asynchronous w/ event listener triggers React state change Receiving data with an API on the client side Note that you can set a cookie for the client and use it to authenticate against your own API for that user... handling this by alias inside a child function with its own this Using arrow functions to manage state. Using preventDefault to prevent a form's default submit behavior Declaring a variable currentTemp and managing its default value and state. Plot.ly Part III - Plot.ly - Adding a Forecast Graph New Concepts ComponentDidMount, ComponentDidUpdate build Plot component around plot.ly library (imported with cdnjs) Interacting with a plot.ly graph's plotly_click event handler. Managing state with a complex UI -- still kind of a rats nest. Tie plot.ly event handler and CSS IDs into onPlotClick component (props.onPlotClick) Plot.ly Part IV - State Management with Redux","title":"React Basic"},{"location":"docs/references/react-basic/#react-basics","text":"This is a draft version of a react outline from basics. Send PRs to correct any misconceptions.","title":"React Basics"},{"location":"docs/references/react-basic/#resources","text":"react-boilerplate React official docs plot.ly React Tutorial Part 1: This section is confusingly written but the example is quite nice. See below. Part 2-6: The weather app seems like a nice example, but I don't plan to use create-react-app Plan: Try building this part in a static file with a transpiler service? Result: Parts 2, 3 are complete, using babel-standalone transpiler served from cdnjs Babel is the de facto JSX transpiler. babel-standalone - might be used as a static site transpiler? Official React Tutorial","title":"Resources"},{"location":"docs/references/react-basic/#getting-started","text":"Basics Capabilities - React Official Docs React can be used in: Frontend Stack React Native (mobile) Server Side (node) React Components: Keep state out of DOM Encapsulated Compose them to make complex UIs Build them Declarative Views Design Simple Views for each state in your application React efficiently updates and renders just the right components when the data changes","title":"Getting Started"},{"location":"docs/references/react-basic/#plotly-introduction-weather-app","text":"Who uses react? Netflix, Airbnb, etc. Why React? For \"building large applications with data that changes over time\" Components: composable, reusable, encapsulated Lets Build: A Counter that updates state. react.jsbin.com - a fully featured react environment React is 2 Libraries: React - allows you to create ReactElements ReactDOM - renders the ReactElements Why the split? You could theoretically render those ReactElements anywhere Boilerplate HTML for this section html React

    Example javascript ReactDOM.render( React.createElement('h1', {className: 'heading'}, 'Hello World!'), document.getElementById('container') ); ReactDOM.render() will render a ReactElement created by React.createElement() The DOM node we want to render (2nd argument) is called the entry point ReactElements take three arguments: The node we want to create (HTML Element) A JavaScript Object of information (like 'type') Optionally a child such as innerText or another ReactElement A child element like this does get null for the second argument Components: Creating a ReactComponent Component is a function that receives props - short for properties ```javascript // What is the purpose of props here? Does it allow us to pass the child ReactElement? var Wrapper = function(props) { return( React.createElement('div', { className: 'wrapper'}, props.children); ); } React.createElement(Wrapper, {}, 'Hello World!'); ReactDOM.render( React.createElement(Wrapper, null, React.createElement('h1', { className: 'heading' }, 'Hello World!') ), document.getElementById('container') ); ``` Converting our ReactComponent to JSX JSX is 'nothing but a wrapper on React.createElement To use Javascript in JSX, wrap it in curly braces. JSX always must be transpiled with a build tool. How to transpile JSX in your build environment?","title":"Plot.ly Introduction - Weather App"},{"location":"docs/references/react-basic/#-babel-gulp-npm-install-save-dev-babel-cli-babel-preset-react","text":"javascript var Wrapper = function(props) { return (
    { props.children }
    ); }; ReactDOM.render(

    Hello World!

    , document.getElementById('container') ); 7. Classes - 1. Event handlers like onClick , onMouseOver , etc. CANNOT go in a ReactComponent. - These handlers must be attached to an actual DOM node. - This 'Counter' object actually demonstrates passing Event Handlers. ``` javascript class Counter extends React . Component { render () { return ( < div > < p > This is a Counter component ! < Button text = \"Click me!\" onClick = { function () { console . log ( 'click!' ) }} /> ); } } // Button pulls ` props ` from ReactComponent JSX ( React . CreateElement ) var Button = function ( props ) { return ( < button onClick = { props . onClick } > { props . text } ); } ReactDOM . render ( < Counter /> document . getElementById ( 'container' ) ); ``` Handling State - State is a plain object in react, with any number of properties. constructor is used to assign initial state Lets make counter do what it is supposed to do with state. The { } JSX notation works with any variable, example { myPotato } ``javascript class Counter extends React.Component { constructor() { super(); this.state = { clicks: 0 }; // \" this is undefined in increment because of the way ES6 Classes work // This explanation is terrible. Why again must we bind this ? // Trent: According to MDN, bind will make a new bound function and bind whatever you pass as this` for that function. The bound function wraps the original function object. // Trent: But why is increment set in the constructor? Is increment constructed before the constructor? Maybe... not sure. Alternative idea: Can you bind a function and then define it? this.increment = this.increment.bind(this); } increment() { this.setState({ clicks: this.state.clicks + 1 }); }; render() { return (

    This is a Counter component! The button was clicked { this.state.clicks } times.

    ); } } // Button pulls props from ReactComponent JSX (React.CreateElement) var Button = function(props) { return ( { props.text } ); } ReactDOM.render( document.getElementById('container') ); ``` Whenever the state changes, the

    element is updated.","title":"- Babel / Gulp - npm install --save-dev babel-cli babel-preset-react"},{"location":"docs/references/react-basic/#plotly-part-ii-your-first-app","text":"New Concepts XMLHttpRequest asynchronous w/ event listener triggers React state change Receiving data with an API on the client side Note that you can set a cookie for the client and use it to authenticate against your own API for that user... handling this by alias inside a child function with its own this Using arrow functions to manage state. Using preventDefault to prevent a form's default submit behavior Declaring a variable currentTemp and managing its default value and state.","title":"Plot.ly Part II - Your First App"},{"location":"docs/references/react-basic/#plotly-part-iii-plotly-adding-a-forecast-graph","text":"New Concepts ComponentDidMount, ComponentDidUpdate build Plot component around plot.ly library (imported with cdnjs) Interacting with a plot.ly graph's plotly_click event handler. Managing state with a complex UI -- still kind of a rats nest. Tie plot.ly event handler and CSS IDs into onPlotClick component (props.onPlotClick)","title":"Plot.ly Part III - Plot.ly - Adding a Forecast Graph"},{"location":"docs/references/react-basic/#plotly-part-iv-state-management-with-redux","text":"","title":"Plot.ly Part IV - State Management with Redux"},{"location":"docs/references/rust_plan/","text":"A Plan to Learn Rust I was planning on learning C but it's tough to get up to speed and people seem to have wildly varying practices. It would be better to learn low level things in a modern context with less baggage. The Plan Todo Go through the book (2nd edition) and check out the community maintained git repo. Skip the git project of examples for now, I've checked them out before and should learn the rust book before checking them out again. How do I get a .gitignore to be generated when I do cargo new --bin variables or similar? What's the deal with shadowing? Sure it's fine, but you could end up with a bunch of values that never get garbage collected, what other tradeoffs are there? Perhaps the same type management issues that Python is attempting to solve with type annotation. Why use shadowing? Done Learn about rustup and how to maintain your rust toolchain. Hopefully build an analogy to python-virtualenv . Ingesting Anthologies and Aggregators of Rust Information More Resource Compilations to Ingest Rust Anthology readrust.net interesting post aggregator rust community blog project euler in rust hackr.io tutorials learn-rust tutorials and courses rust design patterns Already Ingested Here & Date rust-learning - 2018.08.13 Tools Tools for Rust. Places to get help there are a number of places you can get help. The easiest is the #rust IRC channel on irc.mozilla.org, which you can access through Mibbit. At that address you can chat with other Rustaceans (a silly nickname we call ourselves) who can help you out. Other great resources include the Users forum and Stack Overflow. Local Documentation try: rustup doc rustup Switch between stable and nightly you will need some or all of these: rustup update rustup install nightly switch with: rustup default nightly or rustup default stable rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated . It makes cross-compiling simpler with binary builds of the standard library for common platforms. And it runs on all platforms Rust supports, including Windows. (emphasis mine) rustup is a toolchain multiplexer. It installs and manages many Rust toolchains and presents them all through a single set of tools installed to ~/.cargo/bin. The rustc and cargo installed to ~/.cargo/bin are proxies that delegate to the real toolchain. rustup then provides mechanisms to easily change the active toolchain by reconfiguring the behavior of the proxies. Clippy Linter - nightly only. Use it! Playpen You can put your rust in a gist and put it in Playpen and then share it with others who can see it run. Good tool for collaboration. Crater I don't think this is useful until I'm trying to switch between stable and nightly with tons of dependencies. detect regressions in rust compiler against a bunch of crates github project Check the differences between stable and target only for sandboxed environments, it's very destructive... so I guess only on vms. Cargo howto: specify cargo dependencies This is manual... but I prefer cargo-edit so far for add/rm/upgrade Make sure to cargo install cargo-edit This gives you the ability to use cargo add/rm/upgrade for example cargo add num_bigint Rust cargo guide Cargo is a tool that allows Rust projects to declare their various dependencies and ensure that you\u2019ll always get a repeatable build. To accomplish this goal, Cargo does four things: Introduces two metadata files with various bits of project information. Fetches and builds your project\u2019s dependencies. Invokes rustc or another build tool with the correct parameters to build your project. Introduces conventions to make working with Rust projects easier. GDB GDB supports Rust Lizzie says no one uses it \"The Book 2nd Ed.\" aka \"The Rust Programming Language\" When you finish this you will be an intermediate rust programmer. In general, this book assumes that you\u2019re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a topic; we typically revisit the topic in a later chapter. You\u2019ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you\u2019ll learn about an aspect of Rust. In project chapters, we\u2019ll build small programs together, applying what you\u2019ve learned so far. Chapters 2, 12, and 20 are project chapters; the rest are concept chapters. Rust 101 Youtube (20 Jan 2017) Speaker: E. Dunham; @qedunham (Mozilla) source slides Exercises Rustlings repo Rust By Example book Macros Macros are syntactic sugar for functions that take a variable number of arguments... Need more content, see rust book v2. Inclusive and Exclusive Ranges .. is an exclusive range, ..= is an inclusive range This is true for both matches and expressions The old match-only inclusive range syntax ... is still acceptable in match-only but not recommended and does not work in expressions See rust book v2 appendix 6 Notes Rust is an expression based language Statements are instructions that perform some action and do not return a value. let y = 6; is a statement, it does not return a value Expressions evaluate to a resulting value. Expressions can be parts of statements: in let y = 6 , the 6 is an expression that evaluates to 6 . calling a function or calling a macro is an expression calling the block to create new scopes, {} , is an expression a function can have an expression and it will be returned by the function other languages don't have the same distinctions blocks of code inside if expressions or match expressions are sometimes called arms Remember that blocks of code evaluate to the last expression in them Chapter 2 Switching from an expect call to a match expression is how you generally move from crashing on an error to handling the error. Remember that parse returns a Result type and Result is an enum that has the variants Ok or Err . We\u2019re using a match expression here, as we did with the Ordering result of the cmp method. --- snip --- If parse is not able to turn the string into a number, it will return an Err value that contains more information about the error. The Err value does not match the Ok(num) pattern in the first match arm, but it does match the Err(_) pattern in the second arm. The underscore, _ , is a catchall value; in this example, we\u2019re saying we want to match all Err values, no matter what information they have inside them. So the program will execute the second arm\u2019s code, continue , which tells the program to go to the next iteration of the loop and ask for another guess. So effectively, the program ignores all errors that parse might encounter! Chapter 3 Function bodies are made up of a series of statements optionally ending in an expression. So far, we\u2019ve only covered functions without an ending expression, but you have seen an expression as part of a statement. Because Rust is an expression-based language, this is an important distinction to understand. Other languages don\u2019t have the same distinctions, so let\u2019s look at what statements and expressions are and how their differences affect the bodies of functions. We\u2019ve actually already used statements and expressions. Statements are instructions that perform some action and do not return a value. Expressions evaluate to a resulting value. Let\u2019s look at some examples. So how do you know which type of integer to use? If you\u2019re unsure, Rust\u2019s defaults are generally good choices, and integer types default to i32: this type is generally the fastest, even on 64-bit systems. The primary situation in which you\u2019d use isize or usize is when indexing some sort of collection. Floating-point numbers are represented according to the IEEE-754 standard. The f32 type is a single-precision float, and f64 has double precision. Rust\u2019s char type represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust. Unicode Scalar Values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive. However, a \u201ccharacter\u201d isn\u2019t really a concept in Unicode, so your human intuition for what a \u201ccharacter\u201d is may not match up with what a char is in Rust. We\u2019ll discuss this topic in detail in \u201cStrings\u201d in Chapter 8. Chapter 4: Understanding Ownership (ownership, references, borrowing, slices) Lifetimes are not covered in this chapter, see chapter 10. I think this most related to borrowing with async, which sounds like a hairball. Chapter 5: Using Structs to Structure Related Data Structs and enums (discussed in Chapter 6) are the building blocks for creating new types in your program\u2019s domain to take full advantage of Rust\u2019s compile time type checking. Use let to instantiate struct with kv pairs (not ordered). Use dot notation to get a value back from a struct. Entire struct instance must be mutable, not certain fields of struct instance. Mutability is on the instance not the struct definition Struct Instantiaton Example This valid expression is returned from the function and expressed in the function signature: fn build_user ( email : String , username : String ) -> User { User { email : email , username : username , active : true , sign_in_count : 1 , } } Resources Resources from main rust site. \"Are we _ yet?\" web app stuff game stuff also check out \"things that are not awesome yet in rust \" Articles Summaries go below. A list of 'fearless rust bloggers' Tutorials & Workshop Materials hackr.io tutorials \"Rust for Python Developers\" by Armin Ronacher Mutability, Borrows, and Owners Functions that operate on immutable borrows are marked as &self and functions that need a mutable borrow are marked as &mut self. You can only loan out references if you are the owner. If you want to move the value out of the function (for instance by returning it) you cannot have any outstanding loans and you cannot loan out values after having moved ownership away from yourself. This is a big change in how you think about programs but you will get used to it. Three rust things Armin wishes he learned earlier RUST'S OWNERSHIP MODEL FOR JAVASCRIPT DEVELOPERS github py2rs rust for node developers rust for c developers / \"I used to use pointers - now what?\" rust for clojurists Intro Rust Docs \"The Book (Second Edition)\" aka \"The Rust Programming Language\" Self Contained Rust Examples Community Maintained Git Repo of Rust Resources Rust Performance Pitfalls Detailed The Rust Reference Rust Grammar Standard Library API Reference Rust API Guidelines Rust API Guidelines Quick Checklist Advanced: How to write unsafe Rust code aka \"The Rustonomicon\" Unstable Book Rust release notes Rust platform support Rust Compiler Error Index Segfaults in Rust Profiling Rust Applications on Linux Writing an OS in rust Pretty state machine patterns in rust Rust Community Find a meetup on meetup.com in your area goog.gl/EJ2iRb rust conf - west coast? #rust-community on IRC k Cool Projects Redox OS - unix-like operating system Popular Crate on crates.io - find cool stuff to work on Embedded Need llvm , there is an avr llvm project Does esp32 have access to llvm yet? llvm now supports arm64 which is good for the future... This is fall 2018, 18 months later... does this work yet? check","title":"Rust Plan"},{"location":"docs/references/rust_plan/#a-plan-to-learn-rust","text":"I was planning on learning C but it's tough to get up to speed and people seem to have wildly varying practices. It would be better to learn low level things in a modern context with less baggage.","title":"A Plan to Learn Rust"},{"location":"docs/references/rust_plan/#the-plan","text":"","title":"The Plan"},{"location":"docs/references/rust_plan/#todo","text":"Go through the book (2nd edition) and check out the community maintained git repo. Skip the git project of examples for now, I've checked them out before and should learn the rust book before checking them out again. How do I get a .gitignore to be generated when I do cargo new --bin variables or similar? What's the deal with shadowing? Sure it's fine, but you could end up with a bunch of values that never get garbage collected, what other tradeoffs are there? Perhaps the same type management issues that Python is attempting to solve with type annotation. Why use shadowing?","title":"Todo"},{"location":"docs/references/rust_plan/#done","text":"Learn about rustup and how to maintain your rust toolchain. Hopefully build an analogy to python-virtualenv .","title":"Done"},{"location":"docs/references/rust_plan/#ingesting-anthologies-and-aggregators-of-rust-information","text":"","title":"Ingesting Anthologies and Aggregators of Rust Information"},{"location":"docs/references/rust_plan/#more-resource-compilations-to-ingest","text":"Rust Anthology readrust.net interesting post aggregator rust community blog project euler in rust hackr.io tutorials learn-rust tutorials and courses rust design patterns","title":"More Resource Compilations to Ingest"},{"location":"docs/references/rust_plan/#already-ingested-here-date","text":"rust-learning - 2018.08.13","title":"Already Ingested Here & Date"},{"location":"docs/references/rust_plan/#tools","text":"Tools for Rust.","title":"Tools"},{"location":"docs/references/rust_plan/#places-to-get-help","text":"there are a number of places you can get help. The easiest is the #rust IRC channel on irc.mozilla.org, which you can access through Mibbit. At that address you can chat with other Rustaceans (a silly nickname we call ourselves) who can help you out. Other great resources include the Users forum and Stack Overflow.","title":"Places to get help"},{"location":"docs/references/rust_plan/#local-documentation","text":"try: rustup doc","title":"Local Documentation"},{"location":"docs/references/rust_plan/#rustup","text":"","title":"rustup"},{"location":"docs/references/rust_plan/#switch-between-stable-and-nightly","text":"you will need some or all of these: rustup update rustup install nightly switch with: rustup default nightly or rustup default stable rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated . It makes cross-compiling simpler with binary builds of the standard library for common platforms. And it runs on all platforms Rust supports, including Windows. (emphasis mine) rustup is a toolchain multiplexer. It installs and manages many Rust toolchains and presents them all through a single set of tools installed to ~/.cargo/bin. The rustc and cargo installed to ~/.cargo/bin are proxies that delegate to the real toolchain. rustup then provides mechanisms to easily change the active toolchain by reconfiguring the behavior of the proxies.","title":"Switch between stable and nightly"},{"location":"docs/references/rust_plan/#clippy","text":"Linter - nightly only. Use it!","title":"Clippy"},{"location":"docs/references/rust_plan/#playpen","text":"You can put your rust in a gist and put it in Playpen and then share it with others who can see it run. Good tool for collaboration.","title":"Playpen"},{"location":"docs/references/rust_plan/#crater","text":"I don't think this is useful until I'm trying to switch between stable and nightly with tons of dependencies. detect regressions in rust compiler against a bunch of crates github project Check the differences between stable and target only for sandboxed environments, it's very destructive... so I guess only on vms.","title":"Crater"},{"location":"docs/references/rust_plan/#cargo","text":"howto: specify cargo dependencies This is manual... but I prefer cargo-edit so far for add/rm/upgrade Make sure to cargo install cargo-edit This gives you the ability to use cargo add/rm/upgrade for example cargo add num_bigint Rust cargo guide Cargo is a tool that allows Rust projects to declare their various dependencies and ensure that you\u2019ll always get a repeatable build. To accomplish this goal, Cargo does four things: Introduces two metadata files with various bits of project information. Fetches and builds your project\u2019s dependencies. Invokes rustc or another build tool with the correct parameters to build your project. Introduces conventions to make working with Rust projects easier.","title":"Cargo"},{"location":"docs/references/rust_plan/#gdb","text":"GDB supports Rust Lizzie says no one uses it","title":"GDB"},{"location":"docs/references/rust_plan/#the-book-2nd-ed-aka-the-rust-programming-language","text":"When you finish this you will be an intermediate rust programmer. In general, this book assumes that you\u2019re reading it in sequence from front to back. Later chapters build on concepts in earlier chapters, and earlier chapters might not delve into details on a topic; we typically revisit the topic in a later chapter. You\u2019ll find two kinds of chapters in this book: concept chapters and project chapters. In concept chapters, you\u2019ll learn about an aspect of Rust. In project chapters, we\u2019ll build small programs together, applying what you\u2019ve learned so far. Chapters 2, 12, and 20 are project chapters; the rest are concept chapters.","title":"\"The Book 2nd Ed.\" aka \"The Rust Programming Language\""},{"location":"docs/references/rust_plan/#rust-101-youtube-20-jan-2017","text":"Speaker: E. Dunham; @qedunham (Mozilla) source slides","title":"Rust 101 Youtube (20 Jan 2017)"},{"location":"docs/references/rust_plan/#exercises","text":"Rustlings repo Rust By Example book","title":"Exercises"},{"location":"docs/references/rust_plan/#macros","text":"Macros are syntactic sugar for functions that take a variable number of arguments... Need more content, see rust book v2.","title":"Macros"},{"location":"docs/references/rust_plan/#inclusive-and-exclusive-ranges","text":".. is an exclusive range, ..= is an inclusive range This is true for both matches and expressions The old match-only inclusive range syntax ... is still acceptable in match-only but not recommended and does not work in expressions See rust book v2 appendix 6","title":"Inclusive and Exclusive Ranges"},{"location":"docs/references/rust_plan/#notes","text":"Rust is an expression based language Statements are instructions that perform some action and do not return a value. let y = 6; is a statement, it does not return a value Expressions evaluate to a resulting value. Expressions can be parts of statements: in let y = 6 , the 6 is an expression that evaluates to 6 . calling a function or calling a macro is an expression calling the block to create new scopes, {} , is an expression a function can have an expression and it will be returned by the function other languages don't have the same distinctions blocks of code inside if expressions or match expressions are sometimes called arms Remember that blocks of code evaluate to the last expression in them","title":"Notes"},{"location":"docs/references/rust_plan/#chapter-2","text":"Switching from an expect call to a match expression is how you generally move from crashing on an error to handling the error. Remember that parse returns a Result type and Result is an enum that has the variants Ok or Err . We\u2019re using a match expression here, as we did with the Ordering result of the cmp method. --- snip --- If parse is not able to turn the string into a number, it will return an Err value that contains more information about the error. The Err value does not match the Ok(num) pattern in the first match arm, but it does match the Err(_) pattern in the second arm. The underscore, _ , is a catchall value; in this example, we\u2019re saying we want to match all Err values, no matter what information they have inside them. So the program will execute the second arm\u2019s code, continue , which tells the program to go to the next iteration of the loop and ask for another guess. So effectively, the program ignores all errors that parse might encounter!","title":"Chapter 2"},{"location":"docs/references/rust_plan/#chapter-3","text":"Function bodies are made up of a series of statements optionally ending in an expression. So far, we\u2019ve only covered functions without an ending expression, but you have seen an expression as part of a statement. Because Rust is an expression-based language, this is an important distinction to understand. Other languages don\u2019t have the same distinctions, so let\u2019s look at what statements and expressions are and how their differences affect the bodies of functions. We\u2019ve actually already used statements and expressions. Statements are instructions that perform some action and do not return a value. Expressions evaluate to a resulting value. Let\u2019s look at some examples. So how do you know which type of integer to use? If you\u2019re unsure, Rust\u2019s defaults are generally good choices, and integer types default to i32: this type is generally the fastest, even on 64-bit systems. The primary situation in which you\u2019d use isize or usize is when indexing some sort of collection. Floating-point numbers are represented according to the IEEE-754 standard. The f32 type is a single-precision float, and f64 has double precision. Rust\u2019s char type represents a Unicode Scalar Value, which means it can represent a lot more than just ASCII. Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char values in Rust. Unicode Scalar Values range from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive. However, a \u201ccharacter\u201d isn\u2019t really a concept in Unicode, so your human intuition for what a \u201ccharacter\u201d is may not match up with what a char is in Rust. We\u2019ll discuss this topic in detail in \u201cStrings\u201d in Chapter 8.","title":"Chapter 3"},{"location":"docs/references/rust_plan/#chapter-4-understanding-ownership-ownership-references-borrowing-slices","text":"Lifetimes are not covered in this chapter, see chapter 10. I think this most related to borrowing with async, which sounds like a hairball.","title":"Chapter 4: Understanding Ownership (ownership, references, borrowing, slices)"},{"location":"docs/references/rust_plan/#chapter-5-using-structs-to-structure-related-data","text":"Structs and enums (discussed in Chapter 6) are the building blocks for creating new types in your program\u2019s domain to take full advantage of Rust\u2019s compile time type checking. Use let to instantiate struct with kv pairs (not ordered). Use dot notation to get a value back from a struct. Entire struct instance must be mutable, not certain fields of struct instance. Mutability is on the instance not the struct definition","title":"Chapter 5: Using Structs to Structure Related Data"},{"location":"docs/references/rust_plan/#struct-instantiaton-example","text":"This valid expression is returned from the function and expressed in the function signature: fn build_user ( email : String , username : String ) -> User { User { email : email , username : username , active : true , sign_in_count : 1 , } }","title":"Struct Instantiaton Example"},{"location":"docs/references/rust_plan/#resources","text":"Resources from main rust site.","title":"Resources"},{"location":"docs/references/rust_plan/#are-we-_-yet","text":"web app stuff game stuff also check out \"things that are not awesome yet in rust \"","title":"\"Are we _ yet?\""},{"location":"docs/references/rust_plan/#articles","text":"Summaries go below. A list of 'fearless rust bloggers' Tutorials & Workshop Materials hackr.io tutorials","title":"Articles"},{"location":"docs/references/rust_plan/#rust-for-python-developers-by-armin-ronacher","text":"","title":"\"Rust for Python Developers\" by Armin Ronacher"},{"location":"docs/references/rust_plan/#mutability-borrows-and-owners","text":"Functions that operate on immutable borrows are marked as &self and functions that need a mutable borrow are marked as &mut self. You can only loan out references if you are the owner. If you want to move the value out of the function (for instance by returning it) you cannot have any outstanding loans and you cannot loan out values after having moved ownership away from yourself. This is a big change in how you think about programs but you will get used to it.","title":"Mutability, Borrows, and Owners"},{"location":"docs/references/rust_plan/#three-rust-things-armin-wishes-he-learned-earlier","text":"","title":"Three rust things Armin wishes he learned earlier"},{"location":"docs/references/rust_plan/#rusts-ownership-model-for-javascript-developers","text":"","title":"RUST'S OWNERSHIP MODEL FOR JAVASCRIPT DEVELOPERS"},{"location":"docs/references/rust_plan/#github-py2rs","text":"","title":"github py2rs"},{"location":"docs/references/rust_plan/#rust-for-node-developers","text":"","title":"rust for node developers"},{"location":"docs/references/rust_plan/#rust-for-c-developers-i-used-to-use-pointers-now-what","text":"","title":"rust for c developers / \"I used to use pointers - now what?\""},{"location":"docs/references/rust_plan/#rust-for-clojurists","text":"","title":"rust for clojurists"},{"location":"docs/references/rust_plan/#intro","text":"Rust Docs \"The Book (Second Edition)\" aka \"The Rust Programming Language\" Self Contained Rust Examples Community Maintained Git Repo of Rust Resources Rust Performance Pitfalls","title":"Intro"},{"location":"docs/references/rust_plan/#detailed","text":"The Rust Reference Rust Grammar Standard Library API Reference Rust API Guidelines Rust API Guidelines Quick Checklist Advanced: How to write unsafe Rust code aka \"The Rustonomicon\" Unstable Book Rust release notes Rust platform support Rust Compiler Error Index Segfaults in Rust Profiling Rust Applications on Linux Writing an OS in rust Pretty state machine patterns in rust","title":"Detailed"},{"location":"docs/references/rust_plan/#rust-community","text":"Find a meetup on meetup.com in your area goog.gl/EJ2iRb rust conf - west coast? #rust-community on IRC k","title":"Rust Community"},{"location":"docs/references/rust_plan/#cool-projects","text":"Redox OS - unix-like operating system Popular Crate on crates.io - find cool stuff to work on","title":"Cool Projects"},{"location":"docs/references/rust_plan/#embedded","text":"Need llvm , there is an avr llvm project Does esp32 have access to llvm yet? llvm now supports arm64 which is good for the future... This is fall 2018, 18 months later... does this work yet? check","title":"Embedded"},{"location":"docs/references/scansf/","text":"Police Scanner Reference Purpose Gain some fluency with police radio codes and common abbreviations or slang. Workflow When possible, if you hear a new code, toss it on the \"Heard at least once\" list. As a call becomes common, transfer it to the relevant list. Scan and Scan Code Sources ScanSF Online Scanners ScanSF SFPD Radio Codes SFPD Scan Code Flash Cards More scan codes based on Santa Barbara and others Another site - seems to have MISS (mississipi?) codes Scan San Diego Codes Common Radio Codes Unknown \"273.5 was observed.\" \"I'll get my own\" or \"We'll get our own\" - Maybe case number. Common for traffic stop (585). \"if you want to break each other one at a time apparently they are serving again up here.\" 908 - Muni bus inspection program (quizlet) Could be related to indecent exposure. Maybe related to suspicious person? 10-04E - aka 'ten four edward' one four edward for a 415 on 19th avenue - 14e ? '13 edward' - maybe 13e - no code for that I think it might be the station, e.g. 'charlie 15 edward to 13 edward' 10-13 is 'advise conditions at scene' 'david one six edward' - maybe d-16e note: 10-16 is pick up prisoner 'david twelve edward, can you put us on this run, we are 98' 'henry eleven edward' we have that car that was on mission '115' on the close 5 of that i will give result to the '110' - 'three ida one ten' 'charlie 12 edwards can you copy a plate' What is a \"one five edward\"? \"ida one five edward\" Serious Code 3 - Emergency/lights and siren \"I'm going to be code 3 to this run.\" Code 33 - Mobile Emergency - Clear this radio channel 10-30 - Person/Vehicle wanted/stolen (ex: I don't know if that is 10-30 or not) 152 - Drunk Driver 211 - Robbery (holdup) 212 - Strongarm 216 - Shots fired 217 - Shooting 221 - Person with gun 240 - Assault 418 - Fight or dispute, no weapons 918 - Person screaming for help 602 - Breaking and entering 914 - Person down (ex. I have a 914 bleeding but stable) Heard at least once 10-07I - Out of service (investigation) 10-09 - Repeat last transmission 10-10A - Off duty, at home 10-26 - Clear (example: \"still waiting on the 10-26\") 10-28 - vehicle registration info (ex. \"The 10-28 is going to be (car plate letters) etc...\" 10-29 or 29 - Check for warrants (ex. \"can you run a 29 for me) 10-49 - Proceed to ______ Code 1 - Do so at your convenience 207 - Kidnapping 311 - indecent exposure 407 - Prisoner transport 459 - Robbery (suspect tried to break the window then ran off) 488 - petty theft 496 - Stolen property receiving (example: phone) 518 - Vehicle accident no injury 519 - Vehicle accident with injury 520 - Accident (non-vehicle) (example: like going off the road) 529 - Explosion 588 - Driveway violation - tow 594 - Malicious Mischief (vandalism) 601 - Trespassers 800 - Mentally-disturbed person 802 - Coroner's Case (unexpected or possibility of a law being broken) 851 - Stolen vehicle 852 - Auto boost/strip (heard a 852 misreported as a 459) 809 - Missing Person 904 - Meet with officer non-emergency (example: marin county warrant search) 905 - Meet with city or public service employee (fire dept etc) 910 - Check on well-being 913 - Complaint Unknown 914 - Person down Very Frequent 10-01 - Reception is poor 10-08 - In service, ready for assignment 10-22 or 22 - Disregard that last assignment (example: \"22 all that\") 408 - Send ambulance (example: they are sending a 408) 410 - Requested assistance responding (ex: 'request 408' 'confirm you have a 410') 415 - Noise complaint 585 - Traffic stop 587 - Parking violation 811 - Intoxicated person (question: is this ever used for a person in vehicle? 152?) 901 - Call ______ (example: \"can you 901 my cell\", \"give me a 901 please\") 909 - Citizen requests interviews 915 - Homeless (call for service) - slang refers to people chronically city-camping 916 - Suspicious person in vehicle 917 - Suspicious person 10-32 or 32 - Person/vehicle clear - '32 all around' 10-98 or 98 - Available for assignment 11-98 or 98 - Meet: ______ (possible example: I am 98 to you? are you still at X?) Every Transmission 10-20 or 20 - Location (example: Your 20?) 10-04 - Copy/Ok Code 4 - No further assistance needed 10-97 or 97 or nine seven - Arrived at scene, or at the scene (ex. \"Are you still 97 on mission?\") Slang 302 - protesters, protest, also called a 'demo' CAD - Computer Aided Dispatch (ex: \"Can you put another plate in CAD for me?\") Operator on scansf used 470/fraud code to portray repeat suicide threat offender \"do you think he is really 801 or is he 470?\" X - female (from scansf sfpd radio codes, typically \"X yelling for help\" 418 - any dispute people are having? mostly verbal disputes fistfights someone disputes someone elses behavior? (complaint about burnouts?) LoJack - stolen vehicle recovery system This is a system that consumers install on their vehicle and which can be used by police for recovering a vehicle if stolen G.O.A - gone on arrival (example: person of interest was G.O.A.) A.M.F. - probably very intoxicated and unable to move: 'adios mother f---er' R.P. - relevant person (usually not a suspect) R.O. - registered owner (usually of a stolen vehicle) O.M. - oriental male B.M. - black male white male - white male L.M. - latin male - also apparently are LMAs (ex. five LMAs in a red honda) the city - slang for san francisco in registration data (address etc.) merit - a crime, something concrete to report shots fired - shots fired (observed directly by officer?) In the aves (sunset), officers use the letter of the alphabet to describe location. 40th and K = 40th and Kirkham (etc.) Hot Sheet - A list of stolen property and crimes under investigation compiled and held by the police. The use of 'hot' means known or wanted by the police; suspect. Source: Quora blue on blue - there are men with guns, we do not know if there are uniformed officers or not (undercover). Please be aware of any blue on blue (don't shoot the other cops!) \"broken down\" - telling people camping on the street they need to move their camp elsewhere. suspect information followed by 'verbal' or 'documented' - whether they said it or showed their ID. lower great highway from sloat to taraval is utl - unable to locate (suspect) \"so far the fire is utl.\" Police ID Format (Speculative) L##L - Letter:Number:Number:Letter Case Number Format Info Case 017 000 239 at 129 am new years day SFPD Preferred Phoenetic Alphabet Adam Boy Charlie David Edward Frank George Henry Ida John King Lincoln Mary, Medic? Norah Ocean Paul Queen Robert, Red Sam Tom, Tim Union Victor William Xray Yellow Zebra","title":"Scansf"},{"location":"docs/references/scansf/#police-scanner-reference","text":"","title":"Police Scanner Reference"},{"location":"docs/references/scansf/#purpose","text":"Gain some fluency with police radio codes and common abbreviations or slang.","title":"Purpose"},{"location":"docs/references/scansf/#workflow","text":"When possible, if you hear a new code, toss it on the \"Heard at least once\" list. As a call becomes common, transfer it to the relevant list.","title":"Workflow"},{"location":"docs/references/scansf/#scan-and-scan-code-sources","text":"ScanSF Online Scanners ScanSF SFPD Radio Codes SFPD Scan Code Flash Cards More scan codes based on Santa Barbara and others Another site - seems to have MISS (mississipi?) codes Scan San Diego Codes","title":"Scan and Scan Code Sources"},{"location":"docs/references/scansf/#common-radio-codes","text":"Unknown \"273.5 was observed.\" \"I'll get my own\" or \"We'll get our own\" - Maybe case number. Common for traffic stop (585). \"if you want to break each other one at a time apparently they are serving again up here.\" 908 - Muni bus inspection program (quizlet) Could be related to indecent exposure. Maybe related to suspicious person? 10-04E - aka 'ten four edward' one four edward for a 415 on 19th avenue - 14e ? '13 edward' - maybe 13e - no code for that I think it might be the station, e.g. 'charlie 15 edward to 13 edward' 10-13 is 'advise conditions at scene' 'david one six edward' - maybe d-16e note: 10-16 is pick up prisoner 'david twelve edward, can you put us on this run, we are 98' 'henry eleven edward' we have that car that was on mission '115' on the close 5 of that i will give result to the '110' - 'three ida one ten' 'charlie 12 edwards can you copy a plate' What is a \"one five edward\"? \"ida one five edward\" Serious Code 3 - Emergency/lights and siren \"I'm going to be code 3 to this run.\" Code 33 - Mobile Emergency - Clear this radio channel 10-30 - Person/Vehicle wanted/stolen (ex: I don't know if that is 10-30 or not) 152 - Drunk Driver 211 - Robbery (holdup) 212 - Strongarm 216 - Shots fired 217 - Shooting 221 - Person with gun 240 - Assault 418 - Fight or dispute, no weapons 918 - Person screaming for help 602 - Breaking and entering 914 - Person down (ex. I have a 914 bleeding but stable) Heard at least once 10-07I - Out of service (investigation) 10-09 - Repeat last transmission 10-10A - Off duty, at home 10-26 - Clear (example: \"still waiting on the 10-26\") 10-28 - vehicle registration info (ex. \"The 10-28 is going to be (car plate letters) etc...\" 10-29 or 29 - Check for warrants (ex. \"can you run a 29 for me) 10-49 - Proceed to ______ Code 1 - Do so at your convenience 207 - Kidnapping 311 - indecent exposure 407 - Prisoner transport 459 - Robbery (suspect tried to break the window then ran off) 488 - petty theft 496 - Stolen property receiving (example: phone) 518 - Vehicle accident no injury 519 - Vehicle accident with injury 520 - Accident (non-vehicle) (example: like going off the road) 529 - Explosion 588 - Driveway violation - tow 594 - Malicious Mischief (vandalism) 601 - Trespassers 800 - Mentally-disturbed person 802 - Coroner's Case (unexpected or possibility of a law being broken) 851 - Stolen vehicle 852 - Auto boost/strip (heard a 852 misreported as a 459) 809 - Missing Person 904 - Meet with officer non-emergency (example: marin county warrant search) 905 - Meet with city or public service employee (fire dept etc) 910 - Check on well-being 913 - Complaint Unknown 914 - Person down Very Frequent 10-01 - Reception is poor 10-08 - In service, ready for assignment 10-22 or 22 - Disregard that last assignment (example: \"22 all that\") 408 - Send ambulance (example: they are sending a 408) 410 - Requested assistance responding (ex: 'request 408' 'confirm you have a 410') 415 - Noise complaint 585 - Traffic stop 587 - Parking violation 811 - Intoxicated person (question: is this ever used for a person in vehicle? 152?) 901 - Call ______ (example: \"can you 901 my cell\", \"give me a 901 please\") 909 - Citizen requests interviews 915 - Homeless (call for service) - slang refers to people chronically city-camping 916 - Suspicious person in vehicle 917 - Suspicious person 10-32 or 32 - Person/vehicle clear - '32 all around' 10-98 or 98 - Available for assignment 11-98 or 98 - Meet: ______ (possible example: I am 98 to you? are you still at X?) Every Transmission 10-20 or 20 - Location (example: Your 20?) 10-04 - Copy/Ok Code 4 - No further assistance needed 10-97 or 97 or nine seven - Arrived at scene, or at the scene (ex. \"Are you still 97 on mission?\") Slang 302 - protesters, protest, also called a 'demo' CAD - Computer Aided Dispatch (ex: \"Can you put another plate in CAD for me?\") Operator on scansf used 470/fraud code to portray repeat suicide threat offender \"do you think he is really 801 or is he 470?\" X - female (from scansf sfpd radio codes, typically \"X yelling for help\" 418 - any dispute people are having? mostly verbal disputes fistfights someone disputes someone elses behavior? (complaint about burnouts?) LoJack - stolen vehicle recovery system This is a system that consumers install on their vehicle and which can be used by police for recovering a vehicle if stolen G.O.A - gone on arrival (example: person of interest was G.O.A.) A.M.F. - probably very intoxicated and unable to move: 'adios mother f---er' R.P. - relevant person (usually not a suspect) R.O. - registered owner (usually of a stolen vehicle) O.M. - oriental male B.M. - black male white male - white male L.M. - latin male - also apparently are LMAs (ex. five LMAs in a red honda) the city - slang for san francisco in registration data (address etc.) merit - a crime, something concrete to report shots fired - shots fired (observed directly by officer?) In the aves (sunset), officers use the letter of the alphabet to describe location. 40th and K = 40th and Kirkham (etc.) Hot Sheet - A list of stolen property and crimes under investigation compiled and held by the police. The use of 'hot' means known or wanted by the police; suspect. Source: Quora blue on blue - there are men with guns, we do not know if there are uniformed officers or not (undercover). Please be aware of any blue on blue (don't shoot the other cops!) \"broken down\" - telling people camping on the street they need to move their camp elsewhere. suspect information followed by 'verbal' or 'documented' - whether they said it or showed their ID. lower great highway from sloat to taraval is utl - unable to locate (suspect) \"so far the fire is utl.\" Police ID Format (Speculative) L##L - Letter:Number:Number:Letter Case Number Format Info Case 017 000 239 at 129 am new years day SFPD Preferred Phoenetic Alphabet Adam Boy Charlie David Edward Frank George Henry Ida John King Lincoln Mary, Medic? Norah Ocean Paul Queen Robert, Red Sam Tom, Tim Union Victor William Xray Yellow Zebra","title":"Common Radio Codes"},{"location":"docs/references/security_resources/","text":"A Resource List for Security Mailing Lists lists.openwall.net","title":"Security Resources"},{"location":"docs/references/security_resources/#a-resource-list-for-security","text":"","title":"A Resource List for Security"},{"location":"docs/references/security_resources/#mailing-lists","text":"lists.openwall.net","title":"Mailing Lists"},{"location":"docs/references/skyrim_creation_kit/","text":"Skyrim Creation Kit Information Questions Is it better to use the creation kit from the Bethesda Launcher or the Steam Library Toolkit? Creation Engine Data Format Master Files - .esm files; large collections of data. Plugins - .esp files; small collections of data loaded on top of Master Files. May modify or reference data in a master file, or add new data. In the game, multiple Plugins may be loaded. In the Creation Kit, only one plugin may be considered the 'active file', meaning any changes will be saved to that plugin when the user saves. First Plugin Use the skyrim.esm and Update.esm files as your plugin's master files. Load them with the menu: File>Data. Ignore any warnings, they are supposed to happen... Create your plugin in the menu: File>Save. Since you have no active plugin, you will be prompted to create a new .esp file. NOTE: There is no \"save as\" feature. All saves will overwrite the current plugin. Versioning must be done outside the program. Your saved plugins are found directly in your Skyrim\\Data\\ folder. Load Plugins in Special Edition: In the main game menu choose Mods>Load Order and activate your local plugins. Demo Console Commands : `TGM` - Toggle God Mode `TWF` - ToggleWireframe `COC RiverwoodSleepingGiantInn` - teleport to Riverwood inn Save games made with mods or console commands might be broken !! Make sure any saves you care about are backed up before testing and don 't save over them. Papyrus Scripting Info for Experienced Programmers Papyrus Primer [Papyrus Events & Properties (goog cache)] (https://webcache.googleusercontent.com/search?q=cache:eXVPDMVDaTsJ:https://www.creationkit.com/index.php%3Ftitle%3DBethesda_Tutorial_Papyrus_Events_and_Properties+&cd=1&hl=en&ct=clnk&gl=us) Level Design Series Papyrus Programming References Literals Reference Operator Reference Statement Reference Variable Reference (cache) Variables and Properties Creation Kit Wiki References Creation Kit Wiki Main Page Getting Started (creation kit tour) Creation Kit Wiki Content Statistics Papyrus \"Hello World\" Script I did this and it worked. Simple intro to check that your toolchain works. Creation Kit Wiki Categories Category:Tutorials Category:Game_Systems Category:Editor_Reference Category:Getting_Started Category:Keyboard_Mapping Category:Papyrus Category:Designer_Debug_Tools Additional Resources Skyrim Special Edition Creation Kit Fine-Tuning Converting Standard mods to SE Community Resources https://www.reddit.com/r/skyrimmods/wiki/guides_and_resources http://forums.bethsoft.com/forum/117-v-skyrim-skyrim-special-edition/ http://forums.bethsoft.com/forum/184-the-creation-kit/","title":"Skyrim Creation Kit"},{"location":"docs/references/skyrim_creation_kit/#skyrim-creation-kit-information","text":"","title":"Skyrim Creation Kit Information"},{"location":"docs/references/skyrim_creation_kit/#questions","text":"Is it better to use the creation kit from the Bethesda Launcher or the Steam Library Toolkit?","title":"Questions"},{"location":"docs/references/skyrim_creation_kit/#creation-engine-data-format","text":"Master Files - .esm files; large collections of data. Plugins - .esp files; small collections of data loaded on top of Master Files. May modify or reference data in a master file, or add new data. In the game, multiple Plugins may be loaded. In the Creation Kit, only one plugin may be considered the 'active file', meaning any changes will be saved to that plugin when the user saves.","title":"Creation Engine Data Format"},{"location":"docs/references/skyrim_creation_kit/#first-plugin","text":"Use the skyrim.esm and Update.esm files as your plugin's master files. Load them with the menu: File>Data. Ignore any warnings, they are supposed to happen... Create your plugin in the menu: File>Save. Since you have no active plugin, you will be prompted to create a new .esp file. NOTE: There is no \"save as\" feature. All saves will overwrite the current plugin. Versioning must be done outside the program. Your saved plugins are found directly in your Skyrim\\Data\\ folder. Load Plugins in Special Edition: In the main game menu choose Mods>Load Order and activate your local plugins. Demo Console Commands : `TGM` - Toggle God Mode `TWF` - ToggleWireframe `COC RiverwoodSleepingGiantInn` - teleport to Riverwood inn Save games made with mods or console commands might be broken !! Make sure any saves you care about are backed up before testing and don 't save over them.","title":"First Plugin"},{"location":"docs/references/skyrim_creation_kit/#papyrus-scripting-info-for-experienced-programmers","text":"Papyrus Primer [Papyrus Events & Properties (goog cache)] (https://webcache.googleusercontent.com/search?q=cache:eXVPDMVDaTsJ:https://www.creationkit.com/index.php%3Ftitle%3DBethesda_Tutorial_Papyrus_Events_and_Properties+&cd=1&hl=en&ct=clnk&gl=us) Level Design Series","title":"Papyrus Scripting Info for Experienced Programmers"},{"location":"docs/references/skyrim_creation_kit/#papyrus-programming-references","text":"Literals Reference Operator Reference Statement Reference Variable Reference (cache) Variables and Properties","title":"Papyrus Programming References"},{"location":"docs/references/skyrim_creation_kit/#creation-kit-wiki-references","text":"Creation Kit Wiki Main Page Getting Started (creation kit tour) Creation Kit Wiki Content Statistics Papyrus \"Hello World\" Script I did this and it worked. Simple intro to check that your toolchain works.","title":"Creation Kit Wiki References"},{"location":"docs/references/skyrim_creation_kit/#creation-kit-wiki-categories","text":"Category:Tutorials Category:Game_Systems Category:Editor_Reference Category:Getting_Started Category:Keyboard_Mapping Category:Papyrus Category:Designer_Debug_Tools","title":"Creation Kit Wiki Categories"},{"location":"docs/references/skyrim_creation_kit/#additional-resources","text":"Skyrim Special Edition Creation Kit Fine-Tuning Converting Standard mods to SE","title":"Additional Resources"},{"location":"docs/references/skyrim_creation_kit/#community-resources","text":"https://www.reddit.com/r/skyrimmods/wiki/guides_and_resources http://forums.bethsoft.com/forum/117-v-skyrim-skyrim-special-edition/ http://forums.bethsoft.com/forum/184-the-creation-kit/","title":"Community Resources"},{"location":"docs/references/slic3r/","text":"Some tips for using Slic3r Issues rendering a preview I had problems rendering a preview. As I brought the slider up from 0% rendered to 100% (top of model) rendered, the computer was running out of memory. There is a guide that has helpful information Things I did (did not help render preview without crashing): Set resolution to 0.01mm (default is 0mm). Set threads to 1 may not have mattered Things I am doing (TBD): 3. Opened each file in meshlab, allowed it to delete duplicate vertices, and saved the file again. - In the original pass I did simplify mesh according to this howto - See if the simplify mesh actually matters... removing duplicate vertices may have been enough Information: In top , CPU seemed to be the bottleneck. Memory was not observed to increase as the model rendering slowed (between 35% to 45%)","title":"Slic3R"},{"location":"docs/references/slic3r/#some-tips-for-using-slic3r","text":"","title":"Some tips for using Slic3r"},{"location":"docs/references/slic3r/#issues-rendering-a-preview","text":"I had problems rendering a preview. As I brought the slider up from 0% rendered to 100% (top of model) rendered, the computer was running out of memory. There is a guide that has helpful information Things I did (did not help render preview without crashing): Set resolution to 0.01mm (default is 0mm). Set threads to 1 may not have mattered Things I am doing (TBD): 3. Opened each file in meshlab, allowed it to delete duplicate vertices, and saved the file again. - In the original pass I did simplify mesh according to this howto - See if the simplify mesh actually matters... removing duplicate vertices may have been enough Information: In top , CPU seemed to be the bottleneck. Memory was not observed to increase as the model rendering slowed (between 35% to 45%)","title":"Issues rendering a preview"},{"location":"docs/references/spacemacs/","text":"Spacemacs Reference Document A general reference for getting into spacemacs from vim. Mostly derivative of other guides. Table of Contents This does not have all sections listed, just main sections and popular reference areas. Reference Notes Spacemacs State Color Codes Spacemacs Fixes Greg's elisp notes Why I switched Reference Useful Sequences See all active minor-modes and major mode : C-h m another get major-mode: C-h v major-mode another get minor-mode: C-h v minor-mode-list spacemacs minor-mode stuff Reload stuff/settings: SPC f e R Load up non-GUI mode: $ emacs -nw Insert any character: C-q Increment by q (q=1 by default): q SPC n - has some sort of minor mode where you can keep pressing stuff, try it Clear search highlighting: SPC s c Navigate buffers: SPC b b Check out the Messages buffer kill buffer: SPC b d next or prev buffer: SPC b n or SPC b p Jump between matched tags: % Exit insert mode (evil-escape): fd note that this should take you to evil normal mode from anywhere this may work identically to C-g Find a file and open in a new buffer: SPC f f \"help describe\": SPC h d \"help describe function\" SPC h d f \"help describe key\" SPC h d k guide-key , a menu of stuff: SPC Insert lorem ipsum: SPC i l l (lorem-ipsum) has several nice insert options SPC i l Note that the vim . repeater works on SPC -leader macros.. try SPC i l l . . . . . Using evil-nerd-commenter comment or uncomment a block of lines SPC c l toggle comment on each line in a block of lines SPC c ; can be used to simultaneously uncomment and comment neighboring lines SPC m is aliased to , and accesses the current major-mode menu Interesting Sequences Incremental Search: C-s stuff Note: / style search is already incremental in spacemacs. Learn emacs lisp: SPC h i elisp RET Future Mess with iedit and iedit-insert states Try out the other SPC s search options Test out spacemacs regex SPC x which uses pcre2el package further reference editing lisp code & lisp keybindings managing projects compiling code External References Spacemacs documentation Migrating from Vim Remapping keys guide-key learn elisp in 15 minutes GNU emacs manual Configuration \"Tutorial\" Orientation for contributing layers Chaotic Migration Guide Subreddits: /r/emacs/ /r/spacemacs/ /r/evilmode/ /r/orgmode/ Notes (From References) Each note should have a #### header and be included in the TOC. What is setq ? Set Quoted. (set (quote scroll-margin) 5) is equivalent to (setq scroll-margin 5) . Spacemacs State Color Codes There are 10 states . The state table is from the Spacemacs documentation . State Default Color Description normal orange like the =normal mode of Vim=, used to execute and combine commands insert green like the =insert mode of Vim=, used to actually insert text visual gray like the =visual mode of Vim=, used to make text selection motion purple exclusive to =Evil=, used to navigate read only buffers emacs blue exclusive to =Evil=, using this state is like using a regular Emacs without Vim replace chocolate exclusive to =Evil=, overwrites the character under point instead of inserting a new one hybrid blue exclusive to Spacemacs, this is like the insert state except that all the emacs key bindings are available evilified light brown exclusive to Spacemacs, this is an =emacs state= modified to bring Vim navigation, selection and search. lisp pink exclusive to Spacemacs, used to navigate Lisp code and modify it (more [[#editing-lisp-code][info]]) iedit red exclusive to Spacemacs, used to navigate between multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]]) iedit-insert red exclusive to Spacemacs, used to replace multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]]) Spacemacs Fixes Things I think need fixed. Identified as needs fixed for spacemacs Make default colors the same as default terminal colors... not sure how to let these pass through, spacemacs has magic colors Consider moving my hotkeys to a helm menu or something, with a space leader instead of C- pattern. Also includes vim functions. Rewrite vim functions for spacemacs Consider alias for bash for spacemacs nongui as default emacs -nw Also, consider installing the emacs-plus package from homebrew cask on mac The emacs-plus package is apparently the recommended package by spacemacs, no idea why Store undo history between sessions for all edited files. manage branching undo history better? may just need training... C-c should exit insert mode Fix ridiculous html indentation Disable the mouse... try the (disable-mouse) package? Needs Deeper Research tabs->spaces looks like highlight and <|> indent by 4 spaces in html extension files... not sure how it varies by file extension we want this to be 2 spaces by default and 4 spaces in the .py file extension indentation with the tab also does not always work, it seems to try to force a style from somewhere, tab does not always have an effect html specific tab seems to add spaces when it allows input... this should not follow complex rules, tab should just put 2 spaces in regardless in html when exiting insert mode, it seems to do some postprocessing on my editing, visual mode gets weird things in html mode are generally not working, especially with regards to and similar Esc (1/2 second pause or less) followed by a key is a meta-key leader... need it to be dead key from now on this is related: https://github.com/syl20bnr/spacemacs/issues/2756 this seems to have abated, i think i toggled a mode i do not know why it would have abated but i did restart my computer still reloading emacs settings should be enough, mysterious How do I drill down to my packages? How do I learn about my evil mode configuration and contribute to the evil mode emacs plugin? i have been reading the elisp in the .spacemacs.d layers How do I manage undo branches? Done line numbers on startup, line number toggle? note taken - How do i search for tabs, e.g. \\t scroll-margin set to 5 C-l should redraw the screen - redraw does not clear search highlighting in emacs... Clear a search with SPC s c Turn off auto add closing quotes, braces, brackets, tildes, etc. in init.el: put smartparens in dotspacemacs-excluded-packages Optional redraw screen with some key combo? - https://www.gnu.org/software/emacs/manual/html_node/elisp/Refresh-Screen.html May already be in spacemacs, check around Greg's elisp notes I'm starting by reading An Introduction to Programming in Emacs Lisp. To get to this, open emacs with no arguments, hit ctrl-h i . C-h is for help. i is for the info reader, which lets you browse manuals. Then you're presented with a long menu. Hit m for menu, then type Emacs Lisp Intro into the mini buffer. Then hit enter. That gets you to the elisp intro. Lisp stands for LISt Processing. A list: '(rose violet daisy buttercup) Awesome and beautiful quote from the book: \"The elements of this list are the names of the four different flowers, separated from each other by whitespace and surrounded by parentheses, like flowers in a field with a stone wall around them.\" Text between double quotation marks is also an atom. If there is no apostraphe before a preceding list then the first item of the list is a function. If there is an apostophe then the list is just taken as is. Why I switched to Spacemacs I wrote these out for someone. I prefer to see spacemacs as a vim featureset expansion. Vimscript sucks and vim isn't really great wrt extendability, extensions are all over the place. I like scheme/lisp and am writing a lot of C this year, emacs seems much better suited for working in both. Spacemacs provides most common keys in vim (but not all!). For example C-a in vim is SPC n + in spacemacs. It drops chording, a net positive. Vim promises leader keys but you effectively chord enough of your actions that it's a fake claim. Spacemacs uses a space leader for most things. Vim feels stagnant, even if it isn't. The core featureset of vim doesn't really need vim the application anymore","title":"Spacemacs"},{"location":"docs/references/spacemacs/#spacemacs-reference-document","text":"A general reference for getting into spacemacs from vim. Mostly derivative of other guides.","title":"Spacemacs Reference Document"},{"location":"docs/references/spacemacs/#table-of-contents","text":"This does not have all sections listed, just main sections and popular reference areas. Reference Notes Spacemacs State Color Codes Spacemacs Fixes Greg's elisp notes Why I switched","title":"Table of Contents"},{"location":"docs/references/spacemacs/#reference","text":"","title":"Reference"},{"location":"docs/references/spacemacs/#useful-sequences","text":"See all active minor-modes and major mode : C-h m another get major-mode: C-h v major-mode another get minor-mode: C-h v minor-mode-list spacemacs minor-mode stuff Reload stuff/settings: SPC f e R Load up non-GUI mode: $ emacs -nw Insert any character: C-q Increment by q (q=1 by default): q SPC n - has some sort of minor mode where you can keep pressing stuff, try it Clear search highlighting: SPC s c Navigate buffers: SPC b b Check out the Messages buffer kill buffer: SPC b d next or prev buffer: SPC b n or SPC b p Jump between matched tags: % Exit insert mode (evil-escape): fd note that this should take you to evil normal mode from anywhere this may work identically to C-g Find a file and open in a new buffer: SPC f f \"help describe\": SPC h d \"help describe function\" SPC h d f \"help describe key\" SPC h d k guide-key , a menu of stuff: SPC Insert lorem ipsum: SPC i l l (lorem-ipsum) has several nice insert options SPC i l Note that the vim . repeater works on SPC -leader macros.. try SPC i l l . . . . . Using evil-nerd-commenter comment or uncomment a block of lines SPC c l toggle comment on each line in a block of lines SPC c ; can be used to simultaneously uncomment and comment neighboring lines SPC m is aliased to , and accesses the current major-mode menu","title":"Useful Sequences"},{"location":"docs/references/spacemacs/#interesting-sequences","text":"Incremental Search: C-s stuff Note: / style search is already incremental in spacemacs. Learn emacs lisp: SPC h i elisp RET","title":"Interesting Sequences"},{"location":"docs/references/spacemacs/#future","text":"Mess with iedit and iedit-insert states Try out the other SPC s search options Test out spacemacs regex SPC x which uses pcre2el package further reference editing lisp code & lisp keybindings managing projects compiling code","title":"Future"},{"location":"docs/references/spacemacs/#external-references","text":"Spacemacs documentation Migrating from Vim Remapping keys guide-key learn elisp in 15 minutes GNU emacs manual Configuration \"Tutorial\" Orientation for contributing layers Chaotic Migration Guide","title":"External References"},{"location":"docs/references/spacemacs/#subreddits","text":"/r/emacs/ /r/spacemacs/ /r/evilmode/ /r/orgmode/","title":"Subreddits:"},{"location":"docs/references/spacemacs/#notes-from-references","text":"Each note should have a #### header and be included in the TOC.","title":"Notes (From References)"},{"location":"docs/references/spacemacs/#what-is-setq","text":"Set Quoted. (set (quote scroll-margin) 5) is equivalent to (setq scroll-margin 5) .","title":"What is setq?"},{"location":"docs/references/spacemacs/#spacemacs-state-color-codes","text":"There are 10 states . The state table is from the Spacemacs documentation . State Default Color Description normal orange like the =normal mode of Vim=, used to execute and combine commands insert green like the =insert mode of Vim=, used to actually insert text visual gray like the =visual mode of Vim=, used to make text selection motion purple exclusive to =Evil=, used to navigate read only buffers emacs blue exclusive to =Evil=, using this state is like using a regular Emacs without Vim replace chocolate exclusive to =Evil=, overwrites the character under point instead of inserting a new one hybrid blue exclusive to Spacemacs, this is like the insert state except that all the emacs key bindings are available evilified light brown exclusive to Spacemacs, this is an =emacs state= modified to bring Vim navigation, selection and search. lisp pink exclusive to Spacemacs, used to navigate Lisp code and modify it (more [[#editing-lisp-code][info]]) iedit red exclusive to Spacemacs, used to navigate between multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]]) iedit-insert red exclusive to Spacemacs, used to replace multiple regions of text using =iedit= (more [[#replacing-text-with-iedit][info]])","title":"Spacemacs State Color Codes"},{"location":"docs/references/spacemacs/#spacemacs-fixes","text":"Things I think need fixed.","title":"Spacemacs Fixes"},{"location":"docs/references/spacemacs/#identified-as-needs-fixed-for-spacemacs","text":"Make default colors the same as default terminal colors... not sure how to let these pass through, spacemacs has magic colors Consider moving my hotkeys to a helm menu or something, with a space leader instead of C- pattern. Also includes vim functions. Rewrite vim functions for spacemacs Consider alias for bash for spacemacs nongui as default emacs -nw Also, consider installing the emacs-plus package from homebrew cask on mac The emacs-plus package is apparently the recommended package by spacemacs, no idea why Store undo history between sessions for all edited files. manage branching undo history better? may just need training... C-c should exit insert mode Fix ridiculous html indentation Disable the mouse... try the (disable-mouse) package?","title":"Identified as needs fixed for spacemacs"},{"location":"docs/references/spacemacs/#needs-deeper-research","text":"tabs->spaces looks like highlight and <|> indent by 4 spaces in html extension files... not sure how it varies by file extension we want this to be 2 spaces by default and 4 spaces in the .py file extension indentation with the tab also does not always work, it seems to try to force a style from somewhere, tab does not always have an effect html specific tab seems to add spaces when it allows input... this should not follow complex rules, tab should just put 2 spaces in regardless in html when exiting insert mode, it seems to do some postprocessing on my editing, visual mode gets weird things in html mode are generally not working, especially with regards to and similar Esc (1/2 second pause or less) followed by a key is a meta-key leader... need it to be dead key from now on this is related: https://github.com/syl20bnr/spacemacs/issues/2756 this seems to have abated, i think i toggled a mode i do not know why it would have abated but i did restart my computer still reloading emacs settings should be enough, mysterious How do I drill down to my packages? How do I learn about my evil mode configuration and contribute to the evil mode emacs plugin? i have been reading the elisp in the .spacemacs.d layers How do I manage undo branches?","title":"Needs Deeper Research"},{"location":"docs/references/spacemacs/#done","text":"line numbers on startup, line number toggle? note taken - How do i search for tabs, e.g. \\t scroll-margin set to 5 C-l should redraw the screen - redraw does not clear search highlighting in emacs... Clear a search with SPC s c Turn off auto add closing quotes, braces, brackets, tildes, etc. in init.el: put smartparens in dotspacemacs-excluded-packages","title":"Done"},{"location":"docs/references/spacemacs/#optional","text":"redraw screen with some key combo? - https://www.gnu.org/software/emacs/manual/html_node/elisp/Refresh-Screen.html May already be in spacemacs, check around","title":"Optional"},{"location":"docs/references/spacemacs/#gregs-elisp-notes","text":"I'm starting by reading An Introduction to Programming in Emacs Lisp. To get to this, open emacs with no arguments, hit ctrl-h i . C-h is for help. i is for the info reader, which lets you browse manuals. Then you're presented with a long menu. Hit m for menu, then type Emacs Lisp Intro into the mini buffer. Then hit enter. That gets you to the elisp intro. Lisp stands for LISt Processing. A list: '(rose violet daisy buttercup) Awesome and beautiful quote from the book: \"The elements of this list are the names of the four different flowers, separated from each other by whitespace and surrounded by parentheses, like flowers in a field with a stone wall around them.\" Text between double quotation marks is also an atom. If there is no apostraphe before a preceding list then the first item of the list is a function. If there is an apostophe then the list is just taken as is.","title":"Greg's elisp notes"},{"location":"docs/references/spacemacs/#why-i-switched-to-spacemacs","text":"I wrote these out for someone. I prefer to see spacemacs as a vim featureset expansion. Vimscript sucks and vim isn't really great wrt extendability, extensions are all over the place. I like scheme/lisp and am writing a lot of C this year, emacs seems much better suited for working in both. Spacemacs provides most common keys in vim (but not all!). For example C-a in vim is SPC n + in spacemacs. It drops chording, a net positive. Vim promises leader keys but you effectively chord enough of your actions that it's a fake claim. Spacemacs uses a space leader for most things. Vim feels stagnant, even if it isn't. The core featureset of vim doesn't really need vim the application anymore","title":"Why I switched to Spacemacs"},{"location":"docs/references/spelunking_sqlite3/","text":"Spelunking - Reading the SQLite3 Source Tracking the fossil repository Fossil is a source control tool. About the source 3 ways to get the source Download current snapshot Download tarball of source+fossil history Cloning the complete development history References B-tree","title":"Spelunking Sqlite3"},{"location":"docs/references/spelunking_sqlite3/#spelunking-reading-the-sqlite3-source","text":"","title":"Spelunking - Reading the SQLite3 Source"},{"location":"docs/references/spelunking_sqlite3/#tracking-the-fossil-repository","text":"Fossil is a source control tool. About the source 3 ways to get the source Download current snapshot Download tarball of source+fossil history Cloning the complete development history","title":"Tracking the fossil repository"},{"location":"docs/references/spelunking_sqlite3/#references","text":"B-tree","title":"References"},{"location":"docs/references/stardart_spacedomination/","text":"Space Domination AKA Stardart One of my favorite games from the 90s. Space Domination: A modern release of stardart: http://www.spacedomination.org/index.php/play/ Build Ticks Build ticks are 10 seconds, measured with a stopwatch. Races It depends on if you need to maximize your acceleration into the game, your fleet power, your total build capacity, or your fleet retention. Raw score bonuses are the best long term, but fleet combat can make or break the game, heavily favoring Avarians. Human gets a bonus stardart, can help you win Master24: They can double score darts if it lands on their phenomenon or stellurae Bonus, 1/3 chance of scoring extra dart on owned phenomenon and stellurae. Avarian get to bring station in fleet, very OP for combat and max fleet size Zorestians get -20% decay, I think it means they start at world decay? Solid but can be supplemented by worlds instead. Makluvians - best merchant world build, best build speed, if you need to max that, probably best acceleration in the game. Quick Facts From manual: https://www.spacedomination.org/index.php/the-galaxy/ World Population The population regulates what and how many global facilities you can build as well as how fast building goes. Industry used to be 4x population. Is it still true? Home Worlds According to player \"sunny\" humans are sector 0, i think every game. North Northeast of OE. I am in sector 5, west of OE. Clockwise from OE increases sector Home World \u2013 Rich Planets supporting high industry Technical: 150 population (2250 industry max) Starting with Refinery, 3 of all minerals. If the home world is from your own race you will get a declaration of planets/phenomenon from the owner. This declaration can be seen on the Settings page of the Login Screen, as it can change depending on galaxy size. World Moods Worlds can revolt if happiness goes below some threshold, destroying industry. I assume this reduces pollution increasing happiness, so it will equilibrate naturally. Angry: None Annoyed: Merchant Content: Merchant and Beacon Happy: Merchant, Beacon, and Blaster Ecstatic: No limitations (Stardock) World Colors Blue with Orange Border - Old Earth Old Earth Technical: 200 population (3000 industry max) Starting with refinery, 3 of all minerals. Old Earth will start with Star Darts based on the number of worlds in the game. If taken you will get a percentage of planets/phenomenon from the owner of the planet. You can see the current set ratio on the Settings page of the login screen. BrightOrange - Core, rich worlds around Old Earth Core Worlds Technical: 100 population (1500 industry max) Starting with Refinery, 3 of all minerals. Purple - Merchant - population/30 + 1 merchants Maroon - Beacon - population/8 + 1 beacons Orange - Stardock - population/40 + 1 stardocks Red - Blaster - population/50 + 1 blasters Orange-red - Rich, 50% more build points Magenta - Poor, 50% less build points White - Normal, standard Orange Textured - Large - +20% Population, +1 all minerals Blue-Purple - Small - -20% Population Grey Smooth - Toxic - -60% Population, low industry Grey Textured - 2x faster industry build Blue - Sloops - 3 Pladesium Khaki - Frigates - 3 Frelenium Aqua - Corsairs - 3 Calastium Green - Stations - 3 Stenterium Red with Orange Stripe - Ranger - 3 S World Minerals Generation seems random with bonuses or guarantees for special worlds. 1 == 0.5x 2 == 1.0x 3 == 1.5x chiisana (player) says: 1 = 1/2 speed; 2 = full speed; 3 = twice(?) as fast Master24: 1.5x The world minerals start with the same letter as their ship except slooP and Pladesium. If you have none of a given mineral, you cannot build the corresponding ship, and if you have 3 of it you can build that ship at a quicker rate. Do the high mineral worlds correspond to the colored worlds above? What is a normal world's minerals? Rich world? Large world? Notes: - this Large world has 2 of all minerals and 3 of 2 minerals... which? - this merchant world has 3 revidium/ranger and holds 4 merchants max - merchant world with 1 revidium, 2 pladesium, 3 merchant max Pladesium: Sloops Calastium: Corsairs Frelenium: Frigates Stenterium: Stations Revidium: Rangers World Industry * Happiness ] Mightymo: Happiness will increase over time, And it works by percent Industry influences pollution as a % of total industry. Happiness increases over time Planets in home sector will be happier, home sector is the same sector as your race's homeworld. Anomalies Blue = slower Green = faster Early Strategy Fleet Fleet ECM is an important factor, so emphasize rangers. Fleets have a max size, but you won't hit it until you are harvesting worlds for fleets. Worlds Cannot afford much early on, so really need to pump fleet build up! Stardock is a goal. So is stellurae, but not yet attainable. Rangers are highly preferred thanks to their attack speed and ECM. To build stations? It is relevant once you hit max world fleet. You need the ecm for defense against other players as well. I think it's definitely worth it. Modern Strategy Blaster worlds seem very highly powered, assuming they are a fleet multiplier. If the fleet limit is normal, then blaster is the endgame. Blaster is also useful at all stages since it augments fleet power at peak non/attrition, increasing conquest speed. However, every non-merchant world will increase fleet harvesting times. Riffing on the classic strategy, we want to avoid pollution, so avoid building industry. It won't matter compared to merchants and stardocks. I think early stardocks are very useful to half the fleet attrition with a cost of only 10 global facilities. I also think that a template build based on fleet composition is the best option, stick to the long game. Questions Can I have 1 of each facility available on each planet? That is fantastic. What is sector? Can I use it to get to richer worlds? How is it better than distance from Old Earth? The population regulates what and how many global facilities you can build as well as how fast building goes. How much industry per pollution, how does pollution impact happiness? Is the max fleet size still present? Is industry with refinery worth it? It is a local facility. Note the tradeoff is that stellurae is now a local facility. Since Stellurae doesn't interfere with Merchant/Stardock strategy it may actually be worth it instead of industry+refinery. Classic Strategy focus on building tons of merchants so you can harvest your worlds. Ignore everything else. Fleet build balance is based exclusively on max fleet size. Eventually your fleet attrition will be high, then start balancing in Stardocks. Build some beacons early as you want to reap the benefits of fast travel early. Sometimes you need to remove beacons to avoid navigation problems. Avoid stardarts. Global Facilities Classic: focus on building tons of merchants so you can harvest your worlds. Ignore everything else. Merchants thedudeabides: Currently getting 7.77/37 increase - Master24: Yup, some races have added / decreased per merchant `(7.98*.95)/38 == 0.2% world build increase per Merchant, that's subtracting the human bonus and allowing for floating points... Factory [9:08 PM] thedudeabides: what are the technicals for factory? [9:11 PM] Master24: 50% extra build points for the industry built Blasters Blasters are a fleet bonus. Blaster cutoffs: [7:19 PM] thedudeabides: how many blasters to get above level 0 7:25 PM] Master24: Blasters: Level 0 100% 10-24 1 105% 25-49 2 110% 50-74 3 115% 75-99 4 120% 100-149 5 125% 150-199 6 130% 200-249 7 135% 250-299 8 140% 300-399 9 145% 400-499 10 150% 500-624 11 155% 625-749 12 160% 750-874 13 165% 875-999 14 170% 1000-1199 15 175% 1200-1399 16 180% 1400-1599 17 185% 1600-1799 18 190% 1800-1999 19 195% 2000+ 20 200% World Setup Ideas Early Merchant Growth Early Fleet Building Should I build a short string of 10 factory core with full industry for fleets? I think so! Will have to manage it when it revolts. It is +50% industry, so move in a bit before investing. Strafing worlds What's the easiest way to get 10k guns? Probably 10 worlds with 50% industry. Note that with 500 industry or 500 build, the worlds can easily finish merchant in about 2 minutes, so I think it is more efficient to set industry, then set merchant and leave. Industry takes 100 industry, so it might be good to kick start. Does population count towards build points? With 100 population, 1 industry per tick, so 500/6== 83 minutes to 500 industry. Target 90+ population worlds with a fleet about 8k-15k. The cutoff is to get 4 merchants. 50 industry all merchants up to 50% industry - dont wait on it to complete... build ships for 3 resource, then 2 build if no 3, 1 build if no 2 or 3... repeat, prioritize rangers solo early NO beacons early, 10 gave me like 1% increase in speed. Can get them once a few hundred merchants make building them 1-2 ticks. Note: 74 pop blaster world gave 12 blasters...absolutely huge. chiisana says try to get over 25 blasters at the beginning with 1-2 blaster worlds and some normal worlds. Notes & Anecdata chiisana: I personally like to do 30% industry, amenity, fly away and come back to it much later Storage attrition rollover tells you your build poins basically. Once you get to the storage of required - build points, you will complete the build next pulse with 0 attrition. Not fully validated. Sunny or someone says: 80k guns for a core world to be safe, 20k guns for a dart, you can roll over homeworlds with 120k guns Had a beacon world at 6000w-OE with 2 merchant, 4 beacon 34 pop Industry seems to be 10x population. Not sure how pollution is calculated from industry... A merchant world with 20 popl, 200 industry, severe pollution, ecstatic population, 3 revidium, no local facility, and 4 merchant facilities just gave me 800 guns of rangers 6180 seems to be the limit around my local... the old game used to increase the universe size if there were more players in the previous game. I found a beacon world around 5000 out from Old Earth and it had only 1 beacon. I guess it is +1 to +3 or something and this one natively had 0? I just found a normal planet with 2 merchants allowed. I don't know why. It also has 30 pop, 300 industry An early large world that I added full industry+factory to is Happy and producing several hundred guns after a wait. Even though pollution is severe, happiness is only very slowly going down, making it worth it for early harvest. TAKEAWAY: focus on large worlds early Worlds used to become more populated as approaching Old Earth, still true? If so focus on going that direction, as population affects global facilities on special worlds. Large world with max industry and a factory is losing happiness to pollution, but at the beginning I can't build enough \"storage\" build for a refinery to reduce pollution so I will try an amenity facility to keep them happy... but I can't seem to get to 8000 either, I may abandon the world and try some without industry to get fleet build up. Looks like merchants increase world build by a percentage, is it flat per merchant? That makes it kind of interesting rather than a flat value, since world build can be quite low without industry or factories. So this incentivizes me to build industry and factories. Scores \"cap\" - my cap - when your score accumulates to its full potential. The required score to win goes down 1% every 4 hours. Homeworlds are a good way to boost scores. Getting a homeworld is about 2.95% of total points when capped. Strategies Attacking Others You can reduce their global garrison power by ganking mech and stardock worlds where industry == 10x population . Spiral out from OE and follow a route that is working. It's easy to gank someone's merch if they are all in a row, but hard to collect guns if they are not. I think it might be better to have a guns place near OE then merch hunting via gates. Player Strategies & Alliances chiisani and waffle are brothers and ganged up on Sunny. Gawdawful seems to target merchants very heavily if people keep grudges, change names Misc Strategy Notes What about scumming/traveling for good worlds? Then the enemies cant follow your line and you have a facilities multiplier. Especially effective if you have a low attrition fleet... like stardarts, but then combat is slow... This 80 pop merch world has 16 merchant capacity. Wild. I can build merchants without command at 500 build. Base build is pop+ind. What is the minimum threshold build to build a merchant? 830/2+83 aka 83 pop planet is 498 build which is fine... how about 60 pop? 60+600/2 == 360 is that enough for merchant? A 90 population stardock world yields 15 stardocks. But have to get happiness up... I will try amenity on Icelu at 1859 north of OE Move into the 90 pop worlds early and build 4 merchants per world and optimize the queue, build 50% industry. Once you can build refinery, about 1500 gross build (incl factories), do 100% industry. Basically the tradeoff is pop vs command build if you build full industry. You could build factory to build refinery with only 66% otherwise required population.... but it's too slow Somehow Sunny has 147 merch with 48 worlds... must be cherry picking in the inner system. Chiisana says worlds x 4 == merch worlds early on is reasonable. The gates are a single large circuit predetermined. The size scales with galaxy size. The loop is apparently often about 30 gates. Gates can be used to get to a home sector, get closer to OE for better worlds, or scum a certain kind of world, but those worlds are also more discoverable by playeers.","title":"Stardart Spacedomination"},{"location":"docs/references/stardart_spacedomination/#space-domination-aka-stardart","text":"One of my favorite games from the 90s. Space Domination: A modern release of stardart: http://www.spacedomination.org/index.php/play/","title":"Space Domination AKA Stardart"},{"location":"docs/references/stardart_spacedomination/#build-ticks","text":"Build ticks are 10 seconds, measured with a stopwatch.","title":"Build Ticks"},{"location":"docs/references/stardart_spacedomination/#races","text":"It depends on if you need to maximize your acceleration into the game, your fleet power, your total build capacity, or your fleet retention. Raw score bonuses are the best long term, but fleet combat can make or break the game, heavily favoring Avarians. Human gets a bonus stardart, can help you win Master24: They can double score darts if it lands on their phenomenon or stellurae Bonus, 1/3 chance of scoring extra dart on owned phenomenon and stellurae. Avarian get to bring station in fleet, very OP for combat and max fleet size Zorestians get -20% decay, I think it means they start at world decay? Solid but can be supplemented by worlds instead. Makluvians - best merchant world build, best build speed, if you need to max that, probably best acceleration in the game.","title":"Races"},{"location":"docs/references/stardart_spacedomination/#quick-facts","text":"From manual: https://www.spacedomination.org/index.php/the-galaxy/","title":"Quick Facts"},{"location":"docs/references/stardart_spacedomination/#world-population","text":"The population regulates what and how many global facilities you can build as well as how fast building goes. Industry used to be 4x population. Is it still true?","title":"World Population"},{"location":"docs/references/stardart_spacedomination/#home-worlds","text":"According to player \"sunny\" humans are sector 0, i think every game. North Northeast of OE. I am in sector 5, west of OE. Clockwise from OE increases sector Home World \u2013 Rich Planets supporting high industry Technical: 150 population (2250 industry max) Starting with Refinery, 3 of all minerals. If the home world is from your own race you will get a declaration of planets/phenomenon from the owner. This declaration can be seen on the Settings page of the Login Screen, as it can change depending on galaxy size.","title":"Home Worlds"},{"location":"docs/references/stardart_spacedomination/#world-moods","text":"Worlds can revolt if happiness goes below some threshold, destroying industry. I assume this reduces pollution increasing happiness, so it will equilibrate naturally. Angry: None Annoyed: Merchant Content: Merchant and Beacon Happy: Merchant, Beacon, and Blaster Ecstatic: No limitations (Stardock)","title":"World Moods"},{"location":"docs/references/stardart_spacedomination/#world-colors","text":"Blue with Orange Border - Old Earth Old Earth Technical: 200 population (3000 industry max) Starting with refinery, 3 of all minerals. Old Earth will start with Star Darts based on the number of worlds in the game. If taken you will get a percentage of planets/phenomenon from the owner of the planet. You can see the current set ratio on the Settings page of the login screen. BrightOrange - Core, rich worlds around Old Earth Core Worlds Technical: 100 population (1500 industry max) Starting with Refinery, 3 of all minerals. Purple - Merchant - population/30 + 1 merchants Maroon - Beacon - population/8 + 1 beacons Orange - Stardock - population/40 + 1 stardocks Red - Blaster - population/50 + 1 blasters Orange-red - Rich, 50% more build points Magenta - Poor, 50% less build points White - Normal, standard Orange Textured - Large - +20% Population, +1 all minerals Blue-Purple - Small - -20% Population Grey Smooth - Toxic - -60% Population, low industry Grey Textured - 2x faster industry build Blue - Sloops - 3 Pladesium Khaki - Frigates - 3 Frelenium Aqua - Corsairs - 3 Calastium Green - Stations - 3 Stenterium Red with Orange Stripe - Ranger - 3 S","title":"World Colors"},{"location":"docs/references/stardart_spacedomination/#world-minerals","text":"Generation seems random with bonuses or guarantees for special worlds. 1 == 0.5x 2 == 1.0x 3 == 1.5x chiisana (player) says: 1 = 1/2 speed; 2 = full speed; 3 = twice(?) as fast Master24: 1.5x The world minerals start with the same letter as their ship except slooP and Pladesium. If you have none of a given mineral, you cannot build the corresponding ship, and if you have 3 of it you can build that ship at a quicker rate. Do the high mineral worlds correspond to the colored worlds above? What is a normal world's minerals? Rich world? Large world? Notes: - this Large world has 2 of all minerals and 3 of 2 minerals... which? - this merchant world has 3 revidium/ranger and holds 4 merchants max - merchant world with 1 revidium, 2 pladesium, 3 merchant max Pladesium: Sloops Calastium: Corsairs Frelenium: Frigates Stenterium: Stations Revidium: Rangers","title":"World Minerals"},{"location":"docs/references/stardart_spacedomination/#world-industry-happiness","text":"] Mightymo: Happiness will increase over time, And it works by percent Industry influences pollution as a % of total industry. Happiness increases over time Planets in home sector will be happier, home sector is the same sector as your race's homeworld.","title":"World Industry * Happiness"},{"location":"docs/references/stardart_spacedomination/#_1","text":"","title":""},{"location":"docs/references/stardart_spacedomination/#anomalies","text":"Blue = slower Green = faster","title":"Anomalies"},{"location":"docs/references/stardart_spacedomination/#early-strategy","text":"","title":"Early Strategy"},{"location":"docs/references/stardart_spacedomination/#fleet","text":"Fleet ECM is an important factor, so emphasize rangers. Fleets have a max size, but you won't hit it until you are harvesting worlds for fleets.","title":"Fleet"},{"location":"docs/references/stardart_spacedomination/#worlds","text":"Cannot afford much early on, so really need to pump fleet build up! Stardock is a goal. So is stellurae, but not yet attainable. Rangers are highly preferred thanks to their attack speed and ECM. To build stations? It is relevant once you hit max world fleet. You need the ecm for defense against other players as well. I think it's definitely worth it.","title":"Worlds"},{"location":"docs/references/stardart_spacedomination/#modern-strategy","text":"Blaster worlds seem very highly powered, assuming they are a fleet multiplier. If the fleet limit is normal, then blaster is the endgame. Blaster is also useful at all stages since it augments fleet power at peak non/attrition, increasing conquest speed. However, every non-merchant world will increase fleet harvesting times. Riffing on the classic strategy, we want to avoid pollution, so avoid building industry. It won't matter compared to merchants and stardocks. I think early stardocks are very useful to half the fleet attrition with a cost of only 10 global facilities. I also think that a template build based on fleet composition is the best option, stick to the long game.","title":"Modern Strategy"},{"location":"docs/references/stardart_spacedomination/#questions","text":"Can I have 1 of each facility available on each planet? That is fantastic. What is sector? Can I use it to get to richer worlds? How is it better than distance from Old Earth? The population regulates what and how many global facilities you can build as well as how fast building goes. How much industry per pollution, how does pollution impact happiness? Is the max fleet size still present? Is industry with refinery worth it? It is a local facility. Note the tradeoff is that stellurae is now a local facility. Since Stellurae doesn't interfere with Merchant/Stardock strategy it may actually be worth it instead of industry+refinery.","title":"Questions"},{"location":"docs/references/stardart_spacedomination/#classic-strategy","text":"focus on building tons of merchants so you can harvest your worlds. Ignore everything else. Fleet build balance is based exclusively on max fleet size. Eventually your fleet attrition will be high, then start balancing in Stardocks. Build some beacons early as you want to reap the benefits of fast travel early. Sometimes you need to remove beacons to avoid navigation problems. Avoid stardarts.","title":"Classic Strategy"},{"location":"docs/references/stardart_spacedomination/#global-facilities","text":"Classic: focus on building tons of merchants so you can harvest your worlds. Ignore everything else.","title":"Global Facilities"},{"location":"docs/references/stardart_spacedomination/#merchants","text":"thedudeabides: Currently getting 7.77/37 increase - Master24: Yup, some races have added / decreased per merchant `(7.98*.95)/38 == 0.2% world build increase per Merchant, that's subtracting the human bonus and allowing for floating points...","title":"Merchants"},{"location":"docs/references/stardart_spacedomination/#factory","text":"[9:08 PM] thedudeabides: what are the technicals for factory? [9:11 PM] Master24: 50% extra build points for the industry built","title":"Factory"},{"location":"docs/references/stardart_spacedomination/#blasters","text":"Blasters are a fleet bonus. Blaster cutoffs: [7:19 PM] thedudeabides: how many blasters to get above level 0 7:25 PM] Master24: Blasters: Level 0 100% 10-24 1 105% 25-49 2 110% 50-74 3 115% 75-99 4 120% 100-149 5 125% 150-199 6 130% 200-249 7 135% 250-299 8 140% 300-399 9 145% 400-499 10 150% 500-624 11 155% 625-749 12 160% 750-874 13 165% 875-999 14 170% 1000-1199 15 175% 1200-1399 16 180% 1400-1599 17 185% 1600-1799 18 190% 1800-1999 19 195% 2000+ 20 200%","title":"Blasters"},{"location":"docs/references/stardart_spacedomination/#world-setup-ideas","text":"","title":"World Setup Ideas"},{"location":"docs/references/stardart_spacedomination/#early-merchant-growth","text":"","title":"Early Merchant Growth"},{"location":"docs/references/stardart_spacedomination/#early-fleet-building","text":"Should I build a short string of 10 factory core with full industry for fleets? I think so! Will have to manage it when it revolts. It is +50% industry, so move in a bit before investing.","title":"Early Fleet Building"},{"location":"docs/references/stardart_spacedomination/#strafing-worlds","text":"What's the easiest way to get 10k guns? Probably 10 worlds with 50% industry. Note that with 500 industry or 500 build, the worlds can easily finish merchant in about 2 minutes, so I think it is more efficient to set industry, then set merchant and leave. Industry takes 100 industry, so it might be good to kick start. Does population count towards build points? With 100 population, 1 industry per tick, so 500/6== 83 minutes to 500 industry. Target 90+ population worlds with a fleet about 8k-15k. The cutoff is to get 4 merchants. 50 industry all merchants up to 50% industry - dont wait on it to complete... build ships for 3 resource, then 2 build if no 3, 1 build if no 2 or 3... repeat, prioritize rangers solo early NO beacons early, 10 gave me like 1% increase in speed. Can get them once a few hundred merchants make building them 1-2 ticks. Note: 74 pop blaster world gave 12 blasters...absolutely huge. chiisana says try to get over 25 blasters at the beginning with 1-2 blaster worlds and some normal worlds.","title":"Strafing worlds"},{"location":"docs/references/stardart_spacedomination/#notes-anecdata","text":"chiisana: I personally like to do 30% industry, amenity, fly away and come back to it much later Storage attrition rollover tells you your build poins basically. Once you get to the storage of required - build points, you will complete the build next pulse with 0 attrition. Not fully validated. Sunny or someone says: 80k guns for a core world to be safe, 20k guns for a dart, you can roll over homeworlds with 120k guns Had a beacon world at 6000w-OE with 2 merchant, 4 beacon 34 pop Industry seems to be 10x population. Not sure how pollution is calculated from industry... A merchant world with 20 popl, 200 industry, severe pollution, ecstatic population, 3 revidium, no local facility, and 4 merchant facilities just gave me 800 guns of rangers 6180 seems to be the limit around my local... the old game used to increase the universe size if there were more players in the previous game. I found a beacon world around 5000 out from Old Earth and it had only 1 beacon. I guess it is +1 to +3 or something and this one natively had 0? I just found a normal planet with 2 merchants allowed. I don't know why. It also has 30 pop, 300 industry An early large world that I added full industry+factory to is Happy and producing several hundred guns after a wait. Even though pollution is severe, happiness is only very slowly going down, making it worth it for early harvest. TAKEAWAY: focus on large worlds early Worlds used to become more populated as approaching Old Earth, still true? If so focus on going that direction, as population affects global facilities on special worlds. Large world with max industry and a factory is losing happiness to pollution, but at the beginning I can't build enough \"storage\" build for a refinery to reduce pollution so I will try an amenity facility to keep them happy... but I can't seem to get to 8000 either, I may abandon the world and try some without industry to get fleet build up. Looks like merchants increase world build by a percentage, is it flat per merchant? That makes it kind of interesting rather than a flat value, since world build can be quite low without industry or factories. So this incentivizes me to build industry and factories.","title":"Notes & Anecdata"},{"location":"docs/references/stardart_spacedomination/#scores","text":"\"cap\" - my cap - when your score accumulates to its full potential. The required score to win goes down 1% every 4 hours. Homeworlds are a good way to boost scores. Getting a homeworld is about 2.95% of total points when capped.","title":"Scores"},{"location":"docs/references/stardart_spacedomination/#strategies","text":"","title":"Strategies"},{"location":"docs/references/stardart_spacedomination/#attacking-others","text":"You can reduce their global garrison power by ganking mech and stardock worlds where industry == 10x population . Spiral out from OE and follow a route that is working. It's easy to gank someone's merch if they are all in a row, but hard to collect guns if they are not. I think it might be better to have a guns place near OE then merch hunting via gates.","title":"Attacking Others"},{"location":"docs/references/stardart_spacedomination/#player-strategies-alliances","text":"chiisani and waffle are brothers and ganged up on Sunny. Gawdawful seems to target merchants very heavily if people keep grudges, change names","title":"Player Strategies & Alliances"},{"location":"docs/references/stardart_spacedomination/#misc-strategy-notes","text":"What about scumming/traveling for good worlds? Then the enemies cant follow your line and you have a facilities multiplier. Especially effective if you have a low attrition fleet... like stardarts, but then combat is slow... This 80 pop merch world has 16 merchant capacity. Wild. I can build merchants without command at 500 build. Base build is pop+ind. What is the minimum threshold build to build a merchant? 830/2+83 aka 83 pop planet is 498 build which is fine... how about 60 pop? 60+600/2 == 360 is that enough for merchant? A 90 population stardock world yields 15 stardocks. But have to get happiness up... I will try amenity on Icelu at 1859 north of OE Move into the 90 pop worlds early and build 4 merchants per world and optimize the queue, build 50% industry. Once you can build refinery, about 1500 gross build (incl factories), do 100% industry. Basically the tradeoff is pop vs command build if you build full industry. You could build factory to build refinery with only 66% otherwise required population.... but it's too slow Somehow Sunny has 147 merch with 48 worlds... must be cherry picking in the inner system. Chiisana says worlds x 4 == merch worlds early on is reasonable. The gates are a single large circuit predetermined. The size scales with galaxy size. The loop is apparently often about 30 gates. Gates can be used to get to a home sector, get closer to OE for better worlds, or scum a certain kind of world, but those worlds are also more discoverable by playeers.","title":"Misc Strategy Notes"},{"location":"docs/references/uart_isp_ftdi_etc_programming/","text":"FTDI v ISP/ICSP v UART/USART v SPI These terms cause a bunch of confusion. Programming You probably program these things with avrdude . See man avrdude . Bootloaders It is popular to put a bootloader on your chip. This takes up some space but allows the chip to \"reprogram\" itself by writing to its own flash. Some systems have a separate ISP/ICSP or UART chip on board and you can use that to reprogram the chip without a bootloader. The purpose of both of these systems is that you can reprogram the chip while it is on-board. Disambiguation FTDI is one implementation of UART. ISP/ICSP is a set of similar protocols created by different companies, AVR ISP is used with AVR chips and is common/popular. UART is common. USART is uncommon. Many devices support UART and not USART. USART is similar to SPI. Definitions asynchronous - uses no clock synchronous - uses a clock Synchronous USART SPI ISP/ICSP Asynchronous UART (therefore FTDI) References Thread on USART v SPI Wikipedia SPI ISP/ICSP UART SPI - Serial Peripheral Interface Direction: Simplex Channels: 1 I used SPI via Raspberry Pi (original) GPIO pins to program a flash chip that I soldered onto my lenovo x220 mainboard to install coreboot. ISP/ICSP - In-system Programming or In Circuit Serial Programming . Direction: Channels: This allows you to program on-chip. There are multiple incompatible ISP technologies. AVR ISP is very popular right now. Wikipedia states: \"A ISP USB cable must typically be shorter than 180cm\" UART - Universal Asynchronous Receiver/Transmitter Direction: Simplex, Half Duplex, Full Duplex Channels: 1+ (typically 1 channel) The foundation of UART is the shift register and clock. Raspberry Pi <-> Arduino via UART Note that in the demo, a voltage divider is used to talk from the arduino to the raspberry pi. The raspberry pi uses 3v3 on the UART tx/rx pins. The arduino pin 11 (MOSI) gets the voltage divider to the Raspberry Pi GPIO 16 RxD UART. Demo What about Raspberry Pi -> ESP8266EX? Maybe the Raspberry Pi would be a good way to program the ESP8266EX? FTDI is UART Direction: A common chip in 2017 is FT232RL which goes USB to UART. The ESP8266EX AiLight uses the [BoyaMicro 25Q32ASSIG Chip] as an ISP. Future Technology Devices International is a company that apparently makes people sad sometimes. To use FTDI you need a 512 byte bootloader. A number of FTDI programmers exist but do not always seem branded as such. Arduino: FTDI or ISP? Arduinos used to have an FTDI chip but it was too expensive so they moved to a second chip that can do USB ISP on the primary chip. UART (FTDI) Programmers Sparkfun FT232RL Breakout: 3v3 5v These are called 'USB to serial IC' boards These use miniUSB, there is a different offering for microUSB Offers DTR pin but not RTS ; DTR resets your arduino; other models offer RTS Adafruit FTDI Friend FT232RL Breakout: 3v3 and 5v Offers RTS pin and DTR as a pad DTR guide Offers 3v3 and 5v - signal is 3v3 (5v compatible), power is 5v... make sure you know what you are doing Other brands The ESP8266 AiThinker Light Bulb needs an UART programmer recommended by the developer: AiLight Jig He got some boards from china, I have asked him for a link to the seller Hardware JTAG Programmers - Apparently the industry standard. Can we make these for fun? AVR ISP Programmers Standard issue microcomputers Raspberry Pi Arduino Uno BusPirate The CP210x USB to UART from Silicon Labs exists It is cheaper than the FTDI FT232RL. Adafruit offers a low-cost breakout board of this chip and it is also in other popular USB->UART devices. Raspberry Pi How does this fit into the picture? I have used it with flashrom as a flash programmer for a lenovo x220 with a test clip, how is this related to everything else? BusPirate Apparently the BUS Pirate can do all of this, but requires configuration. Arduino Uno Careful! Transmits at 5V which will fry the Raspberry Pi and esp8266. Software flashrom avrdude Arduino IDE","title":"Uart Isp Ftdi Etc Programming"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#ftdi-v-ispicsp-v-uartusart-v-spi","text":"These terms cause a bunch of confusion.","title":"FTDI v ISP/ICSP v UART/USART v SPI"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#programming","text":"You probably program these things with avrdude . See man avrdude .","title":"Programming"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#bootloaders","text":"It is popular to put a bootloader on your chip. This takes up some space but allows the chip to \"reprogram\" itself by writing to its own flash. Some systems have a separate ISP/ICSP or UART chip on board and you can use that to reprogram the chip without a bootloader. The purpose of both of these systems is that you can reprogram the chip while it is on-board.","title":"Bootloaders"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#disambiguation","text":"FTDI is one implementation of UART. ISP/ICSP is a set of similar protocols created by different companies, AVR ISP is used with AVR chips and is common/popular. UART is common. USART is uncommon. Many devices support UART and not USART. USART is similar to SPI.","title":"Disambiguation"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#definitions","text":"asynchronous - uses no clock synchronous - uses a clock","title":"Definitions"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#synchronous","text":"USART SPI ISP/ICSP","title":"Synchronous"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#asynchronous","text":"UART (therefore FTDI)","title":"Asynchronous"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#references","text":"Thread on USART v SPI Wikipedia SPI ISP/ICSP UART","title":"References"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#spi-serial-peripheral-interface","text":"Direction: Simplex Channels: 1 I used SPI via Raspberry Pi (original) GPIO pins to program a flash chip that I soldered onto my lenovo x220 mainboard to install coreboot.","title":"SPI - Serial Peripheral Interface"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#ispicsp-in-system-programming-or-in-circuit-serial-programming","text":"Direction: Channels: This allows you to program on-chip. There are multiple incompatible ISP technologies. AVR ISP is very popular right now. Wikipedia states: \"A ISP USB cable must typically be shorter than 180cm\"","title":"ISP/ICSP - In-system Programming or In Circuit Serial Programming."},{"location":"docs/references/uart_isp_ftdi_etc_programming/#uart-universal-asynchronous-receivertransmitter","text":"Direction: Simplex, Half Duplex, Full Duplex Channels: 1+ (typically 1 channel) The foundation of UART is the shift register and clock.","title":"UART - Universal Asynchronous Receiver/Transmitter"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#raspberry-pi-arduino-via-uart","text":"Note that in the demo, a voltage divider is used to talk from the arduino to the raspberry pi. The raspberry pi uses 3v3 on the UART tx/rx pins. The arduino pin 11 (MOSI) gets the voltage divider to the Raspberry Pi GPIO 16 RxD UART. Demo","title":"Raspberry Pi <-> Arduino via UART"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#what-about-raspberry-pi-esp8266ex","text":"Maybe the Raspberry Pi would be a good way to program the ESP8266EX?","title":"What about Raspberry Pi -> ESP8266EX?"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#ftdi-is-uart","text":"Direction: A common chip in 2017 is FT232RL which goes USB to UART. The ESP8266EX AiLight uses the [BoyaMicro 25Q32ASSIG Chip] as an ISP. Future Technology Devices International is a company that apparently makes people sad sometimes. To use FTDI you need a 512 byte bootloader. A number of FTDI programmers exist but do not always seem branded as such.","title":"FTDI is UART"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#arduino-ftdi-or-isp","text":"Arduinos used to have an FTDI chip but it was too expensive so they moved to a second chip that can do USB ISP on the primary chip.","title":"Arduino: FTDI or ISP?"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#uart-ftdi-programmers","text":"Sparkfun FT232RL Breakout: 3v3 5v These are called 'USB to serial IC' boards These use miniUSB, there is a different offering for microUSB Offers DTR pin but not RTS ; DTR resets your arduino; other models offer RTS Adafruit FTDI Friend FT232RL Breakout: 3v3 and 5v Offers RTS pin and DTR as a pad DTR guide Offers 3v3 and 5v - signal is 3v3 (5v compatible), power is 5v... make sure you know what you are doing","title":"UART (FTDI) Programmers"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#other-brands","text":"The ESP8266 AiThinker Light Bulb needs an UART programmer recommended by the developer: AiLight Jig He got some boards from china, I have asked him for a link to the seller","title":"Other brands"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#hardware","text":"JTAG Programmers - Apparently the industry standard. Can we make these for fun? AVR ISP Programmers Standard issue microcomputers Raspberry Pi Arduino Uno BusPirate","title":"Hardware"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#the-cp210x-usb-to-uart-from-silicon-labs-exists","text":"It is cheaper than the FTDI FT232RL. Adafruit offers a low-cost breakout board of this chip and it is also in other popular USB->UART devices.","title":"The CP210x USB to UART from Silicon Labs exists"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#raspberry-pi","text":"How does this fit into the picture? I have used it with flashrom as a flash programmer for a lenovo x220 with a test clip, how is this related to everything else?","title":"Raspberry Pi"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#buspirate","text":"Apparently the BUS Pirate can do all of this, but requires configuration.","title":"BusPirate"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#arduino-uno","text":"Careful! Transmits at 5V which will fry the Raspberry Pi and esp8266.","title":"Arduino Uno"},{"location":"docs/references/uart_isp_ftdi_etc_programming/#software","text":"flashrom avrdude Arduino IDE","title":"Software"},{"location":"docs/references/vim_tricks/","text":"A collection of vim tricks. For .vimrc , see .dotfiles Vim tricks are added here in order of need. A trick not often referenced should be at the bottom. Buffers :tabnew - open a new empty buffer :edit - open in a new buffer :buffers , :ls - show open buffers :buffer 1 , :bu 1 - go to buffer 1 :buffer - go to buffer that matches substring (press tab to complete) :bd 1 - close buffer :w - write buffer","title":"Vim Tricks"},{"location":"docs/references/vim_tricks/#a-collection-of-vim-tricks-for-vimrc-see-dotfiles","text":"Vim tricks are added here in order of need. A trick not often referenced should be at the bottom.","title":"A collection of vim tricks. For .vimrc, see .dotfiles"},{"location":"docs/references/vim_tricks/#buffers","text":":tabnew - open a new empty buffer :edit - open in a new buffer :buffers , :ls - show open buffers :buffer 1 , :bu 1 - go to buffer 1 :buffer - go to buffer that matches substring (press tab to complete) :bd 1 - close buffer :w - write buffer","title":"Buffers"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/","text":"Advanced DATA ENGINEERING PATTERNS with Airflow Speaker: Max Beauchim, Creator of Airflow and Superset currently @ Lyft (was at Airbnb) prev. Data Engineer at Facebook, inspiration! He is wearing an Airflow shirt... how do I get an Airflow shirt? Check out his medium account, there are a few interesting blog posts on there. Teespring is an airflow user. He will do a batch and send a link over the next few days. There are a bunch of frameworks for running jobs every 5 minutes or every minute. Qbiz data consulting firm guy says during questions: 3/4 of our customers use AutoDAG. Answer: With superset, it is not a scheduler. It could expose an endpoint where airflow could call an endpoint where the queries run and write a pipeline out of it. What is Data Engineering? In charge of building data models and data pipelines that organize information in a way that it can power the processes of the people in the company. He wrote a blog post The Downfall of the Data Engineer discussing challenges today. Another post Functional Data Engineering about data engineering design patterns. Apache Airflow A batch workflow orchestrator. Especially for large data pipelines . The tasks really accumulate and orchestrating really become a challenge... denormalize, something, something else.... What is Airflow - 5 min An open source platform to author, schedule, and monitor batch processes. It's the glue that binds your data ecosystem together. It orchestrates tasks in a complex network of job dependencies. It's Python all the way down. It's popular and has a thriving open source community. It's expressive and dynamic, workflows are defined in code. Airflow is configuration as code and pipelines as code . We are going to get into why configuration as code is such a powerful concept. DAG is a fancy acronym that also just means workflow in this context (and Directed Acyclic Graph). Hive and Spark operators with a DAG to define topology of workflow . Data Engineering Patterns - Foundational Pattern for all examples Concept: building data pipelines dynamically A classic data warehouse is pretty static. Dimension tables, fact tables. Processes roughly for every table. Airflow is dynamic, breaks out of this pattern. Pipelines dynamically built that read configuration. Configuration as code Why use code instead of drag-and-drop data pipelines? Because it naturally gets source control and design patterns are easier to pull and collaborate on. Configuration as code is more powerful than good ole configuration files . Code is more expressive, powerful, and compact Resuable components (functions, classes, object factories) come naturally in code. An API has a clear specification with defaults, input validation, and useful methods. Allow users to hook logic to configuration as callbacks. SEE IMAGE IN PHONE FOR REST. Conceptual Model SEE PHOTO Example 1: AB Testing Example Lets change a Lyft button to be a brighter shade of pink. Airflow script to read configuration of all these experiments and metrics and weave a workflow of dependency based on the input of the user. As the workflow executes, it waits on source data, processes metrics and experiments. Comes out with P-value, confidence interval, other computations. These become exposed in the UI. Computation Frameworks AutoDAG at AirBnB - lots of people run sql and they just want to schedule it to run every day. Might not want to set up a pipeline. Built a simple UI as an airflow plugin, AutoDAG , they paste what they run and give it a target table, finds dependencies, creates waitfor operator, hivepartitionsensors, lints code and gives advice, and schedules the workflow and alerts on failure. Simplest implementation of this pattern Source code for autodag is extremely simple, couple dozen lines of code. Example 2: Engagement & Growth Metrics - web companies and most industries, aka \"Growth Accounting Metrics\" DAU, WAU, MAU / new, churn, resurrected, stale and active users Wrote this for all of facebook then replicated for different verticals: photos, messaging, photo uploads - anything you can think of we wanted a flavor of this pipeline. Count distinct metrics are ... slide is gone... (try to get the slides) Framework reads the config file and builds a very complex framework on your behalf. Behind the scene / at Facebook There's a photo that has a bunch of bullets for how this configuration works (he said 'behind the Python') Runs optimized logic If building the same pipeline over and over, some older ones won't be optimized. Why not improve the old whenever you improve the new? Cut the long tail of high cardinality dimension as specified Give parameters instead of tons of parameters and the framework does it automagically for you. In theory crafts a dashboard on your behalf. Experimentation Based largely on how it's done using Airflow at AirBnB. Their complex dags are MASSIVE at airbnb. Nested in a complicated way. This looks to be a couple hundred root tasks. Wait for source data Load source data into metric repository He could do a talk on what a metric repository might be. A skinny table with a lot of rows... joins to experimental assignments and experimental stats ... (slide moved on) ... (slide moved on) ... (slide moved on) No photo for the above 5 points, get the slides? More Complexity Cookie->userid mapping event level attributes, dimensional breakdowns different types of subjects (host, guests, listing, cookie, ...) different types of experimentation (web, mobile, emails, tickets...) ... (slide moved on, see photo) statistics beyond pvalue and confidence intervals, preventing bias, global impact, time-boxing Need for ML Feature Repository Where you put all your entity centric methods that are useful to train your machine learning models. Instead of reinventing the wheel for each model you are training. Entity-centric methods used to train ML models centralized & reusable across models consistent reproducible. smart and efficient around time-windowing life-to-date metrics how many times over the last 7- or 28-days that a user performed a certain action use a YAML file to define what might be interesting hooks for training and scoring hooks are out of the metrics repository Stats Daemon This is not open source. It seems like there is a lack of followthrough. He thought people would start open sourcing high leve. Running a sql express engine against the partition. How to make a Stats Daemon Model metastore, ask metastore for schema of table, ask rule engine to build sql automatically. Use presto and pivot the result, attach to partition in a skinny table. He verbally said the following: A stats daemon is the idea of computing database stats on top of your data warehouse. People who know about classic RDBMS, mysql, oracle, postgres, etc. These stats are stored in the schema for the query optimizer to plan.- Hive etc. do not compute these stats but people can leverage these stats too, beyond the query optimizer.- Every time we see something changes in hive or hive metadata we compute a bunch more metadata.- (See photo for this slide and copy the text below... ) - - More! Anomoly Detection Production MySQL exports AirOlap: Loads data into druid.io druid.io - in-memory column store that's really fast Email targeting rule engine Complex rules to determine who gets what email - no marketing email in 3 days and no lyft ride in 7 days... do the right thing Cohort analysis and user segmentation (prototype) [Insert your common pattern here] Knowing you can write dynamic python you can find your own place to apply this pattern. Conclusion METADATA ENGINEERING! Airflow allows you to take data enginering to a whole new level. Data engineering should find common patterns in their work and build frameworks and services Building pipelines can be repetitive and inefficient. Data engineers should build machines that build pipelines.","title":"Airflowcreatortalkbigdata 20180117"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#advanced-data-engineering-patterns-with-airflow","text":"","title":"Advanced DATA ENGINEERING PATTERNS with Airflow"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#speaker-max-beauchim-creator-of-airflow-and-superset","text":"currently @ Lyft (was at Airbnb) prev. Data Engineer at Facebook, inspiration! He is wearing an Airflow shirt... how do I get an Airflow shirt? Check out his medium account, there are a few interesting blog posts on there. Teespring is an airflow user. He will do a batch and send a link over the next few days. There are a bunch of frameworks for running jobs every 5 minutes or every minute.","title":"Speaker: Max Beauchim, Creator of Airflow and Superset"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#qbiz-data-consulting-firm-guy-says-during-questions","text":"3/4 of our customers use AutoDAG. Answer: With superset, it is not a scheduler. It could expose an endpoint where airflow could call an endpoint where the queries run and write a pipeline out of it.","title":"Qbiz data consulting firm guy says during questions:"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#what-is-data-engineering","text":"In charge of building data models and data pipelines that organize information in a way that it can power the processes of the people in the company. He wrote a blog post The Downfall of the Data Engineer discussing challenges today. Another post Functional Data Engineering about data engineering design patterns.","title":"What is Data Engineering?"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#apache-airflow","text":"A batch workflow orchestrator. Especially for large data pipelines . The tasks really accumulate and orchestrating really become a challenge... denormalize, something, something else....","title":"Apache Airflow"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#what-is-airflow-5-min","text":"An open source platform to author, schedule, and monitor batch processes. It's the glue that binds your data ecosystem together. It orchestrates tasks in a complex network of job dependencies. It's Python all the way down. It's popular and has a thriving open source community. It's expressive and dynamic, workflows are defined in code. Airflow is configuration as code and pipelines as code . We are going to get into why configuration as code is such a powerful concept. DAG is a fancy acronym that also just means workflow in this context (and Directed Acyclic Graph). Hive and Spark operators with a DAG to define topology of workflow .","title":"What is Airflow - 5 min"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#data-engineering-patterns-foundational-pattern-for-all-examples","text":"Concept: building data pipelines dynamically A classic data warehouse is pretty static. Dimension tables, fact tables. Processes roughly for every table. Airflow is dynamic, breaks out of this pattern. Pipelines dynamically built that read configuration.","title":"Data Engineering Patterns - Foundational Pattern for all examples"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#configuration-as-code","text":"Why use code instead of drag-and-drop data pipelines? Because it naturally gets source control and design patterns are easier to pull and collaborate on. Configuration as code is more powerful than good ole configuration files . Code is more expressive, powerful, and compact Resuable components (functions, classes, object factories) come naturally in code. An API has a clear specification with defaults, input validation, and useful methods. Allow users to hook logic to configuration as callbacks. SEE IMAGE IN PHONE FOR REST.","title":"Configuration as code"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#conceptual-model","text":"SEE PHOTO","title":"Conceptual Model"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#example-1-ab-testing-example","text":"Lets change a Lyft button to be a brighter shade of pink. Airflow script to read configuration of all these experiments and metrics and weave a workflow of dependency based on the input of the user. As the workflow executes, it waits on source data, processes metrics and experiments. Comes out with P-value, confidence interval, other computations. These become exposed in the UI.","title":"Example 1: AB Testing Example"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#computation-frameworks","text":"AutoDAG at AirBnB - lots of people run sql and they just want to schedule it to run every day. Might not want to set up a pipeline. Built a simple UI as an airflow plugin, AutoDAG , they paste what they run and give it a target table, finds dependencies, creates waitfor operator, hivepartitionsensors, lints code and gives advice, and schedules the workflow and alerts on failure. Simplest implementation of this pattern Source code for autodag is extremely simple, couple dozen lines of code.","title":"Computation Frameworks"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#example-2-engagement-growth-metrics-web-companies-and-most-industries-aka-growth-accounting-metrics","text":"DAU, WAU, MAU / new, churn, resurrected, stale and active users Wrote this for all of facebook then replicated for different verticals: photos, messaging, photo uploads - anything you can think of we wanted a flavor of this pipeline. Count distinct metrics are ... slide is gone... (try to get the slides) Framework reads the config file and builds a very complex framework on your behalf.","title":"Example 2: Engagement & Growth Metrics - web companies and most industries, aka \"Growth Accounting Metrics\""},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#behind-the-scene-at-facebook","text":"There's a photo that has a bunch of bullets for how this configuration works (he said 'behind the Python') Runs optimized logic If building the same pipeline over and over, some older ones won't be optimized. Why not improve the old whenever you improve the new? Cut the long tail of high cardinality dimension as specified Give parameters instead of tons of parameters and the framework does it automagically for you. In theory crafts a dashboard on your behalf.","title":"Behind the scene / at Facebook"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#experimentation","text":"Based largely on how it's done using Airflow at AirBnB. Their complex dags are MASSIVE at airbnb. Nested in a complicated way. This looks to be a couple hundred root tasks. Wait for source data Load source data into metric repository He could do a talk on what a metric repository might be. A skinny table with a lot of rows... joins to experimental assignments and experimental stats ... (slide moved on) ... (slide moved on) ... (slide moved on) No photo for the above 5 points, get the slides?","title":"Experimentation"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#more-complexity","text":"Cookie->userid mapping event level attributes, dimensional breakdowns different types of subjects (host, guests, listing, cookie, ...) different types of experimentation (web, mobile, emails, tickets...) ... (slide moved on, see photo) statistics beyond pvalue and confidence intervals, preventing bias, global impact, time-boxing","title":"More Complexity"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#need-for-ml-feature-repository","text":"Where you put all your entity centric methods that are useful to train your machine learning models. Instead of reinventing the wheel for each model you are training. Entity-centric methods used to train ML models centralized & reusable across models consistent reproducible. smart and efficient around time-windowing life-to-date metrics how many times over the last 7- or 28-days that a user performed a certain action use a YAML file to define what might be interesting hooks for training and scoring hooks are out of the metrics repository","title":"Need for ML Feature Repository"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#stats-daemon","text":"This is not open source. It seems like there is a lack of followthrough. He thought people would start open sourcing high leve. Running a sql express engine against the partition.","title":"Stats Daemon"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#how-to-make-a-stats-daemon","text":"Model metastore, ask metastore for schema of table, ask rule engine to build sql automatically. Use presto and pivot the result, attach to partition in a skinny table. He verbally said the following: A stats daemon is the idea of computing database stats on top of your data warehouse. People who know about classic RDBMS, mysql, oracle, postgres, etc. These stats are stored in the schema for the query optimizer to plan.- Hive etc. do not compute these stats but people can leverage these stats too, beyond the query optimizer.- Every time we see something changes in hive or hive metadata we compute a bunch more metadata.- (See photo for this slide and copy the text below... )","title":"How to make a Stats Daemon"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#-","text":"","title":"-"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#-_1","text":"","title":"-"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#more","text":"Anomoly Detection Production MySQL exports AirOlap: Loads data into druid.io druid.io - in-memory column store that's really fast Email targeting rule engine Complex rules to determine who gets what email - no marketing email in 3 days and no lyft ride in 7 days... do the right thing Cohort analysis and user segmentation (prototype) [Insert your common pattern here] Knowing you can write dynamic python you can find your own place to apply this pattern.","title":"More!"},{"location":"docs/talks/AirflowCreatorTalkBigData_20180117/#conclusion","text":"METADATA ENGINEERING! Airflow allows you to take data enginering to a whole new level. Data engineering should find common patterns in their work and build frameworks and services Building pipelines can be repetitive and inefficient. Data engineers should build machines that build pipelines.","title":"Conclusion"},{"location":"docs/talks/ReactSFMeetup_20160923_PublishYourComponents/","text":"Publish your own react component Speaker: Mark Muskardin Presentation: http://hackingbeauty.com/reactbook/ About Mark: Mark is building single page blazing fast apps in react/redux for startups. Outline \"No Install\" apps are desirable Future: People want offline 'native feeling' web apps NPM is (opinion) where all dependencies should go, no longer bower Companies are managing apps facing all the different facets of their business e.g. facing both customers and sellers Reusability is key... so develop in Components! Publish your React Components on NPM. npm publish \"and you're done\" Case Study: Material-UI - Google Material React Components Case II: Mark's component - material-ui-youtube-autocomplete Write good documentation! How to install How to use A great example using github pages A solid github readme Use nwb to create your component \"Tooling in a single devDependency for developing, testing, building: React Apps React Components and Libraries npm Modules for the Web nwb builds your demo page for you Nota Bene: You can deliver js and css together through npm in separate files References: ui-patterns.com reddit reactjs nwb frontend npm packaging","title":"Reactsfmeetup 20160923 Publishyourcomponents"},{"location":"docs/talks/ReactSFMeetup_20160923_PublishYourComponents/#publish-your-own-react-component","text":"Speaker: Mark Muskardin Presentation: http://hackingbeauty.com/reactbook/ About Mark: Mark is building single page blazing fast apps in react/redux for startups.","title":"Publish your own react component"},{"location":"docs/talks/ReactSFMeetup_20160923_PublishYourComponents/#outline","text":"\"No Install\" apps are desirable Future: People want offline 'native feeling' web apps NPM is (opinion) where all dependencies should go, no longer bower Companies are managing apps facing all the different facets of their business e.g. facing both customers and sellers Reusability is key... so develop in Components! Publish your React Components on NPM. npm publish \"and you're done\" Case Study: Material-UI - Google Material React Components Case II: Mark's component - material-ui-youtube-autocomplete Write good documentation! How to install How to use A great example using github pages A solid github readme Use nwb to create your component \"Tooling in a single devDependency for developing, testing, building: React Apps React Components and Libraries npm Modules for the Web nwb builds your demo page for you Nota Bene: You can deliver js and css together through npm in separate files","title":"Outline"},{"location":"docs/talks/ReactSFMeetup_20160923_PublishYourComponents/#references","text":"ui-patterns.com reddit reactjs nwb frontend npm packaging","title":"References:"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/","text":"React Animation Speaker: About Speaker: Comes from game development industry Game Animation 30 FPS doesn't really work out, you need to get to 60 fps Debugging is very challenging Webapps Sad about the animation quality (gives a number of really terrible animation examples. CSS3 animations better performance fairly easy to use no programmatic control - trigger and forget cross browser support (it's better now) DOM Incredibly slow Inconsistent API with bad cross-browser support never meant to support complex single page apps Single page apps Code and state management is near impossible in a jQuery App State management is bad in backbone But - react + redux fast rendering fast state management So with react+redux can we do the cool stuff from the game dev industry? We don't have the years of experience and code patterns... (get the example from the presentation) sets css3 opacity from reducer based on scroll getOpacityFromScroll(action.yScroll) use connect to make sure react component can listen to and get state of the redux store connect is a library that works between react and redux. quite popular? one way data flow, set and forget very performant, fluid did not use time control but redux has it in redux you can go frame by frame with time control to debug weird animation frames can we make the demo better? maybe make middleware perhaps write a general animation library based on the concept wraps the whole thing (jquery but in react/redux) Questions Have you tried particle systems based on this demo? not yet but i want to \"Sara Drasner\" or something that sounds similar is an authority on doing this sort of particle based animation question person: shoutout to \"greenstuff\" or something similar, GSAP animation library? Are you using react native at instacart? no we are in native and we are moving code to swift, we are trying to get all our code to swift","title":"Reactsfmeetup 20161013 Animation"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/#react-animation","text":"Speaker: About Speaker: Comes from game development industry","title":"React Animation"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/#game-animation","text":"30 FPS doesn't really work out, you need to get to 60 fps Debugging is very challenging","title":"Game Animation"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/#webapps","text":"Sad about the animation quality (gives a number of really terrible animation examples. CSS3 animations better performance fairly easy to use no programmatic control - trigger and forget cross browser support (it's better now) DOM Incredibly slow Inconsistent API with bad cross-browser support never meant to support complex single page apps Single page apps Code and state management is near impossible in a jQuery App State management is bad in backbone But - react + redux fast rendering fast state management","title":"Webapps"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/#so-with-reactredux-can-we-do-the-cool-stuff-from-the-game-dev-industry","text":"We don't have the years of experience and code patterns... (get the example from the presentation) sets css3 opacity from reducer based on scroll getOpacityFromScroll(action.yScroll) use connect to make sure react component can listen to and get state of the redux store connect is a library that works between react and redux. quite popular? one way data flow, set and forget very performant, fluid did not use time control but redux has it in redux you can go frame by frame with time control to debug weird animation frames can we make the demo better? maybe make middleware perhaps write a general animation library based on the concept wraps the whole thing (jquery but in react/redux)","title":"So with react+redux can we do the cool stuff from the game dev industry?"},{"location":"docs/talks/ReactSFMeetup_20161013_Animation/#questions","text":"Have you tried particle systems based on this demo? not yet but i want to \"Sara Drasner\" or something that sounds similar is an authority on doing this sort of particle based animation question person: shoutout to \"greenstuff\" or something similar, GSAP animation library? Are you using react native at instacart? no we are in native and we are moving code to swift, we are trying to get all our code to swift","title":"Questions"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/","text":"React Async Speaker: Works at: HelloSign Plans to give 60 free seats at reactuniversity.com. High level summary React has won on the UI side. Angular 2 similar to react Ember moved to component approach Stuff missing in redux with async There is middleware redux-saga for async New frontier in javascript is async JavaScript Revolution JQuery, Backbone, Knockout, Angular, Angular2, etc. Now we are seeing the patterns emerge and react has 'won' But react is just one part of the architecture Should only handle view layer State management: redux has simplified it \"redux is a great step forwards\" Redux: Manage state through pure functions and unidirectional data flow Your UI becomes a state machine hen your redux store state changes your react views respond with new data HelloSign has 5 single page apps. Some started implementing redux Result: moved business logic out of react components which is the goal Redux is a workflow - NOT a \"complete architecture\" We need an architecture on top of redux Approach to this: redux middleware think of middleware as a third party extension - django analogy uses currying to dispatch... (see slides) Lets look at some code examples Promises: only three states pending ?? rejected However, async we also need to be able to cancel async processes Redux documentation says redux-thunk but the author says - this is wrong redux-thunk is a function that wraps an expression to delay its evaluation Wrap whatever function into another function and have the middleware ( redux-thunk ) run it later speaker has an example of redux-thunk wrapping in the presentation redux-thunk evaluation: Great for small projects super simple fast to run easy to test in node dependency injection is hard to do... recently redux allows passing an extra value in the thunk but you always have to pass your dependencies in here which adds a lot of code fsa - flux standard action a set of standards describing what an action should look like redux thunk is not fsa compliant doesn't scale well tons of action creators dispatching functions, hard to track down \"too easy to forget error handling and pending state\" forgetting to do the cache forgetting to set a spinner when loading no way to cancel a thunk - ouch rxjs : Reactive eXtensions for JavaScript functional reactive programming need to have a masters or phd to understand functional js If Functional Reactive Programming (FRP) is your thing this is for you netflix uses it a ton does a lot of stuff redux already does, it's probably not a good thing to use WITH redux. rxjs is really robust already redux-saga : saga pattern in redux author uses a ton at HelloSign based on generators author considers generators a better strategy than async await in many cases \"turns your async code into a pillar of your architecture\" instead of dispatching thunk s, you create saga s to gather all your Side Effects logic in a central place saga pattern : ... (look it up, there's a technical paper about it) Wrapup Redux is great for managing state but incomplete; missing: ` He just skipped this slide... get the slides Questions Generators is a learning curve with redux saga \"The 80/20 of Generators\" - book create your own babel and something or other Title is probably: \"The 80/20 of ES2015 Generators\" by Valeri Karpov guy comments: angular 2 observables can be used in the same way as redux-saga guy question: are observables the future? speaker: observables got pushed back and there has been actual pushback against it netflix is pushing hard for something or other with observables, maybe 'falcor' react, redux etc support ie8 i guess, or maybe just hellosign? Highlight of promise to saga is cancelable. If that is async how is it really cancelable? My undestanding is that it stops calling .next on it, maybe... or just drops the result as a cancel maybe? try... catch has finally which may be responsible for canceling","title":"Reactsfmeetup 20161013 Reactasync"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#react-async","text":"Speaker: Works at: HelloSign Plans to give 60 free seats at reactuniversity.com.","title":"React Async"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#high-level-summary","text":"React has won on the UI side. Angular 2 similar to react Ember moved to component approach Stuff missing in redux with async There is middleware redux-saga for async New frontier in javascript is async","title":"High level summary"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#javascript-revolution","text":"JQuery, Backbone, Knockout, Angular, Angular2, etc. Now we are seeing the patterns emerge and react has 'won' But react is just one part of the architecture Should only handle view layer State management: redux has simplified it \"redux is a great step forwards\" Redux: Manage state through pure functions and unidirectional data flow Your UI becomes a state machine hen your redux store state changes your react views respond with new data HelloSign has 5 single page apps. Some started implementing redux Result: moved business logic out of react components which is the goal","title":"JavaScript Revolution"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#redux-is-a-workflow-not-a-complete-architecture","text":"We need an architecture on top of redux Approach to this: redux middleware think of middleware as a third party extension - django analogy uses currying to dispatch... (see slides) Lets look at some code examples Promises: only three states pending ?? rejected However, async we also need to be able to cancel async processes Redux documentation says redux-thunk but the author says - this is wrong redux-thunk is a function that wraps an expression to delay its evaluation Wrap whatever function into another function and have the middleware ( redux-thunk ) run it later speaker has an example of redux-thunk wrapping in the presentation redux-thunk evaluation: Great for small projects super simple fast to run easy to test in node dependency injection is hard to do... recently redux allows passing an extra value in the thunk but you always have to pass your dependencies in here which adds a lot of code fsa - flux standard action a set of standards describing what an action should look like redux thunk is not fsa compliant doesn't scale well tons of action creators dispatching functions, hard to track down \"too easy to forget error handling and pending state\" forgetting to do the cache forgetting to set a spinner when loading no way to cancel a thunk - ouch rxjs : Reactive eXtensions for JavaScript functional reactive programming need to have a masters or phd to understand functional js If Functional Reactive Programming (FRP) is your thing this is for you netflix uses it a ton does a lot of stuff redux already does, it's probably not a good thing to use WITH redux. rxjs is really robust already redux-saga : saga pattern in redux author uses a ton at HelloSign based on generators author considers generators a better strategy than async await in many cases \"turns your async code into a pillar of your architecture\" instead of dispatching thunk s, you create saga s to gather all your Side Effects logic in a central place saga pattern : ... (look it up, there's a technical paper about it)","title":"Redux is a workflow - NOT a \"complete architecture\""},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#wrapup","text":"Redux is great for managing state but incomplete; missing: ` He just skipped this slide... get the slides","title":"Wrapup"},{"location":"docs/talks/ReactSFMeetup_20161013_ReactAsync/#questions","text":"Generators is a learning curve with redux saga \"The 80/20 of Generators\" - book create your own babel and something or other Title is probably: \"The 80/20 of ES2015 Generators\" by Valeri Karpov guy comments: angular 2 observables can be used in the same way as redux-saga guy question: are observables the future? speaker: observables got pushed back and there has been actual pushback against it netflix is pushing hard for something or other with observables, maybe 'falcor' react, redux etc support ie8 i guess, or maybe just hellosign? Highlight of promise to saga is cancelable. If that is async how is it really cancelable? My undestanding is that it stops calling .next on it, maybe... or just drops the result as a cancel maybe? try... catch has finally which may be responsible for canceling","title":"Questions"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/","text":"Lightning Talks Really messy! 1. Linting Originally a C program by Stephen Johnson, 1978 paper. AST, checks against rules. Checks code more strictly than a compiler for syntax, consistency, style Linters are lint-like programs for many languages. Purpose Less Debugging, Looking for logic loopholes, Carving out dead code, Reduce runtime errors, For big teams: Consistency, Interpreted languages - no compile time Uses Unused variables, functions, dead code, undeclared/unset vars, enforcefunction argument/parameter checking... etc. Style Checking Code looks fine but is inconsistent. You know the stuff, PEP8. Consistency. Python Flake8, PyLint, PyFlakes, Pep8 For editors vim - flake8 emacs - ? Custom lint rules You can write a plugin that examines whatever can be checked by AST, etc. Also you can write little rulesets that \"lint\" your code by rules 2. Zebras and Lasers - Jonas Neubert - Zymergen Talk about barcode readers. Writes software stuck in a box for factories. The laser takes samples over time, so you have to do image processing. You thing opencv = image processing. I think LIST COMPREHENSIONS. kernel = lambda a,b,c: a if a==c!=b else b smooth = ''.join([(a,b,c) for a,b,c in zip(data[0:], data[1:], data[2:])]) [str(round(len(list(v))/4.0)) for k,v in itertools.groupby(smooth)][1:-1] Look up what you got on the wikipedia table of barcodes 3. 2FA, OTP, WTF - Making technical concepts accessible - Kelly Who here works on a website where people sign up or login? Congrats you are a security engineer. Get your family using password managers and 2FA . Factors: Something you know, something you have, something you are Use this stuff. 4. Gert, Scientist @ Nasa working on Kepler satellite Kepler looks at the brightness of stars and if you look long enough the brightness dims for 6 hours once a year. You can find a planet using 7-8 lines of python. I am going to find a planet around a distant star live on stage. python3, numpy, scipy.signal, matplotlib working in a jupyter notebook Use a low pass filter to remove long term trend in star brightness data, this normalizes the year. Next, a lomb-scargle periodogram or something is used to find periodic signal in the data. The planet has a 0.84 day orbit, so the data was aggregated daily. Python package: PyKE - come talk to us if you want to be a developer or intern at nasa. 5. Bot Cars! - John Ellis Race course out in oakland once a month, the cars look like RC type cars. Were are these events? Huge warehouse in oakland!! Behavior cloning is what we do. Other techniques: You can do line following, something else... Data labeling is tough in machine learning. Having a data labeler system expidites that. Toolchain Camera input device OpenCV, B4L2 capture, python3 Adafruit BNO005 gyroscope, dualshock4+ds4drv controller, usb2 camera v4l2capture nvidia jetson tx2 + orbitty carrier pololu micromaester + libusb Cycloid: Traxxas Chassis Donkeycar: raspberry pi, 3dprinted superstruture, ~$200 Derp Learning: Nvidia TX1, Traxxas Slash, ~$800 put a gpu on your car so you have no delay and can learn on board Virtual test environment - use a graphics engine in unity you can use numpy+scikit image but it has its limits, he did it 6. Quilt - Docker, but for Data - Anish akarve/pydatabook - an example Why? Code has reusable building blocks, github, PyPI, DockerHub Data is missing reusable building blocks - stuff like s3, github, everywhere online Data packages: metadata and serialized Package Lifecycle - 3-4 primitives that matter - build, , install, import - `quilt build` - shred them into a dataframe, hash, stick into a hash tree, serialize columnar data, indexing Why track in a hash tree? - Need to be able to send all the deltas If you just change a readme, just want to download that on a version update Catalog is like PyPI but for data his book on quiltdata.com from quilt.data.akarve import pydata_book as pb - pb.getdata.train() (or something) and you get a dataframe out. Working on react+Tensorflow, R, Spark, going to get stuff into Jupyter. 7. Datasette - Simon @ Eventbrite - journalist stuff @ guardian datasette Make an instant, read-only JSON API for any SQLite database. It also provides tools for packaging the database as a docker container and deploying to hosting providers. Arbitrary SQL is pretty fine, you can't really modify the data, read only. Chrome history example. San Francisco open data portal, data.sfgov.org - download csv of trees from the city Wrote [csvs2sqlite] which just turns the CSV to a sqlite3 database. Can refactor csv to something a bit more relational. Extract some columns... He list about 12 columns he wants into separate tables. Also he uses -x to make the columns searchable in sqlite, indexing or whatever? $ datasette tree.db $ datasette publish now sf-trees.db - gives you a URL, hyperlinks. Just like that you have a browseable, searchable json API he built https://sf-tree-search.now.sh because he thought \"why not?\" - search sf by tree 8. How to build community - Simeon Pacman rule - Eric Holscher - don't stand in a circle, people can't get in. Everyone should meet more people. Bring a friend, bring a female coworker. BayPiggies, SF Django Meetup, Pyninsula, PyLadies, East Bay Python, North Bay Python","title":"Sfpython Holidayparty Lightningtalks 20171207"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#lightning-talks","text":"Really messy!","title":"Lightning Talks"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#1-linting","text":"Originally a C program by Stephen Johnson, 1978 paper. AST, checks against rules. Checks code more strictly than a compiler for syntax, consistency, style Linters are lint-like programs for many languages.","title":"1. Linting"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#purpose","text":"Less Debugging, Looking for logic loopholes, Carving out dead code, Reduce runtime errors, For big teams: Consistency, Interpreted languages - no compile time","title":"Purpose"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#uses","text":"Unused variables, functions, dead code, undeclared/unset vars, enforcefunction argument/parameter checking... etc.","title":"Uses"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#style-checking","text":"Code looks fine but is inconsistent. You know the stuff, PEP8. Consistency.","title":"Style Checking"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#python","text":"Flake8, PyLint, PyFlakes, Pep8","title":"Python"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#for-editors","text":"vim - flake8 emacs - ?","title":"For editors"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#custom-lint-rules","text":"You can write a plugin that examines whatever can be checked by AST, etc.","title":"Custom lint rules"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#also-you-can-write-little-rulesets-that-lint-your-code-by-rules","text":"","title":"Also you can write little rulesets that \"lint\" your code by rules"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#2-zebras-and-lasers-jonas-neubert-zymergen","text":"Talk about barcode readers. Writes software stuck in a box for factories. The laser takes samples over time, so you have to do image processing. You thing opencv = image processing. I think LIST COMPREHENSIONS. kernel = lambda a,b,c: a if a==c!=b else b smooth = ''.join([(a,b,c) for a,b,c in zip(data[0:], data[1:], data[2:])]) [str(round(len(list(v))/4.0)) for k,v in itertools.groupby(smooth)][1:-1] Look up what you got on the wikipedia table of barcodes","title":"2. Zebras and Lasers - Jonas Neubert - Zymergen"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#3-2fa-otp-wtf-making-technical-concepts-accessible-kelly","text":"Who here works on a website where people sign up or login? Congrats you are a security engineer. Get your family using password managers and 2FA .","title":"3. 2FA, OTP, WTF - Making technical concepts accessible - Kelly"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#factors-something-you-know-something-you-have-something-you-are","text":"Use this stuff.","title":"Factors: Something you know, something you have, something you are"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#4-gert-scientist-nasa-working-on-kepler-satellite","text":"Kepler looks at the brightness of stars and if you look long enough the brightness dims for 6 hours once a year. You can find a planet using 7-8 lines of python. I am going to find a planet around a distant star live on stage. python3, numpy, scipy.signal, matplotlib working in a jupyter notebook Use a low pass filter to remove long term trend in star brightness data, this normalizes the year. Next, a lomb-scargle periodogram or something is used to find periodic signal in the data. The planet has a 0.84 day orbit, so the data was aggregated daily. Python package: PyKE - come talk to us if you want to be a developer or intern at nasa.","title":"4. Gert, Scientist @ Nasa working on Kepler satellite"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#5-bot-cars-john-ellis","text":"Race course out in oakland once a month, the cars look like RC type cars. Were are these events? Huge warehouse in oakland!!","title":"5. Bot Cars! - John Ellis"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#behavior-cloning-is-what-we-do","text":"Other techniques: You can do line following, something else... Data labeling is tough in machine learning. Having a data labeler system expidites that.","title":"Behavior cloning is what we do."},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#toolchain","text":"Camera input device OpenCV, B4L2 capture, python3 Adafruit BNO005 gyroscope, dualshock4+ds4drv controller, usb2 camera v4l2capture nvidia jetson tx2 + orbitty carrier pololu micromaester + libusb Cycloid: Traxxas Chassis Donkeycar: raspberry pi, 3dprinted superstruture, ~$200 Derp Learning: Nvidia TX1, Traxxas Slash, ~$800 put a gpu on your car so you have no delay and can learn on board Virtual test environment - use a graphics engine in unity you can use numpy+scikit image but it has its limits, he did it","title":"Toolchain"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#6-quilt-docker-but-for-data-anish","text":"akarve/pydatabook - an example","title":"6. Quilt - Docker, but for Data - Anish"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#why","text":"Code has reusable building blocks, github, PyPI, DockerHub Data is missing reusable building blocks - stuff like s3, github, everywhere online Data packages: metadata and serialized","title":"Why?"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#package-lifecycle-3-4-primitives-that-matter","text":"- build, , install, import - `quilt build` - shred them into a dataframe, hash, stick into a hash tree, serialize columnar data, indexing","title":"Package Lifecycle - 3-4 primitives that matter"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#why-track-in-a-hash-tree-need-to-be-able-to-send-all-the-deltas","text":"If you just change a readme, just want to download that on a version update","title":"Why track in a hash tree? - Need to be able to send all the deltas"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#catalog-is-like-pypi-but-for-data","text":"his book on quiltdata.com from quilt.data.akarve import pydata_book as pb - pb.getdata.train() (or something) and you get a dataframe out. Working on react+Tensorflow, R, Spark, going to get stuff into Jupyter.","title":"Catalog is like PyPI but for data"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#7-datasette-simon-eventbrite-journalist-stuff-guardian","text":"datasette Make an instant, read-only JSON API for any SQLite database. It also provides tools for packaging the database as a docker container and deploying to hosting providers. Arbitrary SQL is pretty fine, you can't really modify the data, read only. Chrome history example. San Francisco open data portal, data.sfgov.org - download csv of trees from the city Wrote [csvs2sqlite] which just turns the CSV to a sqlite3 database. Can refactor csv to something a bit more relational. Extract some columns... He list about 12 columns he wants into separate tables. Also he uses -x to make the columns searchable in sqlite, indexing or whatever? $ datasette tree.db $ datasette publish now sf-trees.db - gives you a URL, hyperlinks. Just like that you have a browseable, searchable json API he built https://sf-tree-search.now.sh because he thought \"why not?\" - search sf by tree","title":"7. Datasette - Simon @ Eventbrite - journalist stuff @ guardian"},{"location":"docs/talks/SFPython_HolidayParty_LightningTalks_20171207/#8-how-to-build-community-simeon","text":"Pacman rule - Eric Holscher - don't stand in a circle, people can't get in. Everyone should meet more people. Bring a friend, bring a female coworker. BayPiggies, SF Django Meetup, Pyninsula, PyLadies, East Bay Python, North Bay Python","title":"8. How to build community - Simeon"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/","text":"Raymond Hettinger Holiday Party Talk 2017 Raymond says: I will tweet out a link to this presentation later. It is in sphinx. Notes are in this folder, /outlines/talks , as HettingerHolidaySF2017.pdf . Mission: Train thousands of Python Developers Mutable Minds, Inc. raymond.hettinger@gmail.com Training Videos: Free to users of Safari Online: \"Modern Python: Big Ideas, Little Code\" Raymond says about a $100 on-ramp to using Safari Online @raymondh on twitter I use sphinx to prepare my talks / slide decks. Never intend to go back to Powerpoint. I am a manufacturer of Python Programmers. I take someone good at something and make them good at something plus Python programming. Questions from the end of the talk I didn't really record them all. (Mentions offhand he has an OCaml background) Q: Why can't I use a value use_slots = True instead of manually adding slots Raymond: I expect some discussion this week on python-dev about that. Solution is probably that the class decorator will return a new class with the slots in it. It's a little late to turn it on and off with true/false. The present design doesn't preclude that feature. We need to avoid making it impossible. Also because no one who reviewed the pep and no one thought of it, or eric wanted to do it that way. Python 3.7 How to hold these 3 numbers: 33, 1.00, 0.5 (HSL Colors) Class Generators: dataclasses and namedtuples Problems to be Solved I want to pass around a bunch of instances of colors: HSL system. Dark Orange: 33 degrees on the color wheel at 100% saturation and 50% lightness. from bunch import Bunch from types import SimpleNamespace ? import record # for recordtype ? import dataclass # tuple dark_orange = ( 33 , 1.00 , 0.5 ) print ( dark_orange ) # dict dark_orange = { 'hue' : 33 , 'saturation' : 1.0 , 'lightness' : 0.5 } print ( dark_orange ) # simple class class Color : ''' there are 6 basic dunder methods, __init__, __hash__, something else, __lt__ etc, ''' def __init__ ( self , hue , saturation , lightness = 0.5 ): self . hue = hue self . saturation = saturation self . lightness = lightness dark_orange = Color ( 33 , 1.00 , 0.5 ) print ( dark_orange ) # bunch recipe ########### Bunch can be written in three lines (not in std library) dark_orange = Bunch ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) print ( dark_orange ) # simple namespace ######### Bunch, but in the standard library, written in c # good, because it's in the standard library... ha but it's just bunch # this way is pretty good, repr but can't compare it, can't sort, can't hash... # takes a bunch of space... has an object with a reference to a dictionary, 300 bytes dark_orange = SimpleNamespace ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) # named tuples ######### i stole it, i'm an aggregator... i found it reinvented dozens of times # i brought them all together in a massive chart, took the best ideas from each, aggregated # published the recipe, got lots of people to use it, took it to python dev, we put it in # internally same name tuple as before, but now written in a class format... before what? class Color ( NamedTuple ): ''' benefits from before one from each line see the datatype, use default ''' hue : int saturation : floor lightness : float = 0.5 # calling the NamedTuple... 72 bytes, 4 times smaller than SimpleNamespace # make one namedtuple then you can make another one based on it, just change an attribute and clone # named tuples are hashable so they are useable as dictionary keys # immutable! - whaa - you just have to use the replace() method to make another... too hard dark_orange = Color ( hue = 33 , saturation = 1.00 ) print ( dark_orange ) ''' Python 2.7 so it's commented # record by george sakkis #### # python 2.7 recipe and not changed for Python3 # we had mutable nametuples for a very long time, 8 years, no typing, needs typing # but it didn't have a cool name#127.0.0.1 dev.hackersinresidence.c so no one knew! Color = record.recordtype('Color', ['hue', 'saturation', 'lightness']) # mutability is fun! # 64 bytes, smaller than a tuple... tuples store the length, instances don't unless you add the field # so this can't tell you its length... but it's smaller dark_orange = Color(hue=, saturation=1.00, lightness=0.5) ''' # dataclass ################## # half the people see it as a data container, half the people see it as a class # rorscach test # you can start using it in Python3.6 with raymonds code, or wait for python3.7 # in python2, you can import recordtype as dataclass - ha! # biggest way of all at 296 bytes, bigger than a dict @dataclass class Color : ''' it writes classes for you and holds data ''' hue : int saturation : float lightness : float = 0.5 dark_orange = Color ( hue = 33 , saturation = 1.00 ) print ( dark_orange ) # dataclass with slots but no defaults ######## @dataclass class Color : ''' 64 bytes but you can't have any default values, or use george's recipe ''' slots = [ 'hue' , 'saturation' , 'lightness' ] hue : int saturation : float lightness : float dark_orange = Color ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) print ( dark_orange ) # you learned the history of how to store 3 numbers # this gives some output Details about each data container option Have to see the notes for this... it's really fast Bunch and SimpleNamespace Recipe class Bunch ( object ): def __init__ ( self , ** kwds ): self . __dict__ . update ( kwds ) Optimization class Bunch ( object ): ''' much faster, replace the dict with kwds dict is guaranteed to be ordered ''' def __init__ ( self , ** kwds ): self . __dict__ = kwds C version built into Python from types import SimpleNamespace Named Tuples - same size as regular tuple Replaces tons of stuff with NamedTuples when doing code review raymond loves fstrings - brought by eric smith who did dataclass - eric smith are you going to remember his name? You can let the code generator build it then modify it yourself... how? what? I think it's written in python so you need to paste it in or something... no idea Data Classes - PEP 557 has landed Validates that NamedTuple was doing the right thing but we need mutable. And a cool name. Immutable if you want (possible to freeze the data) PEP says - mutable namedtuples with defaults main design goal is to support static type checkers highly opinionated about typing, no way to use it without typing static typing was optional, not here... you can put a type of None or any and it will be ignored. have to explicitly opt out of typing with None or any raymond is working on a workaround boilerplate for class, attribute based dataholder is it a code generator? is it a data holder? two different ways of looking at it generates code for you, generates class docstring, init , repr , eq with strong typechecking, rich comparisons, hashing, read-only enforced by setattr , delattr from dataclasses import make_dataclass - this thing is huge unless there are slots... but with slots you lose defaults - the language has a built in constraint against slots and defaults at the same time Do you always know if something is going to be integer float? No. 12.5 timezones off in india! When you import types it actually executes code... so there is debate about whether they will stringify types in make_dataclass if you read python-dev you will get all of the drama emulate a namedtuple (see slides) with from operator import itemgetter and dataclasses Summary I have been studying dataclasses since the first draft of PEP 557. I really like the new dataclasses! If you need mutable named tuples today, try George Sakkis's Record class or use the attached dataclass code that runs fine on Python3.6 but not prior. (code in raymond's slides) See the 4 tuple code generator table: Namedtuple, Record, Dataclasses, Dataclasses w/ slots Gains and losses (see the slides) Some Nice Improvements (see the slides) Some things that aren't as nice higher complexity and learning curve, 700 ish lines of code, couple hundred lines of tests, lots of specs. dataclasses is its own miniature ORM for python stuff, declare, fields() function, hashable, etc. (see the slides) Inside the sphinx slides this talk is from, you can cut and paste raymond's code and use it now.","title":"Sfpython Holidayparty Raymondhettinger 20171207"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#raymond-hettinger-holiday-party-talk-2017","text":"Raymond says: I will tweet out a link to this presentation later. It is in sphinx. Notes are in this folder, /outlines/talks , as HettingerHolidaySF2017.pdf . Mission: Train thousands of Python Developers Mutable Minds, Inc. raymond.hettinger@gmail.com Training Videos: Free to users of Safari Online: \"Modern Python: Big Ideas, Little Code\" Raymond says about a $100 on-ramp to using Safari Online @raymondh on twitter I use sphinx to prepare my talks / slide decks. Never intend to go back to Powerpoint. I am a manufacturer of Python Programmers. I take someone good at something and make them good at something plus Python programming.","title":"Raymond Hettinger Holiday Party Talk 2017"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#questions-from-the-end-of-the-talk","text":"I didn't really record them all. (Mentions offhand he has an OCaml background) Q: Why can't I use a value use_slots = True instead of manually adding slots Raymond: I expect some discussion this week on python-dev about that. Solution is probably that the class decorator will return a new class with the slots in it. It's a little late to turn it on and off with true/false. The present design doesn't preclude that feature. We need to avoid making it impossible. Also because no one who reviewed the pep and no one thought of it, or eric wanted to do it that way.","title":"Questions from the end of the talk"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#python-37","text":"How to hold these 3 numbers: 33, 1.00, 0.5 (HSL Colors)","title":"Python 3.7"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#class-generators-dataclasses-and-namedtuples","text":"","title":"Class Generators: dataclasses and namedtuples"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#problems-to-be-solved","text":"I want to pass around a bunch of instances of colors: HSL system. Dark Orange: 33 degrees on the color wheel at 100% saturation and 50% lightness. from bunch import Bunch from types import SimpleNamespace ? import record # for recordtype ? import dataclass # tuple dark_orange = ( 33 , 1.00 , 0.5 ) print ( dark_orange ) # dict dark_orange = { 'hue' : 33 , 'saturation' : 1.0 , 'lightness' : 0.5 } print ( dark_orange ) # simple class class Color : ''' there are 6 basic dunder methods, __init__, __hash__, something else, __lt__ etc, ''' def __init__ ( self , hue , saturation , lightness = 0.5 ): self . hue = hue self . saturation = saturation self . lightness = lightness dark_orange = Color ( 33 , 1.00 , 0.5 ) print ( dark_orange ) # bunch recipe ########### Bunch can be written in three lines (not in std library) dark_orange = Bunch ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) print ( dark_orange ) # simple namespace ######### Bunch, but in the standard library, written in c # good, because it's in the standard library... ha but it's just bunch # this way is pretty good, repr but can't compare it, can't sort, can't hash... # takes a bunch of space... has an object with a reference to a dictionary, 300 bytes dark_orange = SimpleNamespace ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) # named tuples ######### i stole it, i'm an aggregator... i found it reinvented dozens of times # i brought them all together in a massive chart, took the best ideas from each, aggregated # published the recipe, got lots of people to use it, took it to python dev, we put it in # internally same name tuple as before, but now written in a class format... before what? class Color ( NamedTuple ): ''' benefits from before one from each line see the datatype, use default ''' hue : int saturation : floor lightness : float = 0.5 # calling the NamedTuple... 72 bytes, 4 times smaller than SimpleNamespace # make one namedtuple then you can make another one based on it, just change an attribute and clone # named tuples are hashable so they are useable as dictionary keys # immutable! - whaa - you just have to use the replace() method to make another... too hard dark_orange = Color ( hue = 33 , saturation = 1.00 ) print ( dark_orange ) ''' Python 2.7 so it's commented # record by george sakkis #### # python 2.7 recipe and not changed for Python3 # we had mutable nametuples for a very long time, 8 years, no typing, needs typing # but it didn't have a cool name#127.0.0.1 dev.hackersinresidence.c so no one knew! Color = record.recordtype('Color', ['hue', 'saturation', 'lightness']) # mutability is fun! # 64 bytes, smaller than a tuple... tuples store the length, instances don't unless you add the field # so this can't tell you its length... but it's smaller dark_orange = Color(hue=, saturation=1.00, lightness=0.5) ''' # dataclass ################## # half the people see it as a data container, half the people see it as a class # rorscach test # you can start using it in Python3.6 with raymonds code, or wait for python3.7 # in python2, you can import recordtype as dataclass - ha! # biggest way of all at 296 bytes, bigger than a dict @dataclass class Color : ''' it writes classes for you and holds data ''' hue : int saturation : float lightness : float = 0.5 dark_orange = Color ( hue = 33 , saturation = 1.00 ) print ( dark_orange ) # dataclass with slots but no defaults ######## @dataclass class Color : ''' 64 bytes but you can't have any default values, or use george's recipe ''' slots = [ 'hue' , 'saturation' , 'lightness' ] hue : int saturation : float lightness : float dark_orange = Color ( hue = 33 , saturation = 1.00 , lightness = 0.5 ) print ( dark_orange ) # you learned the history of how to store 3 numbers # this gives some output","title":"Problems to be Solved"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#details-about-each-data-container-option","text":"Have to see the notes for this... it's really fast","title":"Details about each data container option"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#bunch-and-simplenamespace","text":"","title":"Bunch and SimpleNamespace"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#recipe","text":"class Bunch ( object ): def __init__ ( self , ** kwds ): self . __dict__ . update ( kwds )","title":"Recipe"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#optimization","text":"class Bunch ( object ): ''' much faster, replace the dict with kwds dict is guaranteed to be ordered ''' def __init__ ( self , ** kwds ): self . __dict__ = kwds","title":"Optimization"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#c-version-built-into-python","text":"from types import SimpleNamespace","title":"C version built into Python"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#named-tuples-same-size-as-regular-tuple","text":"Replaces tons of stuff with NamedTuples when doing code review raymond loves fstrings - brought by eric smith who did dataclass - eric smith are you going to remember his name? You can let the code generator build it then modify it yourself... how? what? I think it's written in python so you need to paste it in or something... no idea","title":"Named Tuples - same size as regular tuple"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#data-classes-pep-557-has-landed","text":"Validates that NamedTuple was doing the right thing but we need mutable. And a cool name. Immutable if you want (possible to freeze the data) PEP says - mutable namedtuples with defaults main design goal is to support static type checkers highly opinionated about typing, no way to use it without typing static typing was optional, not here... you can put a type of None or any and it will be ignored. have to explicitly opt out of typing with None or any raymond is working on a workaround boilerplate for class, attribute based dataholder is it a code generator? is it a data holder? two different ways of looking at it generates code for you, generates class docstring, init , repr , eq with strong typechecking, rich comparisons, hashing, read-only enforced by setattr , delattr from dataclasses import make_dataclass - this thing is huge unless there are slots... but with slots you lose defaults - the language has a built in constraint against slots and defaults at the same time Do you always know if something is going to be integer float? No. 12.5 timezones off in india! When you import types it actually executes code... so there is debate about whether they will stringify types in make_dataclass if you read python-dev you will get all of the drama emulate a namedtuple (see slides) with from operator import itemgetter and dataclasses","title":"Data Classes - PEP 557 has landed"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#summary","text":"I have been studying dataclasses since the first draft of PEP 557. I really like the new dataclasses! If you need mutable named tuples today, try George Sakkis's Record class or use the attached dataclass code that runs fine on Python3.6 but not prior. (code in raymond's slides) See the 4 tuple code generator table: Namedtuple, Record, Dataclasses, Dataclasses w/ slots","title":"Summary"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#gains-and-losses","text":"(see the slides)","title":"Gains and losses"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#some-nice-improvements","text":"(see the slides)","title":"Some Nice Improvements"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#some-things-that-arent-as-nice","text":"higher complexity and learning curve, 700 ish lines of code, couple hundred lines of tests, lots of specs. dataclasses is its own miniature ORM for python stuff, declare, fields() function, hashable, etc. (see the slides)","title":"Some things that aren't as nice"},{"location":"docs/talks/SFPython_HolidayParty_RaymondHettinger_20171207/#inside-the-sphinx-slides-this-talk-is-from-you-can-cut-and-paste-raymonds-code-and-use-it-now","text":"","title":"Inside the sphinx slides this talk is from, you can cut and paste raymond's code and use it now."},{"location":"docs/talks/SFPython_Import_Madness_20170614/","text":"import madness This talk only works in Python 3!! This title import madness is executable. If we import it we get an ImportError without that module existing. What is a module? A python file. What else is a module? An object loaded that represents a python module (as in: Python file) Python has a standard module type. __import__ will initialize a module by executing all the source of the module file in main. Can you implement a mergesort algorithm using the Python import keyword? Merge Yes! Should you? Obviously, no. Speaker discusses mergesort. When you import a module in Python, Python executes the entire source of that module. madness is a wrapper module which will import mergesort. It will then create new modules for the left side and right side and continue. Solve most import errors with sys.path . DANGER!! WARNING!! import is dangerous!! Python imports the containing module to find any function you import from that module. Including uploading all your ssh keys to pastebin, encrypting your drive, and deleting the line of code that did that. Some of the source bit.ly/2s8YmzL current_module = sys.modules(__name__) module_source = inspect.getsource(current_module) # buckle up! from merge_sort import sorted_sublist as sorted_list","title":"Sfpython Import Madness 20170614"},{"location":"docs/talks/SFPython_Import_Madness_20170614/#import-madness","text":"This talk only works in Python 3!! This title import madness is executable. If we import it we get an ImportError without that module existing. What is a module? A python file. What else is a module? An object loaded that represents a python module (as in: Python file) Python has a standard module type. __import__ will initialize a module by executing all the source of the module file in main.","title":"import madness"},{"location":"docs/talks/SFPython_Import_Madness_20170614/#can-you-implement-a-mergesort-algorithm-using-the-python-import-keyword","text":"Merge Yes! Should you? Obviously, no. Speaker discusses mergesort. When you import a module in Python, Python executes the entire source of that module. madness is a wrapper module which will import mergesort. It will then create new modules for the left side and right side and continue. Solve most import errors with sys.path .","title":"Can you implement a mergesort algorithm using the Python import keyword?"},{"location":"docs/talks/SFPython_Import_Madness_20170614/#danger-warning","text":"import is dangerous!! Python imports the containing module to find any function you import from that module. Including uploading all your ssh keys to pastebin, encrypting your drive, and deleting the line of code that did that.","title":"DANGER!! WARNING!!"},{"location":"docs/talks/SFPython_Import_Madness_20170614/#some-of-the-source","text":"bit.ly/2s8YmzL current_module = sys.modules(__name__) module_source = inspect.getsource(current_module) # buckle up! from merge_sort import sorted_sublist as sorted_list","title":"Some of the source"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/","text":"Unit Testing with Mock This talk is about unit testing. Speaker: Brian Weber, SRE at Twitter Lets execute tests in your code safely Tests execute your code. For example, a command line function that deletes hard drives... How do we do it? mock What is a mock ? unitteset.mock is a library for Testing in Python. It allows you to replace parts of your system under test with mock objects... (is this text from the unittest documentation?) Why use mock ? Stop the state-changing parts so you can actually run tests. Write better code _____ (missed it!) Patch decorator Mocks are plastic Everything the mock does returns another mock spec - flexible but not safe spec_set - safer, somewhat immutable autospec - match function signatures of class instances Mocks have a bunch of introspection features called, call_count, call_args, call_args list, method_calls, ... (more) assert_called, assert_called_once, ... (more) Example: API Requests Two options Patch locally defined function Replace portion of function being tested - side-effect. Patch external library Which would you pick? USE BOTH! It's really easy to write, don't worry about it and write both. Another thing: Mock \"Factory\" Kind of a factory but not really. DO NOT mock The filesystem - too many surfaces and edges. Lots of debate but don't do it use the temp dir module or whatever it is called. Very simple Acceptance and Integration tests Additional info Write mocks as PyTest fixtures. PyTest and mock go hand-in-hand. How do you mock a for loop that hits an API a certain number of times? Mock the parent library and setup some sort of a \"factory\" module One instantiation setup that mocks all the behavior For loop means some expected behavior inside for loop and some expected behavior outside for loop. Usually you will patch directly in the namespace you are testing. Direct accuracy over what you are replacing.","title":"Sfpython Unit Testing With Mock 20170614"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#unit-testing-with-mock","text":"This talk is about unit testing. Speaker: Brian Weber, SRE at Twitter Lets execute tests in your code safely Tests execute your code. For example, a command line function that deletes hard drives...","title":"Unit Testing with Mock"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#how-do-we-do-it-mock","text":"","title":"How do we do it? mock"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#what-is-a-mock","text":"unitteset.mock is a library for Testing in Python. It allows you to replace parts of your system under test with mock objects... (is this text from the unittest documentation?)","title":"What is a mock?"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#why-use-mock","text":"Stop the state-changing parts so you can actually run tests. Write better code _____ (missed it!)","title":"Why use mock?"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#patch-decorator","text":"","title":"Patch decorator"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#mocks-are-plastic","text":"Everything the mock does returns another mock spec - flexible but not safe spec_set - safer, somewhat immutable autospec - match function signatures of class instances","title":"Mocks are plastic"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#mocks-have-a-bunch-of-introspection-features","text":"called, call_count, call_args, call_args list, method_calls, ... (more) assert_called, assert_called_once, ... (more)","title":"Mocks have a bunch of introspection features"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#example-api-requests","text":"","title":"Example: API Requests"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#two-options","text":"","title":"Two options"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#patch-locally-defined-function","text":"Replace portion of function being tested - side-effect.","title":"Patch locally defined function"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#patch-external-library","text":"Which would you pick? USE BOTH! It's really easy to write, don't worry about it and write both.","title":"Patch external library"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#another-thing-mock-factory","text":"Kind of a factory but not really.","title":"Another thing: Mock \"Factory\""},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#do-not-mock","text":"The filesystem - too many surfaces and edges. Lots of debate but don't do it use the temp dir module or whatever it is called. Very simple Acceptance and Integration tests","title":"DO NOT mock"},{"location":"docs/talks/SFPython_Unit_Testing_With_Mock_20170614/#additional-info","text":"Write mocks as PyTest fixtures. PyTest and mock go hand-in-hand. How do you mock a for loop that hits an API a certain number of times? Mock the parent library and setup some sort of a \"factory\" module One instantiation setup that mocks all the behavior For loop means some expected behavior inside for loop and some expected behavior outside for loop. Usually you will patch directly in the namespace you are testing. Direct accuracy over what you are replacing.","title":"Additional info"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/","text":"Installing, Deploying, Using Tensorflow in Python Speaker: Chris Fregley, Pipeline.ai (former Netflix, Databricks, kickstarted Spark.) https://github.com/PipelineAI/pipeline/ Zero respect for Python until he found Scientific Python. PySpark not his favorite, rather use Scala for Spark, originally a Java guy Slides available on meetup: slides Great GPU notebooks and examples This guy is such a salesman. He used port 6969 because of port colissions. Clever. Notes from meetup site Main talk (~30 mins + Q&A) Optimizing, Profiling, and Deploying High-Performance Spark ML and TensorFlow AI Models in Production with GPUs Using the latest advancements from TensorFlow including the Accelerated Linear Algebra (XLA) Framework, JIT/AOT Compiler, and Graph Transform Tool, I\u2019ll demonstrate how to optimize, profile, and deploy TensorFlow Models - and the TensorFlow Runtime - in GPU-based production environment. This talk is 100% demo based on open source tools and completely reproducible through Docker on your own GPU cluster. Bio Chris Fregly is Founder and Research Engineer at PipelineAI, a Streaming Machine Learning and Artificial Intelligence Startup based in San Francisco. He is also an Apache Spark Contributor, a Netflix Open Source Committer, founder of the Global Advanced Spark and TensorFlow Meetup, author of the O\u2019Reilly Training and Video Series titled, \"High-Performance TensorFlow in Production.\" Previously, Chris was a Distributed Systems Engineer at Netflix, a Data Solutions Engineer at Databricks, and a Founding Member and Principal Engineer at the IBM Spark Technology Center in San Francisco. Tensorflow! Mostly in C. Neural networks never want to go to production always want to be retrained want someone else to do the last 20% Pipeline.ai A framework to get your models into solution. Something about data pipelines! Today - TensorFlow (TF) - Condensed talk: 8 hour into 30 minutes Optimize and Deploy TF models to production. Nice to have a working knowledge of TF. GPU heavy talk. Content Breakdown 50% training optimizations(GPUs, Training Pipeline, JIT) 50% prediction optimizations (AOT Compile, TF Serving) Why heavy focus on 'model prediction' vs 'just training'? Training - boring and batch! Prediction - exciting and real time! Agenda - see the slides Biggest thing is telling data scientists that they can deploy from their jupyter notebook in a controlled manner. Ability to push it out & roll it back. DOCKER - Package model and runtime as one Docker for mac - opened up a ton of use cases! no surprises in production deploy and tune model + runtime together same local, dev, production env Production always a bit different than development before this. A bunch of virtualbox cruft. Did he consider vagrant? I think docker just blows vagrant away for developers, removes tons of devops. Tune Model + Runtime together! (see slides!) Offline models aren't always going to do well online... (see slides) Online - real-time metrics. Cost per prediction! The prediction profiling and tuning stuff is about bot identification. Pipeline AI - Continuous Model Training Identify and fix borderline predictions. Hotdog - not hotdog. Use crowdflower to label the data - then relabel along the classification's edges. Shift traffic to winning model using AI Bandit Algorithms. \"Once we drain this experiment of its value... we can stop this experiment.\" Shift traffic to minimum \"Cloud Cost\" Google Cloud vs Amazon Web Services Shift to amazon when the cloud instances are cheaper. Shift back and forth. He made fun of microsoft azure but plugged their kubernetes support. NVIDIA GPU Half-Precision Support All about Volta V100 (2017) - AMD - tensor cores / Google TPUs Pascal P100 (2016) FP32 = Full Precision FP16 = Half Precision Half good for approximate deep learning use cases Fit two FP16s into FP32 GPU cores for 2x throughput!! Thunk to 32 bit Nvidia: P100, M40, K40 - all tested for whatever reason AMD? - GPU CUDA Programming Barbaric, fun. Must know hardware. Probably hate your life. Optimized for same instruction, multiple thread. Do not like if-statement. Like half the cores go unused. Independent thread scheduling - finally CUDA Streams Tensorflow uses this heavily goal is to saturate cpus Check out Batch Normalization Almost always use batch normalization - except rarely you should never use batch normalization Technique from 2015 gradient descent don't want the network to learn the order the data is showing up first part of pipeline is shuffle normalize per batch normalize per layer each mini batch may have wildly different distributions Dropout sniff connections in your network prevent overfitting ensemble different neural architectures randomly, 50% sniff these things, purposely cripple it figure out ways to distort things they are trying to block out (spaces, numbers) more difficult for the network, better the final network was this guy something or other - his friend https://github.com/yaroslavvb/stuff DON'T USE FEED_DICT feed_dict Requires Python<->C++ Serialization Dataset API what happened to dataframe? it's gone i guess? tensorflow went right to dataset api Tensorflow Debugger - mouse from a terminal it's crazy, only Google... ALWAYS START WITH estimator AND experiment APIs These come from Google trying to productionize tensorflow, probably successfully. See the slide, has the above title!!!!!!!! Skip all the early demos you see, they are old and crusty. These simplify model building. flexible parameter tuning enable rapid model experiments Estimator API See the slides. Train-to-Serve Design Create custom or use a canned Estimator Hides session, graph layers, Chief:Worker Supervisor:Worker getting away from master but not improving their language... just changing it... Canned Estimators See the slides, 60% use prebuilt, 40% roll their own estimator Commonly used estimators Pre tested and pre tuned Multi-headed inference: Single-Objective Estimator vs Multi-Objective Estimator Get two answers (objectives out of one estimator or something). Hparams - Hyper parameter tuning Do a big grid search, a parameter as a range. Layers API exists Use kubernetes or mesos Good cluster organizer for working on this stuff... JIT Compiler - and visualizing Need to do a Python Context Manager with device as... whatever to use JIT. Historically: Spark & Project Tungsten would take your code and create your plan into an optimized one and then to a physical plan. Built on XLA - accelerated linear algebra framework. Goals reduce memory Movement reduce overhead of multiple function calls AOT Compiler - Standalone, Ahead-Of-Time (AOT) Compiler For super tiny devices... pass in your graph. Build up DAGs of operations in spark and tensorflow. tfcompile - point to input for graph and output for graph built on XLA framework creates functions with feeds (inputs) and fetches (outputs) figures out what everything... .so files, what bare minimum is necessary creates binary down to 600k - this is how we fit in the apple app store or not. shrink, shrink, tons of slides, freeze for production request batch tuning At the end of the day the forward prop. is just matrix multiplies. See slides max_batch_size batc There's like 60 slides left !! Damn, lots of content.","title":"Sfpython Tensorflow 8Hr Condensed 20171108"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#installing-deploying-using-tensorflow-in-python","text":"Speaker: Chris Fregley, Pipeline.ai (former Netflix, Databricks, kickstarted Spark.) https://github.com/PipelineAI/pipeline/ Zero respect for Python until he found Scientific Python. PySpark not his favorite, rather use Scala for Spark, originally a Java guy Slides available on meetup: slides Great GPU notebooks and examples This guy is such a salesman. He used port 6969 because of port colissions. Clever.","title":"Installing, Deploying, Using Tensorflow in Python"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#notes-from-meetup-site","text":"Main talk (~30 mins + Q&A) Optimizing, Profiling, and Deploying High-Performance Spark ML and TensorFlow AI Models in Production with GPUs Using the latest advancements from TensorFlow including the Accelerated Linear Algebra (XLA) Framework, JIT/AOT Compiler, and Graph Transform Tool, I\u2019ll demonstrate how to optimize, profile, and deploy TensorFlow Models - and the TensorFlow Runtime - in GPU-based production environment. This talk is 100% demo based on open source tools and completely reproducible through Docker on your own GPU cluster. Bio Chris Fregly is Founder and Research Engineer at PipelineAI, a Streaming Machine Learning and Artificial Intelligence Startup based in San Francisco. He is also an Apache Spark Contributor, a Netflix Open Source Committer, founder of the Global Advanced Spark and TensorFlow Meetup, author of the O\u2019Reilly Training and Video Series titled, \"High-Performance TensorFlow in Production.\" Previously, Chris was a Distributed Systems Engineer at Netflix, a Data Solutions Engineer at Databricks, and a Founding Member and Principal Engineer at the IBM Spark Technology Center in San Francisco.","title":"Notes from meetup site"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#tensorflow","text":"Mostly in C. Neural networks never want to go to production always want to be retrained want someone else to do the last 20%","title":"Tensorflow!"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#pipelineai","text":"A framework to get your models into solution. Something about data pipelines!","title":"Pipeline.ai"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#today-tensorflow-tf-condensed-talk-8-hour-into-30-minutes","text":"Optimize and Deploy TF models to production. Nice to have a working knowledge of TF. GPU heavy talk.","title":"Today - TensorFlow (TF) - Condensed talk: 8 hour into 30 minutes"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#content-breakdown","text":"50% training optimizations(GPUs, Training Pipeline, JIT) 50% prediction optimizations (AOT Compile, TF Serving) Why heavy focus on 'model prediction' vs 'just training'? Training - boring and batch! Prediction - exciting and real time!","title":"Content Breakdown"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#agenda-see-the-slides","text":"Biggest thing is telling data scientists that they can deploy from their jupyter notebook in a controlled manner. Ability to push it out & roll it back.","title":"Agenda - see the slides"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#docker-package-model-and-runtime-as-one","text":"Docker for mac - opened up a ton of use cases! no surprises in production deploy and tune model + runtime together same local, dev, production env Production always a bit different than development before this. A bunch of virtualbox cruft. Did he consider vagrant? I think docker just blows vagrant away for developers, removes tons of devops.","title":"DOCKER - Package model and runtime as one"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#tune-model-runtime-together-see-slides","text":"","title":"Tune Model + Runtime together! (see slides!)"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#offline-models-arent-always-going-to-do-well-online-see-slides","text":"Online - real-time metrics. Cost per prediction! The prediction profiling and tuning stuff is about bot identification.","title":"Offline models aren't always going to do well online... (see slides)"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#pipeline-ai-continuous-model-training","text":"Identify and fix borderline predictions. Hotdog - not hotdog. Use crowdflower to label the data - then relabel along the classification's edges. Shift traffic to winning model using AI Bandit Algorithms. \"Once we drain this experiment of its value... we can stop this experiment.\"","title":"Pipeline AI - Continuous Model Training"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#shift-traffic-to-minimum-cloud-cost","text":"Google Cloud vs Amazon Web Services Shift to amazon when the cloud instances are cheaper. Shift back and forth. He made fun of microsoft azure but plugged their kubernetes support.","title":"Shift traffic to minimum \"Cloud Cost\""},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#nvidia-gpu-half-precision-support","text":"All about Volta V100 (2017) - AMD - tensor cores / Google TPUs Pascal P100 (2016) FP32 = Full Precision FP16 = Half Precision Half good for approximate deep learning use cases Fit two FP16s into FP32 GPU cores for 2x throughput!! Thunk to 32 bit Nvidia: P100, M40, K40 - all tested for whatever reason","title":"NVIDIA GPU Half-Precision Support"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#amd-gpu-cuda-programming","text":"Barbaric, fun. Must know hardware. Probably hate your life. Optimized for same instruction, multiple thread. Do not like if-statement. Like half the cores go unused. Independent thread scheduling - finally CUDA Streams Tensorflow uses this heavily goal is to saturate cpus","title":"AMD? - GPU CUDA Programming"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#check-out-batch-normalization","text":"Almost always use batch normalization - except rarely you should never use batch normalization Technique from 2015 gradient descent don't want the network to learn the order the data is showing up first part of pipeline is shuffle normalize per batch normalize per layer each mini batch may have wildly different distributions","title":"Check out Batch Normalization"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#dropout","text":"sniff connections in your network prevent overfitting ensemble different neural architectures randomly, 50% sniff these things, purposely cripple it figure out ways to distort things they are trying to block out (spaces, numbers) more difficult for the network, better the final network was","title":"Dropout"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#this-guy-something-or-other-his-friend","text":"https://github.com/yaroslavvb/stuff","title":"this guy something or other - his friend"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#dont-use-feed_dict","text":"feed_dict Requires Python<->C++ Serialization Dataset API what happened to dataframe? it's gone i guess? tensorflow went right to dataset api","title":"DON'T USE FEED_DICT"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#tensorflow-debugger-mouse-from-a-terminal-its-crazy-only-google","text":"","title":"Tensorflow Debugger - mouse from a terminal it's crazy, only Google..."},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#always-start-with-estimator-and-experiment-apis","text":"These come from Google trying to productionize tensorflow, probably successfully. See the slide, has the above title!!!!!!!! Skip all the early demos you see, they are old and crusty. These simplify model building. flexible parameter tuning enable rapid model experiments","title":"ALWAYS START WITH estimator AND experiment APIs"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#estimator-api","text":"See the slides. Train-to-Serve Design Create custom or use a canned Estimator Hides session, graph layers, Chief:Worker Supervisor:Worker getting away from master but not improving their language... just changing it...","title":"Estimator API"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#canned-estimators","text":"See the slides, 60% use prebuilt, 40% roll their own estimator Commonly used estimators Pre tested and pre tuned","title":"Canned Estimators"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#multi-headed-inference-single-objective-estimator-vs-multi-objective-estimator","text":"Get two answers (objectives out of one estimator or something).","title":"Multi-headed inference: Single-Objective Estimator vs Multi-Objective Estimator"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#hparams-hyper-parameter-tuning","text":"Do a big grid search, a parameter as a range.","title":"Hparams - Hyper parameter tuning"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#layers-api-exists","text":"","title":"Layers API exists"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#use-kubernetes-or-mesos","text":"Good cluster organizer for working on this stuff...","title":"Use kubernetes or mesos"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#jit-compiler-and-visualizing","text":"Need to do a Python Context Manager with device as... whatever to use JIT. Historically: Spark & Project Tungsten would take your code and create your plan into an optimized one and then to a physical plan. Built on XLA - accelerated linear algebra framework. Goals reduce memory Movement reduce overhead of multiple function calls","title":"JIT Compiler - and visualizing"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#aot-compiler-standalone-ahead-of-time-aot-compiler","text":"For super tiny devices... pass in your graph. Build up DAGs of operations in spark and tensorflow. tfcompile - point to input for graph and output for graph built on XLA framework creates functions with feeds (inputs) and fetches (outputs) figures out what everything... .so files, what bare minimum is necessary creates binary down to 600k - this is how we fit in the apple app store or not. shrink, shrink, tons of slides, freeze for production","title":"AOT Compiler - Standalone, Ahead-Of-Time (AOT) Compiler"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#request-batch-tuning","text":"At the end of the day the forward prop. is just matrix multiplies. See slides max_batch_size batc","title":"request batch tuning"},{"location":"docs/talks/SFPython_tensorflow-8hr-condensed-20171108/#theres-like-60-slides-left-damn-lots-of-content","text":"","title":"There's like 60 slides left !! Damn, lots of content."},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/","text":"Gym & Keras @ SFPython Speaker: Adam Fletcher - adam@gyroscope.cc Using Python To Create SNES STreetFighter II AIs Environment (SNES9x) - BizHawk - Environment (Gym) - Agent (Keras-RL) Python Libraries: Gym from OpenAI, Keras-RL for training the agent Gym Gives you an environment for machine learning - what you are operating on. Functions: step, reset Observation Space For Street Fighter is the timer, health, position of character. The observation space they chose is based on what a human could see. You get to choose how big your observation space would be. Stepping ?? Action space - if it gets too big it becomes too hard to do good learning I think they just decided you can only press one button and one direction at the same time. A human typically does not press right and left at the same time, so it is not part of our action space. Rewards Function Hardest part of all of this. Tons of naive approaches - did you win? Damage received vs damage done. Settled on delta in my health vs opponents health, then maximize that gap. Agent (Keras-RL) Great abstraction for reinforcement learning. Prebuilt agents. Random agent - chooses something from the action space and tries it, does not care about observation. How do you know if your stuff is working? Compare it against the random one. Also has logging and testing for you which is nice. Forward Pass it an observation and say what should I do? Backwards It says 'here are the results' - learn from it! Controller Code wrote to pass all that data back and forth. Python3 Socket server with threads - it just worked with the threaded mixin! Passed json back and forth over a tcp socket. Imagine a state machine that simulated the emulator in your AI code. Also with multiple controllers, agents could play each other. Python socketserver io 450fps on a cloud server. Lua ip 60fps, lua sqlite io 120fps Does it work? After 300 games, it worked! They ran a final tournament every game. M. Bison is OP and the AI always wins. So he got banned. Sagat won the 2nd tournament. Python in AI/ML Python made things super fast!! Gym Tensorflow SciPy Keras One example, when both had very low health, they would back away from each other!! So they could not see an advantage from fighting when they could not get a big delta in opponent's health versus theirs. The AI is way better than a human millisecond reaction time way more training can be done, period","title":"Sfpython Train Streetfighter Gym Keras 20171108"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#gym-keras-sfpython","text":"Speaker: Adam Fletcher - adam@gyroscope.cc","title":"Gym & Keras @ SFPython"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#using-python-to-create-snes-streetfighter-ii-ais","text":"Environment (SNES9x) - BizHawk - Environment (Gym) - Agent (Keras-RL) Python Libraries: Gym from OpenAI, Keras-RL for training the agent","title":"Using Python To Create SNES STreetFighter II AIs"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#gym","text":"Gives you an environment for machine learning - what you are operating on. Functions: step, reset","title":"Gym"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#observation-space","text":"For Street Fighter is the timer, health, position of character. The observation space they chose is based on what a human could see. You get to choose how big your observation space would be.","title":"Observation Space"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#stepping","text":"??","title":"Stepping"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#action-space-if-it-gets-too-big-it-becomes-too-hard-to-do-good-learning","text":"I think they just decided you can only press one button and one direction at the same time. A human typically does not press right and left at the same time, so it is not part of our action space.","title":"Action space - if it gets too big it becomes too hard to do good learning"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#rewards-function","text":"Hardest part of all of this. Tons of naive approaches - did you win? Damage received vs damage done. Settled on delta in my health vs opponents health, then maximize that gap.","title":"Rewards Function"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#agent-keras-rl","text":"Great abstraction for reinforcement learning. Prebuilt agents. Random agent - chooses something from the action space and tries it, does not care about observation. How do you know if your stuff is working? Compare it against the random one. Also has logging and testing for you which is nice.","title":"Agent (Keras-RL)"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#forward","text":"Pass it an observation and say what should I do?","title":"Forward"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#backwards","text":"It says 'here are the results' - learn from it!","title":"Backwards"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#controller","text":"Code wrote to pass all that data back and forth. Python3 Socket server with threads - it just worked with the threaded mixin! Passed json back and forth over a tcp socket. Imagine a state machine that simulated the emulator in your AI code. Also with multiple controllers, agents could play each other. Python socketserver io 450fps on a cloud server. Lua ip 60fps, lua sqlite io 120fps","title":"Controller"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#does-it-work","text":"After 300 games, it worked! They ran a final tournament every game. M. Bison is OP and the AI always wins. So he got banned. Sagat won the 2nd tournament.","title":"Does it work?"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#python-in-aiml","text":"Python made things super fast!! Gym Tensorflow SciPy Keras","title":"Python in AI/ML"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#one-example-when-both-had-very-low-health-they-would-back-away-from-each-other","text":"So they could not see an advantage from fighting when they could not get a big delta in opponent's health versus theirs.","title":"One example, when both had very low health, they would back away from each other!!"},{"location":"docs/talks/SFPython_train-streetfighter-gym-keras-20171108/#the-ai-is-way-better-than-a-human","text":"millisecond reaction time way more training can be done, period","title":"The AI is way better than a human"},{"location":"docs/talks/SFPython_unicode_20170614/","text":"Unicode! Python 3! Speaker: Lukasz Langa Is unicode important? Yes! Plane ticket unicode errors can stop you from flying... How does Python decode a file when you import a module? Python2 imports as ascii by default. Python3 imports as unicode by default. Python reads the encoding you give and additionally has a filesystem encoding it uses but he did not cover details of this. What is text? Words! Communication. On bytes and unicode Programs that assume you can open a plain text file without encoding are broken. A character is not a byte, it is a unicode codepoint. And it can have a long name and you can even use that name in python. A codepoint cannot go on a drive. A code point is a platonic ideal, an abstract theoretical concept. A code point specifies what character you mean, for example U+0142 , in python \\u1402 . In Python 2, the string type tries to be byte too which isn't truly possible. In python 3, bytes is just bytes. Text Transmission Transmitting text is challenging! UTF-16 UTF-16 had to prefix the string with a byte order mark. Must be right, must be there... not likely! Null bytes in the middle of your string! How do we align the bytes in the string? Not all characters fit in UTF-16 UTF-8 Tries to be ascii compatible. First seven bits are ascii, after that we do 2,3,4 bytes. Simple algorithm: `if this is a special byte, i expect 1-3 continuation bytes after it. This must be how we know where the codepoint ends at variable length... >>> len(u'frog'.encode(\"utf-8\") ?? >>> len(u'a'.encode(\"utf-16\") 4 >>> len(u'4'.encode(\"utf-16\") 4 Real Purpose for Unicode... emojis?? Unicode is that thick book with each codepoint. UTF-8 is the encoding!! Unprecedented growth in the standard... We can't fit all the characters in 4 bytes. Solution: two pseudocode unicode characters to produce one - 8 bytes... good for now. Basic multilingual plane. 65536 characters. After this we use two pseudocode. Python3 does this for you. Is this for UTF-16 or UTF-8? You can encode codepoints in many ways, but codepoints do not have any way to write them into a file. Not all encodings can encode all characters. Code points are stored by encoding into bytes. UnicodeEncodeError - current encoding doesn't support all the codepoints you are trying to encode to bytes You can only read unicode back correctly if you know what codepoints was used to encode the bytes How does Python3 make things better? Python2 does not have full unicode support - does not have the full multilingual plane or something. >>> len(u'a') 1 >>> len(u'f') 1 A Single Character - Python 2 does (doesn't?) work well with all but the first one. BMP code point (base multilingual plane) U-Dxxxx surrogate pair grapheme cluster sorting element (example dzs in Hungarian) Grapheme Cluster -- wtf!! Use the library unicodedata to combine these grapheme clusters... somehow... unicodedata.normalize('NFS', u'\\u00c7') unicodedata.normalize('NFS', u'\\u00c7').encode('utf8') Tips! Using bytes for text is heading for a bug! Python3 reused str for unicode text In Python3 bytes means bytes When reading data just do b.decode('utf-8') When writing data back, just do b.encode('utf-8) Avoid using str() and bytes() without an encoding to convert between types. In some languages, uppercase and lowercase may not do the same things, so you can't just go back and forth. Python doesn't reliably do this!! Python2: narrow build of python - no wide character processing, raise weird inaccurate exceptions... Not common anymore Text segmenting, regular expression, right-to-left text Literary characters: en-dash, em-dash, separators, etc. Using bytes for text handling is a bug. Decode Early, Encode Late. Paraphrased: Your data should exist as codepoints for as long as possible","title":"Sfpython Unicode 20170614"},{"location":"docs/talks/SFPython_unicode_20170614/#unicode","text":"Python 3! Speaker: Lukasz Langa","title":"Unicode!"},{"location":"docs/talks/SFPython_unicode_20170614/#is-unicode-important","text":"Yes! Plane ticket unicode errors can stop you from flying...","title":"Is unicode important?"},{"location":"docs/talks/SFPython_unicode_20170614/#how-does-python-decode-a-file-when-you-import-a-module","text":"Python2 imports as ascii by default. Python3 imports as unicode by default. Python reads the encoding you give and additionally has a filesystem encoding it uses but he did not cover details of this.","title":"How does Python decode a file when you import a module?"},{"location":"docs/talks/SFPython_unicode_20170614/#what-is-text","text":"Words! Communication.","title":"What is text?"},{"location":"docs/talks/SFPython_unicode_20170614/#on-bytes-and-unicode","text":"Programs that assume you can open a plain text file without encoding are broken. A character is not a byte, it is a unicode codepoint. And it can have a long name and you can even use that name in python. A codepoint cannot go on a drive. A code point is a platonic ideal, an abstract theoretical concept. A code point specifies what character you mean, for example U+0142 , in python \\u1402 . In Python 2, the string type tries to be byte too which isn't truly possible. In python 3, bytes is just bytes.","title":"On bytes and unicode"},{"location":"docs/talks/SFPython_unicode_20170614/#text-transmission","text":"Transmitting text is challenging!","title":"Text Transmission"},{"location":"docs/talks/SFPython_unicode_20170614/#utf-16","text":"UTF-16 had to prefix the string with a byte order mark. Must be right, must be there... not likely! Null bytes in the middle of your string! How do we align the bytes in the string? Not all characters fit in UTF-16","title":"UTF-16"},{"location":"docs/talks/SFPython_unicode_20170614/#utf-8","text":"Tries to be ascii compatible. First seven bits are ascii, after that we do 2,3,4 bytes. Simple algorithm: `if this is a special byte, i expect 1-3 continuation bytes after it. This must be how we know where the codepoint ends at variable length... >>> len(u'frog'.encode(\"utf-8\") ?? >>> len(u'a'.encode(\"utf-16\") 4 >>> len(u'4'.encode(\"utf-16\") 4","title":"UTF-8"},{"location":"docs/talks/SFPython_unicode_20170614/#real-purpose-for-unicode-emojis","text":"Unicode is that thick book with each codepoint. UTF-8 is the encoding!! Unprecedented growth in the standard... We can't fit all the characters in 4 bytes. Solution: two pseudocode unicode characters to produce one - 8 bytes... good for now. Basic multilingual plane. 65536 characters. After this we use two pseudocode. Python3 does this for you. Is this for UTF-16 or UTF-8? You can encode codepoints in many ways, but codepoints do not have any way to write them into a file. Not all encodings can encode all characters. Code points are stored by encoding into bytes. UnicodeEncodeError - current encoding doesn't support all the codepoints you are trying to encode to bytes You can only read unicode back correctly if you know what codepoints was used to encode the bytes","title":"Real Purpose for Unicode... emojis??"},{"location":"docs/talks/SFPython_unicode_20170614/#how-does-python3-make-things-better","text":"Python2 does not have full unicode support - does not have the full multilingual plane or something. >>> len(u'a') 1 >>> len(u'f') 1 A Single Character - Python 2 does (doesn't?) work well with all but the first one. BMP code point (base multilingual plane) U-Dxxxx surrogate pair grapheme cluster sorting element (example dzs in Hungarian)","title":"How does Python3 make things better?"},{"location":"docs/talks/SFPython_unicode_20170614/#grapheme-cluster-wtf","text":"Use the library unicodedata to combine these grapheme clusters... somehow... unicodedata.normalize('NFS', u'\\u00c7') unicodedata.normalize('NFS', u'\\u00c7').encode('utf8')","title":"Grapheme Cluster -- wtf!!"},{"location":"docs/talks/SFPython_unicode_20170614/#tips","text":"Using bytes for text is heading for a bug! Python3 reused str for unicode text In Python3 bytes means bytes When reading data just do b.decode('utf-8') When writing data back, just do b.encode('utf-8) Avoid using str() and bytes() without an encoding to convert between types. In some languages, uppercase and lowercase may not do the same things, so you can't just go back and forth. Python doesn't reliably do this!! Python2: narrow build of python - no wide character processing, raise weird inaccurate exceptions... Not common anymore Text segmenting, regular expression, right-to-left text Literary characters: en-dash, em-dash, separators, etc. Using bytes for text handling is a bug. Decode Early, Encode Late. Paraphrased: Your data should exist as codepoints for as long as possible","title":"Tips!"},{"location":"docs/talks/airflow-kubernetes-wepay/","text":"Airflow on Kubernetes at WePay Speaker: William @ WePay Where: WePay @ Redwood City When: 2018.04.11 \"Tell them what you are going to tell them, tell them, and tell them what you told them.\" \"I now refer to dags as dags, but I swore that we should change the culture and call them workflows and now I am calling them dags. But we should call them workflows.\" - William trent: it sounds like they version their dags somehow... Question: Are you versioning your DAGs? No we are using git describe so counting up version from a parent. Max: Use Apache Arrow to store serialized data, then use xcom_push and pull to send & retrieve the data. Don't store too much serialized data in xcom stuff. Max: Backfill is so common, you might consider setting up a whole backflow framework. (Trent: maybe just run a whole scheduler with separate dags that have backfill enabled with a different pool of workers...) Max: If you are doing local surgeries or magic on your data, you probably want to keep that in the DAG and use conditionals for what the date is to determine what to do, that way someone running a regular DAG backfill isn't going to blow away your surgery. Max: We would build a dag framework for backfilling that would build a custom dag for a particular date range and manage that, then programmatically manage date ranges. Then managing those backfill datasets into production db as atomic operations. Initial (non k8s) deployment Airflow under supervisord (scheduler and webserver on same box) Manually ssh & pip install Cron job every 2 minutes to git pull and update the dags not a good approach to anything... sorry... couple layers of review... one person reviews the commit for a few minutes and says \"sure (implied ok whatever)\" Issues Everyone running on the same airflow No isolation (resources, dependencies) Deploys are monolithic Scalability Limited Availability Cowboy Culture: ssh to box and run commands: We had pets not cattle (snowflakes) Configuration nginx sidecar airflow scheduler and webser still in the same pod cloudsql elk kubernetes still running under supervisor no more cron job to git pull DAGs, moved to situation where manually push endpoint on pod to get new dags (pull tarball artifact), not terribly interesting Benefits control deployment easily deployed: cattle DAG deployment isolation / security scalable (multiple airflows per team) docker secrets KubernetesExecutor / KubernetesOperator (K8SOperator) Very excited to do this. We use the localexecutor with kubernetes pods so we don't need celery.","title":"Airflow Kubernetes Wepay"},{"location":"docs/talks/airflow-kubernetes-wepay/#airflow-on-kubernetes-at-wepay","text":"Speaker: William @ WePay Where: WePay @ Redwood City When: 2018.04.11 \"Tell them what you are going to tell them, tell them, and tell them what you told them.\" \"I now refer to dags as dags, but I swore that we should change the culture and call them workflows and now I am calling them dags. But we should call them workflows.\" - William trent: it sounds like they version their dags somehow... Question: Are you versioning your DAGs? No we are using git describe so counting up version from a parent. Max: Use Apache Arrow to store serialized data, then use xcom_push and pull to send & retrieve the data. Don't store too much serialized data in xcom stuff. Max: Backfill is so common, you might consider setting up a whole backflow framework. (Trent: maybe just run a whole scheduler with separate dags that have backfill enabled with a different pool of workers...) Max: If you are doing local surgeries or magic on your data, you probably want to keep that in the DAG and use conditionals for what the date is to determine what to do, that way someone running a regular DAG backfill isn't going to blow away your surgery. Max: We would build a dag framework for backfilling that would build a custom dag for a particular date range and manage that, then programmatically manage date ranges. Then managing those backfill datasets into production db as atomic operations.","title":"Airflow on Kubernetes at WePay"},{"location":"docs/talks/airflow-kubernetes-wepay/#initial-non-k8s-deployment","text":"Airflow under supervisord (scheduler and webserver on same box) Manually ssh & pip install Cron job every 2 minutes to git pull and update the dags not a good approach to anything... sorry... couple layers of review... one person reviews the commit for a few minutes and says \"sure (implied ok whatever)\"","title":"Initial (non k8s) deployment"},{"location":"docs/talks/airflow-kubernetes-wepay/#issues","text":"Everyone running on the same airflow No isolation (resources, dependencies) Deploys are monolithic Scalability Limited Availability Cowboy Culture: ssh to box and run commands: We had pets not cattle (snowflakes)","title":"Issues"},{"location":"docs/talks/airflow-kubernetes-wepay/#configuration","text":"nginx sidecar airflow scheduler and webser still in the same pod cloudsql elk kubernetes still running under supervisor no more cron job to git pull DAGs, moved to situation where manually push endpoint on pod to get new dags (pull tarball artifact), not terribly interesting","title":"Configuration"},{"location":"docs/talks/airflow-kubernetes-wepay/#benefits","text":"control deployment easily deployed: cattle DAG deployment isolation / security scalable (multiple airflows per team) docker secrets","title":"Benefits"},{"location":"docs/talks/airflow-kubernetes-wepay/#kubernetesexecutor-kubernetesoperator-k8soperator","text":"Very excited to do this. We use the localexecutor with kubernetes pods so we don't need celery.","title":"KubernetesExecutor / KubernetesOperator (K8SOperator)"},{"location":"docs/talks/airflow-on-googlecloud/","text":"Running Airflow inside Google Cloud Platform A lot of this was somewhat advertisement for GCP wrapped in Airflow. Could be useful for someone if they are already in this platform and want to hack some. It seems nice. Speaker: Trevor Edwards @ Google Location: WePay Redwood City Date: 2018.04.11 My notes on this will be sparse and focused on things I don't already know. Max chimes in - yes only one airflow scheduler running! Questions (at the end) Someone says that Google is planning to release Airflow as a managed service. The speaker would not comment on that. How much would it cost? Maybe on the order of $100 a month to clone this architecture. Not publicly cloneable yet. Tools KubernetesEngine Redis for Celery Airflow Webserver on Google App Engine Google Cloud Storage for DAGs and logs Securing your Airflow Server How to distribute DAGs and Plugins quickly? Many people use git workflows, we decided to use Google Cloud Storage. Sidecar container rsyncs DAGs/Plugins every 5 seconds. You would need to change how often the scheduler pulls dags to every 1 minute. Scaling out Airflow Webserver Scaling the scheduler single process: no horizontal scaling GKE - scale things up Scaling out Airflow Worker GKE Node pool with autoscaling can detect a worker at 99% and add another to the pool Stackdriver Logging & Monitoring - GKE out of the box...","title":"Airflow On Googlecloud"},{"location":"docs/talks/airflow-on-googlecloud/#running-airflow-inside-google-cloud-platform","text":"A lot of this was somewhat advertisement for GCP wrapped in Airflow. Could be useful for someone if they are already in this platform and want to hack some. It seems nice. Speaker: Trevor Edwards @ Google Location: WePay Redwood City Date: 2018.04.11 My notes on this will be sparse and focused on things I don't already know. Max chimes in - yes only one airflow scheduler running!","title":"Running Airflow inside Google Cloud Platform"},{"location":"docs/talks/airflow-on-googlecloud/#questions-at-the-end","text":"Someone says that Google is planning to release Airflow as a managed service. The speaker would not comment on that. How much would it cost? Maybe on the order of $100 a month to clone this architecture. Not publicly cloneable yet.","title":"Questions (at the end)"},{"location":"docs/talks/airflow-on-googlecloud/#tools","text":"KubernetesEngine Redis for Celery Airflow Webserver on Google App Engine Google Cloud Storage for DAGs and logs","title":"Tools"},{"location":"docs/talks/airflow-on-googlecloud/#securing-your-airflow-server","text":"","title":"Securing your Airflow Server"},{"location":"docs/talks/airflow-on-googlecloud/#how-to-distribute-dags-and-plugins-quickly","text":"Many people use git workflows, we decided to use Google Cloud Storage. Sidecar container rsyncs DAGs/Plugins every 5 seconds. You would need to change how often the scheduler pulls dags to every 1 minute.","title":"How to distribute DAGs and Plugins quickly?"},{"location":"docs/talks/airflow-on-googlecloud/#scaling-out-airflow-webserver","text":"","title":"Scaling out Airflow Webserver"},{"location":"docs/talks/airflow-on-googlecloud/#scaling-the-scheduler","text":"single process: no horizontal scaling GKE - scale things up","title":"Scaling the scheduler"},{"location":"docs/talks/airflow-on-googlecloud/#scaling-out-airflow-worker","text":"GKE Node pool with autoscaling can detect a worker at 99% and add another to the pool","title":"Scaling out Airflow Worker"},{"location":"docs/talks/airflow-on-googlecloud/#stackdriver-logging-monitoring-gke-out-of-the-box","text":"","title":"Stackdriver Logging & Monitoring - GKE out of the box..."},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/","text":"Operating Data Pipeline with Airflow Speaker: Ananth Packkildurai @ Slack (chat app) Date: 2018.04.11 Location: WePay Notes 4 Types of Executors - Max freestyles at the end Max says - most people should start using KubernetesExecutor when it comes, which is soon. Max says - LocalExecutor isn't for production, but it at some point has been deemed OK for production. At some point you will go out and get the biggest machine you will get and it won't work. This includes the new KubernetesExecutor . LocalExecutor - Python MultiProcessing Queue of the size you specify say you want to run 125 slots in your multiprocessing queue runs as part of the scheduler process or runs in the process as backfill if the scheduler fails, it would lose contact with the queue CeleryExecutor - Simple-ish abstraction for running remote tasks use redis or rabbitmq broker put the message in the queue that says 'please worker pick up the task locally' as many workers and queues as you want, workers watch queues and look at messages workers run messages if they have them original intent was a yarn executor, but it was hard to do because yarn is a resource negotiator, so it didn't make a lot of sense, hacky not good containerization support for yarn KubernetesExecutor: Daniel at Bloomberg is contributing this - open PR in the process of being merged, all the code is there They are using it in production at bloomberg airbnb looking to use it in production use kubernetes API, no local celery in kubernetes... actually use kubernetes... scheduler in a pod in or out of kubernetes airflow containerization was an afterthought but should have been first maybe in hindsight (heh whoops which one is the third?) Maybe DaskExector... Slack 10 data engineers 1000 employees 6M users 1 in 2 per week access data warehouse (trent: what?) 600,000 events per second at peak 500+ tables 240+ active DAGs 5400+ tables per day 68 contributors We have 68 contributors engaging in airflow or building data pipelines despite having 10 data engineers. Democratizing data access. Agenda Airflow Infrastructure Scale Airflow Executor Pipeline Operations Alerting and Monitoring Airflow Infrastructure Local Executor Tarball code deployment Continuous deployment with Jenkins Flake8, yapf & pytest airflow.sh shell utility to ensure consistent development environment for all the users. Scale Airflow Executor Airflwo Multi Retryable Sensors local executor launches new interpreter per task, which takes significant resources. but we can do multiple external tasks in a single interpreter... he put the code up but i didn't really get to read all of it, maybe its online Pipeline Operations Airflow Fallacies the upstream task success is reliable the task remain static after the success state the DAG structure is static people update or delete the dag the data quality is not part of a task life cycle definitely a complaint, based on system workflow MARIO - global dag operator (cli tool) $ ./mario --help do stuff like clear downstream , export a graphml represenation of downstream tons of other diagnostic stuff... Data Quality Checker - dqcheck Need lots of stuff if you're running 240+ dags, no easy way to visually look and see if some dag's task is in some particular state easily... (trent: lots of ways to do this automatically, they do it automatically)_ from slack.airflow.data_quality import DQCheck do stuff like check if the row count is > 0 Hive partition sensor operator delete_dag - if a dag is not active in the dagbag, clean up after it (delete all tables related to dag) DAG Policy Validator test_external_tasks - check if external tasks point to valid DAGs and tasks. test_circular_dependencies - check if tasks have circular dependencies across DAGs. test_priority_weight - check that production tasks do not depend on lower priority task test_on_failure - require that highpriority DAGs have an on-failure alert. just basically make sure you get notifications for that set of dags on failure... what's the test just read the dag or import it and check its python attrs? seems like it would be good to sandbox this too, maybe overwrite the send list after importing it and send it to a different set of people... test_sla - require that high-priority DAGs have an SLA test_sla_timing - SLA timing should make sense. No job should depend on a tas kthat has an equal or longer SLA than it does.... test_has_retry_and_success_callbacks - Require an on-success_callback for tasks with an on_retry_callback. test_require_dq_for_prod - require sq check for all the high priority tasks. Alerting and Monitoring OnCall Alert Callback I took a photo of OncallAlertCallback for on call engineers. Alerting should be reliable Alerts should be actionable","title":"Airflow Operating Data Pipeline With Airflow"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#operating-data-pipeline-with-airflow","text":"Speaker: Ananth Packkildurai @ Slack (chat app) Date: 2018.04.11 Location: WePay","title":"Operating Data Pipeline with Airflow"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#notes","text":"","title":"Notes"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#4-types-of-executors-max-freestyles-at-the-end","text":"Max says - most people should start using KubernetesExecutor when it comes, which is soon. Max says - LocalExecutor isn't for production, but it at some point has been deemed OK for production. At some point you will go out and get the biggest machine you will get and it won't work. This includes the new KubernetesExecutor . LocalExecutor - Python MultiProcessing Queue of the size you specify say you want to run 125 slots in your multiprocessing queue runs as part of the scheduler process or runs in the process as backfill if the scheduler fails, it would lose contact with the queue CeleryExecutor - Simple-ish abstraction for running remote tasks use redis or rabbitmq broker put the message in the queue that says 'please worker pick up the task locally' as many workers and queues as you want, workers watch queues and look at messages workers run messages if they have them original intent was a yarn executor, but it was hard to do because yarn is a resource negotiator, so it didn't make a lot of sense, hacky not good containerization support for yarn KubernetesExecutor: Daniel at Bloomberg is contributing this - open PR in the process of being merged, all the code is there They are using it in production at bloomberg airbnb looking to use it in production use kubernetes API, no local celery in kubernetes... actually use kubernetes... scheduler in a pod in or out of kubernetes airflow containerization was an afterthought but should have been first maybe in hindsight (heh whoops which one is the third?) Maybe DaskExector...","title":"4 Types of Executors - Max freestyles at the end"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#slack","text":"10 data engineers 1000 employees 6M users 1 in 2 per week access data warehouse (trent: what?) 600,000 events per second at peak 500+ tables 240+ active DAGs 5400+ tables per day 68 contributors We have 68 contributors engaging in airflow or building data pipelines despite having 10 data engineers. Democratizing data access.","title":"Slack"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#agenda","text":"Airflow Infrastructure Scale Airflow Executor Pipeline Operations Alerting and Monitoring","title":"Agenda"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#airflow-infrastructure","text":"Local Executor Tarball code deployment Continuous deployment with Jenkins Flake8, yapf & pytest airflow.sh shell utility to ensure consistent development environment for all the users.","title":"Airflow Infrastructure"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#scale-airflow-executor","text":"Airflwo Multi Retryable Sensors local executor launches new interpreter per task, which takes significant resources. but we can do multiple external tasks in a single interpreter... he put the code up but i didn't really get to read all of it, maybe its online","title":"Scale Airflow Executor"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#pipeline-operations","text":"","title":"Pipeline Operations"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#airflow-fallacies","text":"the upstream task success is reliable the task remain static after the success state the DAG structure is static people update or delete the dag the data quality is not part of a task life cycle definitely a complaint, based on system workflow","title":"Airflow Fallacies"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#mario-global-dag-operator-cli-tool","text":"$ ./mario --help do stuff like clear downstream , export a graphml represenation of downstream tons of other diagnostic stuff...","title":"MARIO - global dag operator (cli tool)"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#data-quality-checker-dqcheck","text":"Need lots of stuff if you're running 240+ dags, no easy way to visually look and see if some dag's task is in some particular state easily... (trent: lots of ways to do this automatically, they do it automatically)_ from slack.airflow.data_quality import DQCheck do stuff like check if the row count is > 0 Hive partition sensor operator delete_dag - if a dag is not active in the dagbag, clean up after it (delete all tables related to dag)","title":"Data Quality Checker - dqcheck"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#dag-policy-validator","text":"test_external_tasks - check if external tasks point to valid DAGs and tasks. test_circular_dependencies - check if tasks have circular dependencies across DAGs. test_priority_weight - check that production tasks do not depend on lower priority task test_on_failure - require that highpriority DAGs have an on-failure alert. just basically make sure you get notifications for that set of dags on failure... what's the test just read the dag or import it and check its python attrs? seems like it would be good to sandbox this too, maybe overwrite the send list after importing it and send it to a different set of people... test_sla - require that high-priority DAGs have an SLA test_sla_timing - SLA timing should make sense. No job should depend on a tas kthat has an equal or longer SLA than it does.... test_has_retry_and_success_callbacks - Require an on-success_callback for tasks with an on_retry_callback. test_require_dq_for_prod - require sq check for all the high priority tasks.","title":"DAG Policy Validator"},{"location":"docs/talks/airflow-operating-data-pipeline-with-airflow/#alerting-and-monitoring","text":"OnCall Alert Callback I took a photo of OncallAlertCallback for on call engineers. Alerting should be reliable Alerts should be actionable","title":"Alerting and Monitoring"},{"location":"docs/talks/cypherpunks_writecode_20161112/","text":"Cypherpunks Write Code - Protecting Online Privacy Speaker: Steve Date: 2016.11.12 Basis: Cypherpunks Manifesto - Eric Hughes (2003) See quote from this about writing software. Motivation Complacency Available Applications Whatsapp owned by facebook, hard to know about tampering Signal 2/3 of Tor users have left since 2013 fall 2-3 million out of billions of internet users PRISM Partners and what they collect (Apple, Facebook, Google, etc.) One Possible Solution Cypherpunks writing code Regular hackathons with ~2 official projects for each Designers Contributing More useable software (than historic cypherpunk work) Project Requirements Idea Open Source Project must include well defined tasks for us to do Github issues, openness in allowing anyone to contribute to issues Project representative should be in attendance (virtual or physical) Represenative helps guide efforts and also attend event Represeentative should: motivate why their projec is important and which features are a priority Shout Out: DESIGN == GOOD Lets appreciate good design! Snowden / Greenwald could barely figure out PGP Project maintainer said 'screw that guy he should have figured it out or gone away' Project Discussion: Which projects deserve our attention? Online Discussion Wiki Dymaxion: Please Stop Writing Messaging Apps Contains 24 other ideas for Cypherpunk apps","title":"Cypherpunks Writecode 20161112"},{"location":"docs/talks/cypherpunks_writecode_20161112/#cypherpunks-write-code-protecting-online-privacy","text":"Speaker: Steve Date: 2016.11.12","title":"Cypherpunks Write Code - Protecting Online Privacy"},{"location":"docs/talks/cypherpunks_writecode_20161112/#basis-cypherpunks-manifesto-eric-hughes-2003","text":"See quote from this about writing software.","title":"Basis: Cypherpunks Manifesto - Eric Hughes (2003)"},{"location":"docs/talks/cypherpunks_writecode_20161112/#motivation","text":"Complacency Available Applications Whatsapp owned by facebook, hard to know about tampering Signal 2/3 of Tor users have left since 2013 fall 2-3 million out of billions of internet users PRISM Partners and what they collect (Apple, Facebook, Google, etc.)","title":"Motivation"},{"location":"docs/talks/cypherpunks_writecode_20161112/#one-possible-solution","text":"Cypherpunks writing code Regular hackathons with ~2 official projects for each Designers Contributing More useable software (than historic cypherpunk work)","title":"One Possible Solution"},{"location":"docs/talks/cypherpunks_writecode_20161112/#project-requirements-idea","text":"Open Source Project must include well defined tasks for us to do Github issues, openness in allowing anyone to contribute to issues Project representative should be in attendance (virtual or physical) Represenative helps guide efforts and also attend event Represeentative should: motivate why their projec is important and which features are a priority","title":"Project Requirements Idea"},{"location":"docs/talks/cypherpunks_writecode_20161112/#shout-out-design-good","text":"Lets appreciate good design! Snowden / Greenwald could barely figure out PGP Project maintainer said 'screw that guy he should have figured it out or gone away'","title":"Shout Out: DESIGN == GOOD"},{"location":"docs/talks/cypherpunks_writecode_20161112/#project-discussion-which-projects-deserve-our-attention","text":"Online Discussion Wiki Dymaxion: Please Stop Writing Messaging Apps Contains 24 other ideas for Cypherpunk apps","title":"Project Discussion: Which projects deserve our attention?"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/","text":"NFC Tool From Scratch Speaker: shanhaoqi@360.cn Location: Defcon 25 (2017) NFC & ISO14443A What is UniProxy Master and Slave Quick Demo I Put the credit card in a UniProxy Master 1. Put the 2 UniProxy Hardware 1 Cellphone 1 NFC enabled credit card Who we are: Unicorn Team Insternal security research team of Qihoo 360, founded in 2014. Focus on wireless hardware hacking and defense Low cost GPS Spoofing Defcon 23 LTE Redirection acttac - Defcon 24 Attack on powerline communication, Blackhat USA 2016 Ghost Telephonist - Defcon 25 Serial hacking tools developed: HackID, HackID Pro, SafeRFID - more I missed NFC and ISO14443A We will focus on ISO14443A for the demo. NFC 13.56MHz low-cost does not require power well developed and deployed ISO14443A In china: passport, bank card, etc. more info in slides Goals ID Card - could be exploited Access forbidden area Target banking systems How Targeting Protocols Proxmark III (The best RFID hardware) Supports many protocols, powerful, cannot hack credit cards ChameleonMini Targeting Data: NFCProxy , NFCGate What is UniProxy Can be extended for ISO14443 protocol and 15693 standard. PN7462AU based NFC relay/proxy device Supports ISO14443A Protocol Can be extended for other protocols that the chipset supports Targeting QuickPass, VisaPay, EMV, Unipay credit cards Reader emulator: Master card emulator: Slave ... see photos Why PN7462AU NXP Chip 20 MHz Cortext-M0 Core 24L01 Chip coordinates between the master and slave Their company has not open sourced the firmware, they didn't let him I think they write some bits on the iblock and a lot of the iblock is boiler plate? Lee says the nfc transaction times out easily and this might keep the connection warm? If there is an R block the card emulator will process itself Speaker says: Principle Described is \"VERY SIMPLE\" Issues Tons of issues occurred in development. First byte of UID is in the firmware, will always be \"zero eight\"?? Did not find a way to modify? Waiting/Wakeup time Real issue when developing a proxy tool NFC has no power, uses power from the reader Gets response from the reader and turns off Must modify wakeup time - see code (to ensure the NFC is powered?) I/S/R - Block data We do not need to transfer all data Just transfer I block data, need to directly transfer S/R block data Read the ISO carefully for more info Power supply can cause corruption of the chipset Don't to do any tricks = follow the regular procedure This is very sensitive The proxy card is used to make the purchase when the master card can be read There is a video of the proxy card in action on my phone. You should use a GuardBunny sleeve on your NFC cards to block RF... Summary Read Protocol Well Better not develop without official support Improvements - future Improve transmission range to 100 meters Currently 50? 15? meters Target security ID cards, HID iClass, Chinese ID Self-compatibility Currently only ISO14443A want to adapt to 15693 and let it know which it is using How?","title":"Defcon25 Nfc Tool From Scratch 20170730"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#nfc-tool-from-scratch","text":"Speaker: shanhaoqi@360.cn Location: Defcon 25 (2017) NFC & ISO14443A What is UniProxy Master and Slave","title":"NFC Tool From Scratch"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#quick-demo-i","text":"Put the credit card in a UniProxy Master 1. Put the 2 UniProxy Hardware 1 Cellphone 1 NFC enabled credit card","title":"Quick Demo I"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#who-we-are-unicorn-team","text":"Insternal security research team of Qihoo 360, founded in 2014. Focus on wireless hardware hacking and defense Low cost GPS Spoofing Defcon 23 LTE Redirection acttac - Defcon 24 Attack on powerline communication, Blackhat USA 2016 Ghost Telephonist - Defcon 25 Serial hacking tools developed: HackID, HackID Pro, SafeRFID - more I missed","title":"Who we are: Unicorn Team"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#nfc-and-iso14443a","text":"We will focus on ISO14443A for the demo. NFC 13.56MHz low-cost does not require power well developed and deployed ISO14443A In china: passport, bank card, etc. more info in slides","title":"NFC and ISO14443A"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#goals","text":"ID Card - could be exploited Access forbidden area Target banking systems","title":"Goals"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#how","text":"Targeting Protocols Proxmark III (The best RFID hardware) Supports many protocols, powerful, cannot hack credit cards ChameleonMini Targeting Data: NFCProxy , NFCGate","title":"How"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#what-is-uniproxy","text":"Can be extended for ISO14443 protocol and 15693 standard. PN7462AU based NFC relay/proxy device Supports ISO14443A Protocol Can be extended for other protocols that the chipset supports Targeting QuickPass, VisaPay, EMV, Unipay credit cards Reader emulator: Master card emulator: Slave ... see photos","title":"What is UniProxy"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#why-pn7462au","text":"NXP Chip 20 MHz Cortext-M0 Core","title":"Why PN7462AU"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#24l01-chip-coordinates-between-the-master-and-slave","text":"","title":"24L01 Chip coordinates between the master and slave"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#their-company-has-not-open-sourced-the-firmware-they-didnt-let-him","text":"","title":"Their company has not open sourced the firmware, they didn't let him"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#i-think-they-write-some-bits-on-the-iblock-and-a-lot-of-the-iblock-is-boiler-plate","text":"","title":"I think they write some bits on the iblock and a lot of the iblock is boiler plate?"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#lee-says-the-nfc-transaction-times-out-easily-and-this-might-keep-the-connection-warm","text":"","title":"Lee says the nfc transaction times out easily and this might keep the connection warm?"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#if-there-is-an-r-block-the-card-emulator-will-process-itself","text":"","title":"If there is an R block the card emulator will process itself"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#speaker-says-principle-described-is-very-simple","text":"","title":"Speaker says: Principle Described is \"VERY SIMPLE\""},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#issues","text":"Tons of issues occurred in development. First byte of UID is in the firmware, will always be \"zero eight\"?? Did not find a way to modify? Waiting/Wakeup time Real issue when developing a proxy tool NFC has no power, uses power from the reader Gets response from the reader and turns off Must modify wakeup time - see code (to ensure the NFC is powered?) I/S/R - Block data We do not need to transfer all data Just transfer I block data, need to directly transfer S/R block data Read the ISO carefully for more info Power supply can cause corruption of the chipset Don't to do any tricks = follow the regular procedure This is very sensitive","title":"Issues"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#the-proxy-card-is-used-to-make-the-purchase-when-the-master-card-can-be-read","text":"There is a video of the proxy card in action on my phone.","title":"The proxy card is used to make the purchase when the master card can be read"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#you-should-use-a-guardbunny-sleeve-on-your-nfc-cards-to-block-rf","text":"","title":"You should use a GuardBunny sleeve on your NFC cards to block RF..."},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#summary","text":"Read Protocol Well Better not develop without official support","title":"Summary"},{"location":"docs/talks/defcon25-nfc-tool-from-scratch-20170730/#improvements-future","text":"Improve transmission range to 100 meters Currently 50? 15? meters Target security ID cards, HID iClass, Chinese ID Self-compatibility Currently only ISO14443A want to adapt to 15693 and let it know which it is using How?","title":"Improvements - future"},{"location":"docs/talks/littlefish_ian_gotts_20170210/","text":"Little Fish Meetup - Ian Gotts Speaker: Ian Gotts Talk: The Business of Consulting Note: Ian wrote about 10 books and his first one still gets him business today. Three R's of Ian's talk: R Remember Reveal Winning Work As a consultant you are winning work or performing work and it's hard to balance. Winning Rewarding, Profitable Work Rewarding - The work takes you where you want to go Profitable - You can do it Credibility Starts with not having a gmail account Starts with a real business card Starts with a decent name Example: xenogonyx Most of your work comes from word of mouth If your client's can't remember, they can't tell anyone about you Example: IG Partners Says you are consulting and your clients can remember it Ian's first impression is: Linkedin 3-5 page website home, services, about, contact us, resources Some orgs put aol.com, hotmail.com, yahoo.com accounts right in the bin People that have no technical competency? AOL still makes 917 million a year on dialup accounts, residual income Build a brand Acronym: \"Every Consultant Is Awesome\" These are in order. 1, most important.... 4. least important Expectation Commonality Intent Ability Expectation - Most important. Are you the consultant they expected? Are you wearing a suit if that is expected Dress and behave for your audience Business card like they would expect \"It's about Clues, not Views\" You are 'disappointed about the superbowl' but they won... oops Political views, technology views let them explain how it all works Commonality - Do you have anything in common with them? Kids the same age, musical instrument interest, anything Intent - Are you there to help them get it done? Are you just there for the day rate Are you there to make it work If you can't help them, don't go!! Ability - Can you do the job? Clearly it's important, but it's below the other three Differentiation Price is the main difference between two consultants that can do the work. How do you differentiate your work? Why is one person worth $1000 a day and another $1200 a day. Anecdote, he worked with a client and they did a perfect job on a $150MM job and all the client could remember a year later was day rate. Intent: What are you passionate about? What are you good at? Skills? Web Designer: There are so many of those. Align yourself with a product. Example: Be a salesforce consultant, or something. You don't know when a client wants to start You don't know when they want to make a business change Need to spend time getting up to speed on a product It's like the trains are going by and you gotta jump on the one It's great to do something you love, but is it profitable? Is money your primary measure? If so, you have to adapt. Are you going to build a 40-person business marketing to startups? Salesforce's limiting factor for growth is business consultants Probably true for microsoft azure, google cloud, aws, rackspace How do you make your project URGENT? \"You cannot make a consulting project start by sheer will\" Tying yourself to a product coaching based on their business pipeline Compliance is another fantastic URGENT incentive. \"If we don't do this by december, the FDA fines us 100MM dollars\" We have to start now, just write the check. What about IP to differentiate yourself? A business methodology - for example Accenture's 'Lightning' Method I have methodologies out there right now Methodology used in your \"sales cycle\" Way you perform the business cycle with your client Example: lawyer - Methodology can be used to convince a client \"Trust me we have the metrics and here are our standard templates\" How much does your methodology increase your day rate and win rate? Profitability Make enough to spend your life the way you want to spend it A sold consulting firm in silicon valley makes 1 to 1.5 times revenue An investor wants to make 5x revenue on that form The three things discussed below: Fix bigger problems Project Management Minimize Bench Time Annuity Revenue Streams Sorry, but it's REALLY HARD to build a consultancy to the second stage. Up to 5 is pretty good. The next stopping point after 3-4 people is twenty. The bit between 5-20 is REALLY HARD. Consulting business with 30+ starts to get momentum: marketing, salespeople Your consultants need something to do between assignments, they aren't just going to develop the business, it isn't what they do. First way is to charge more. How? FIRST THING: Fix bigger problems Application developers - awesome - ukraine Configure systems - above applications Management consultants - above configure (doing business and development) Run big projects - above management (12 weeks, name the day rate) 3500 a day, 12 weeks, bring in the team, i pay you on top of the team Ian: i ROI for that client was 95,000 a day Ian's biggest project, never got that again Running workshops, business consulting Run big programs - above projects Writing books - MARKETING GOLD DUST \"Common Approach, Common Results\" - gets them business today, it was his first one You can't throw a book away, you can give it away but never get rid of it Way better than white papers, they've got a spine! jogging vs marathon Secret is 80 pages - then you have a spine, and it's a book. people love books How do you turn those blogs into something? Project Management - best way to increase your day rate Scope is the intersection of: time, cost, quality If you don't have it down at the beginning you've lost the project If you can't get the scope agreed, leave the project!! This is a real lesson he learned in accenture. Scope, timeframe, skillset => all comes back to scope \"What's the case study going to be like when we get you up on stage?\" Get them focused on how they deliver the project, so you can focus on how they deliver the project Minimize Bench Time Get people around you so you can work together and rely on each other and make sure no one has any bench time Work for clients who don't screw you over all the time ShipClients - glassdoor for clients, was renamed to \"RateClient\" For independent consultants to rate clients on 3 things Too long to get project started Scope creep Pay you correctly and on time http://clientsfromhell.net Annuity Revenue Streams Writing books isn't it! You don't make any money out of books, they up your day rate. Books also cost very little. Silicon Valley is all aboute Annuity Revenue Stream. Could you license some IP? Could other consultants use your metholodogy? Can you get 20% of a revenue stream? Could you build a support service? Be the best you can be Always be yourself, unless you can be Batman. Then always be batman. Always test the boundary of how much you can charge. Day rate: $500, $800, $1000, $2000 - always move it up!! Notes He says technical skills are worthless, amazing eastern european developers cost $20 an hour, so it's all about access to technical skills. Innovative websites don't work. It's why all product websites and carts are the same. Questions How do you be awesome if you don't have a resume that says you worked for the big 5? Ian: It may not be who you worked for but who your clients have been in the past. Example: The best part of the book is the back cover with quotes by people that love them. Everyone reads the back -- this book must be incredible. How do you get a client to use your name? A bunch of clients will, some people won't put it through their legal people. Find people who will bat for you. If it's a book, it can further their career. Find win-wins. What about partnerships? Equity partnerships - you need to be super careful. Getting a divorce is hard. Are you both aligned? Are you both putting the same amount of time on it? \"We'll work it out in the end?\" Very difficult to unwind if it goes wrong. How much do you spend on marketing when do you stop? As a small business, SEO, facebook marketing, etc. are a huge waste. BEST: Networking events where you can work together to figure out how to get clients. BEST: Write a book or a paper, they hang around forever! BEST: Linkedin relationships, article worth reading on linkedin Make sure to get writing out there. What are you really good at? Where are they? Salesforce: all on twitter. Why? No one knows!! 430 salesforce user groups - marin, sf, etc. Every other week. half consultants and half clients!! there's an ecosystem remember: salesforce growth blocker is consultants. How do I move up a tier on project size? Confidence to bid for bigger projects Being there already - take a bigger project with a current client. Who else do you need around? Project management skills? The people who are winning those projects, how are they doing it? What does their website look like? How do I get $2000 a day? Answer: put less on your resume Behave how people are operating at that level behave","title":"Littlefish Ian Gotts 20170210"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#little-fish-meetup-ian-gotts","text":"Speaker: Ian Gotts Talk: The Business of Consulting Note: Ian wrote about 10 books and his first one still gets him business today. Three R's of Ian's talk: R Remember Reveal","title":"Little Fish Meetup - Ian Gotts"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#winning-work","text":"As a consultant you are winning work or performing work and it's hard to balance.","title":"Winning Work"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#winning-rewarding-profitable-work","text":"Rewarding - The work takes you where you want to go Profitable - You can do it","title":"Winning Rewarding, Profitable Work"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#credibility","text":"Starts with not having a gmail account Starts with a real business card Starts with a decent name Example: xenogonyx Most of your work comes from word of mouth If your client's can't remember, they can't tell anyone about you Example: IG Partners Says you are consulting and your clients can remember it","title":"Credibility"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#ians-first-impression-is","text":"Linkedin 3-5 page website home, services, about, contact us, resources Some orgs put aol.com, hotmail.com, yahoo.com accounts right in the bin People that have no technical competency? AOL still makes 917 million a year on dialup accounts, residual income","title":"Ian's first impression is:"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#build-a-brand","text":"Acronym: \"Every Consultant Is Awesome\" These are in order. 1, most important.... 4. least important Expectation Commonality Intent Ability Expectation - Most important. Are you the consultant they expected? Are you wearing a suit if that is expected Dress and behave for your audience Business card like they would expect \"It's about Clues, not Views\" You are 'disappointed about the superbowl' but they won... oops Political views, technology views let them explain how it all works Commonality - Do you have anything in common with them? Kids the same age, musical instrument interest, anything Intent - Are you there to help them get it done? Are you just there for the day rate Are you there to make it work If you can't help them, don't go!! Ability - Can you do the job? Clearly it's important, but it's below the other three","title":"Build a brand"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#differentiation","text":"Price is the main difference between two consultants that can do the work. How do you differentiate your work? Why is one person worth $1000 a day and another $1200 a day. Anecdote, he worked with a client and they did a perfect job on a $150MM job and all the client could remember a year later was day rate. Intent: What are you passionate about? What are you good at? Skills? Web Designer: There are so many of those. Align yourself with a product. Example: Be a salesforce consultant, or something. You don't know when a client wants to start You don't know when they want to make a business change Need to spend time getting up to speed on a product It's like the trains are going by and you gotta jump on the one It's great to do something you love, but is it profitable? Is money your primary measure? If so, you have to adapt. Are you going to build a 40-person business marketing to startups? Salesforce's limiting factor for growth is business consultants Probably true for microsoft azure, google cloud, aws, rackspace How do you make your project URGENT? \"You cannot make a consulting project start by sheer will\" Tying yourself to a product coaching based on their business pipeline Compliance is another fantastic URGENT incentive. \"If we don't do this by december, the FDA fines us 100MM dollars\" We have to start now, just write the check. What about IP to differentiate yourself? A business methodology - for example Accenture's 'Lightning' Method I have methodologies out there right now Methodology used in your \"sales cycle\" Way you perform the business cycle with your client Example: lawyer - Methodology can be used to convince a client \"Trust me we have the metrics and here are our standard templates\" How much does your methodology increase your day rate and win rate?","title":"Differentiation"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#profitability","text":"Make enough to spend your life the way you want to spend it A sold consulting firm in silicon valley makes 1 to 1.5 times revenue An investor wants to make 5x revenue on that form","title":"Profitability"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#the-three-things-discussed-below","text":"Fix bigger problems Project Management Minimize Bench Time Annuity Revenue Streams Sorry, but it's REALLY HARD to build a consultancy to the second stage. Up to 5 is pretty good. The next stopping point after 3-4 people is twenty. The bit between 5-20 is REALLY HARD. Consulting business with 30+ starts to get momentum: marketing, salespeople Your consultants need something to do between assignments, they aren't just going to develop the business, it isn't what they do. First way is to charge more. How? FIRST THING: Fix bigger problems Application developers - awesome - ukraine Configure systems - above applications Management consultants - above configure (doing business and development) Run big projects - above management (12 weeks, name the day rate) 3500 a day, 12 weeks, bring in the team, i pay you on top of the team Ian: i ROI for that client was 95,000 a day Ian's biggest project, never got that again Running workshops, business consulting Run big programs - above projects Writing books - MARKETING GOLD DUST \"Common Approach, Common Results\" - gets them business today, it was his first one You can't throw a book away, you can give it away but never get rid of it Way better than white papers, they've got a spine! jogging vs marathon Secret is 80 pages - then you have a spine, and it's a book. people love books How do you turn those blogs into something? Project Management - best way to increase your day rate Scope is the intersection of: time, cost, quality If you don't have it down at the beginning you've lost the project If you can't get the scope agreed, leave the project!! This is a real lesson he learned in accenture. Scope, timeframe, skillset => all comes back to scope \"What's the case study going to be like when we get you up on stage?\" Get them focused on how they deliver the project, so you can focus on how they deliver the project Minimize Bench Time Get people around you so you can work together and rely on each other and make sure no one has any bench time Work for clients who don't screw you over all the time ShipClients - glassdoor for clients, was renamed to \"RateClient\" For independent consultants to rate clients on 3 things Too long to get project started Scope creep Pay you correctly and on time http://clientsfromhell.net Annuity Revenue Streams Writing books isn't it! You don't make any money out of books, they up your day rate. Books also cost very little. Silicon Valley is all aboute Annuity Revenue Stream. Could you license some IP? Could other consultants use your metholodogy? Can you get 20% of a revenue stream? Could you build a support service?","title":"The three things discussed below:"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#be-the-best-you-can-be","text":"Always be yourself, unless you can be Batman. Then always be batman. Always test the boundary of how much you can charge. Day rate: $500, $800, $1000, $2000 - always move it up!!","title":"Be the best you can be"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#notes","text":"He says technical skills are worthless, amazing eastern european developers cost $20 an hour, so it's all about access to technical skills. Innovative websites don't work. It's why all product websites and carts are the same.","title":"Notes"},{"location":"docs/talks/littlefish_ian_gotts_20170210/#questions","text":"How do you be awesome if you don't have a resume that says you worked for the big 5? Ian: It may not be who you worked for but who your clients have been in the past. Example: The best part of the book is the back cover with quotes by people that love them. Everyone reads the back -- this book must be incredible. How do you get a client to use your name? A bunch of clients will, some people won't put it through their legal people. Find people who will bat for you. If it's a book, it can further their career. Find win-wins. What about partnerships? Equity partnerships - you need to be super careful. Getting a divorce is hard. Are you both aligned? Are you both putting the same amount of time on it? \"We'll work it out in the end?\" Very difficult to unwind if it goes wrong. How much do you spend on marketing when do you stop? As a small business, SEO, facebook marketing, etc. are a huge waste. BEST: Networking events where you can work together to figure out how to get clients. BEST: Write a book or a paper, they hang around forever! BEST: Linkedin relationships, article worth reading on linkedin Make sure to get writing out there. What are you really good at? Where are they? Salesforce: all on twitter. Why? No one knows!! 430 salesforce user groups - marin, sf, etc. Every other week. half consultants and half clients!! there's an ecosystem remember: salesforce growth blocker is consultants. How do I move up a tier on project size? Confidence to bid for bigger projects Being there already - take a bigger project with a current client. Who else do you need around? Project management skills? The people who are winning those projects, how are they doing it? What does their website look like? How do I get $2000 a day? Answer: put less on your resume Behave how people are operating at that level behave","title":"Questions"},{"location":"docs/talks/pyclass_vector_packing_20161114/","text":"Vector Packing: An NP-Hard Problem Made Easy Speaker: Conor Frailey, https://github.com/conorfrailey Turnout: 12 people = 10 students, 1 speaker, and 1 of me. The Knapsack Problem - playing tetris for a living, sort of. Jupyter Notebook Presentation Online Technical Details of Problem: See instructor notes, the definitions are very detailed. Knapsacks are each identical in the context of the problem (volume, weight reqs.) Items have a volume and a weight Weight can be described for items as a percentage a knapsack. In this description, all knapsacks can contain (1,1) which means (100%, 100%) You want to use as few knapsacks as possible You group items by partition to find the solution cannot just brute force it, factorial combinations means takes TOO long e.g. 40 boxes means 40! tries which is not possible to brute force Notes partition (math) - distinct groups of your set bin packing is different - uses three linear dimensions What is NP-Hard Is P == NP? P means problems solvable in polynomial time If you can solve this in polynomial time you can solve almost anything in polynomial time If you can form a problem into a convex optimization problem , you are super happy space has to be convex it keeps on curving up, you want to find the minimum gradient descent is used in high dimensions to find the minimum pick a point and go towards zero if you have mixed integer program you can do a noncontiguous set of point you can't have a continuous number of cases of beef thus you can't use gradient descent on cases of beef list of MIP solvers in the notes MIP programs are super expensive so we can't use it today we can use online tool: Arc-flow VPSolver VPSolver has a docker image available on docker hub Hypergraph - a collection of distinct objects and a connection between two or more example: customer orders a subset of the products, a \"group\". Another customer orders a second subset, different group. They might overlap some products, or even be identical but different customer. solving with a hypergraph. use the first item as a reference, then start optimizing and reducing symmetry. Hit hotspots where employee has to go to more than one (too many) aisles. Other Examples 1. Vacationing on a short vacation , want to do as many things as pos sible - Each day has finite time - You can on ly walk so much a day - You can on ly spend so much money per day ( per diem ) 2. Data centers and their virtual machines 3. Refrigerated warehouses - Fixed height rack , movable height shelves inside racks - All pallets are standard , except height - Get the pallets onto the shelves References","title":"Pyclass Vector Packing 20161114"},{"location":"docs/talks/pyclass_vector_packing_20161114/#vector-packing-an-np-hard-problem-made-easy","text":"Speaker: Conor Frailey, https://github.com/conorfrailey Turnout: 12 people = 10 students, 1 speaker, and 1 of me. The Knapsack Problem - playing tetris for a living, sort of. Jupyter Notebook Presentation Online","title":"Vector Packing: An NP-Hard Problem Made Easy"},{"location":"docs/talks/pyclass_vector_packing_20161114/#technical-details-of-problem","text":"See instructor notes, the definitions are very detailed. Knapsacks are each identical in the context of the problem (volume, weight reqs.) Items have a volume and a weight Weight can be described for items as a percentage a knapsack. In this description, all knapsacks can contain (1,1) which means (100%, 100%) You want to use as few knapsacks as possible You group items by partition to find the solution cannot just brute force it, factorial combinations means takes TOO long e.g. 40 boxes means 40! tries which is not possible to brute force","title":"Technical Details of Problem:"},{"location":"docs/talks/pyclass_vector_packing_20161114/#notes","text":"partition (math) - distinct groups of your set bin packing is different - uses three linear dimensions What is NP-Hard Is P == NP? P means problems solvable in polynomial time If you can solve this in polynomial time you can solve almost anything in polynomial time If you can form a problem into a convex optimization problem , you are super happy space has to be convex it keeps on curving up, you want to find the minimum gradient descent is used in high dimensions to find the minimum pick a point and go towards zero if you have mixed integer program you can do a noncontiguous set of point you can't have a continuous number of cases of beef thus you can't use gradient descent on cases of beef list of MIP solvers in the notes MIP programs are super expensive so we can't use it today we can use online tool: Arc-flow VPSolver VPSolver has a docker image available on docker hub Hypergraph - a collection of distinct objects and a connection between two or more example: customer orders a subset of the products, a \"group\". Another customer orders a second subset, different group. They might overlap some products, or even be identical but different customer. solving with a hypergraph. use the first item as a reference, then start optimizing and reducing symmetry. Hit hotspots where employee has to go to more than one (too many) aisles.","title":"Notes"},{"location":"docs/talks/pyclass_vector_packing_20161114/#other-examples","text":"1. Vacationing on a short vacation , want to do as many things as pos sible - Each day has finite time - You can on ly walk so much a day - You can on ly spend so much money per day ( per diem ) 2. Data centers and their virtual machines 3. Refrigerated warehouses - Fixed height rack , movable height shelves inside racks - All pallets are standard , except height - Get the pallets onto the shelves","title":"Other Examples"},{"location":"docs/talks/pyclass_vector_packing_20161114/#references","text":"","title":"References"},{"location":"docs/talks/pycon2016_django_docdrivendev/","text":"Documentation Driven Development in the Django Project Using the django project as an example for great ddd. What's so good? * structured properly * clear and consistent within structure * covers just about everything * held to a high standard * ? * regarded as a process rather than a product Results: * Django is easier to adopt * Makes people better django programmers * lowers support burden * makes people faster Main point of his talk: Software is not the only thing that develops, grows, improves. Communities of programmers also develops, grows, improves. What does documentation mean for the development of communities and products? Writer keeps riffing on the same stuff. His words have depth but not immediately actionable.","title":"Pycon2016 Django Docdrivendev"},{"location":"docs/talks/pycon2016_django_docdrivendev/#documentation-driven-development-in-the-django-project","text":"Using the django project as an example for great ddd. What's so good? * structured properly * clear and consistent within structure * covers just about everything * held to a high standard * ? * regarded as a process rather than a product Results: * Django is easier to adopt * Makes people better django programmers * lowers support burden * makes people faster","title":"Documentation Driven Development in the Django Project"},{"location":"docs/talks/pycon2016_django_docdrivendev/#main-point-of-his-talk","text":"Software is not the only thing that develops, grows, improves. Communities of programmers also develops, grows, improves.","title":"Main point of his talk:"},{"location":"docs/talks/pycon2016_django_docdrivendev/#what-does-documentation-mean-for-the-development-of-communities-and-products","text":"","title":"What does documentation mean for the development of communities and products?"},{"location":"docs/talks/pycon2016_django_docdrivendev/#writer-keeps-riffing-on-the-same-stuff-his-words-have-depth-but-not-immediately-actionable","text":"","title":"Writer keeps riffing on the same stuff. His words have depth but not immediately actionable."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/","text":"Production Ready Flask App - Part I Notes from Miguel Grinberg's talk on making a production flask app. Speaker: Miguel Grinberg Event: PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link. 1. Move utility functions to utils.py (tag: v0.2) url_for, timestamp functions. 2. Refactor database models. (tag: v0.3) Avoid cyclic dependency of importing db from controller then importing model from models.py Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded \"from flack import db\". 3. Create an Application Package (tag: v0.4) - Use Flask-Script A newer option exists over Flask-Script but is not yet production ready. Flask-Script is available now: https://flask-script.readthedocs.io/en/latest/ See git diff v0.3 v0.4 between these two tags to understand necessary changes. 4. Refactoring API Authentication (tag: v0.5) - Moved auth stuff to auth.py. There were three auth functions finally imported. Again see git diff v0.4 v0.5 for details. 5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure. To get the overview, checkout this tag and manage.py. Look at file structure. Now we are in a django style construction. tests folder exists alongside flack folder. 6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py. Add a config.py. This is pretty hairy even in django. People solve configuration in different ways. I have a pretty good django dev.cfg/prod.cfg pattern that I would use here. 7. Create an API Blueprint - separate the api. Create: flack/api.py . Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py. 8. Create Stats package. See git diff v0.8 v0.9 9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app. Sometimes it is desirable to work with more than one application Best Example: Unit tests that need applications with different configurations. SPECIAL NOTE: Having app blueprints allows you to have a really elegant test setup and teardown. Howto get the Blueprint working (see git diff v0.9 v.10 for exact code) We need to get rid of app because it will exist outside the context of the controller. Now we can no longer reference app. We must refactor app.config and other references to app. That means no app.debug. To achieve this we can use a Blueprint. Use the current_app context variable to access application. Put application factory function in init .py, see create_app function here. To create an app you now call create_app, pass an application name, and get the app. SQLAlchemy needs the models in init .py because it introspects on the app. You can miss this and maybe the models get imported elsewhere but that is sloppy. 10. Creating an API Package (tag: v0.11) - Turn api.py into a package. This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users. tokens, messages, users become modules inside of the api package. Part II - Scaling Flask for Production. Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link. Scaling Web Servers Problem - one request at a time. Not great. Multiple Threads Limited use of multiple threads because of GIL. Not really great. Multiple processes Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy? Green threads / coroutines - asyncio, gevent, eventlet. Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function). Using Production Web Servers (tag: v0.12) gunicorn Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads. uwsgi nginx Written in C. Ideal for serving static files in production. You expose the static file in the nginx config. Bottlenecks: I/O Bound and CPU Bound I/O Bottlenecks Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous. CPU Bottlenecks Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous. Asynchronous HTTP Requests (tag: v0.13) Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it. Celery Workers (tag: v0.14) There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular. Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens. This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket) Streaming One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask Long polling client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated. WebSocket HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time. SocketIO written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides. Even more Socket.IO. We can now only use gevent or eventlet. See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary. Flask-SocketIO Miguel's project Pure python, translation of the Socket.IO node project for flask. Questions / Notes Flask has a Python profiler.","title":"Pycon2016 Grinberg Flaskprod"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#production-ready-flask-app-part-i","text":"Notes from Miguel Grinberg's talk on making a production flask app. Speaker: Miguel Grinberg Event: PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link.","title":"Production Ready Flask App - Part I"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#1-move-utility-functions-to-utilspy-tag-v02","text":"url_for, timestamp functions.","title":"1. Move utility functions to utils.py (tag: v0.2)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#2-refactor-database-models-tag-v03","text":"Avoid cyclic dependency of importing db from controller then importing model from models.py Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded \"from flack import db\".","title":"2. Refactor database models. (tag: v0.3)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#3-create-an-application-package-tag-v04-use-flask-script","text":"A newer option exists over Flask-Script but is not yet production ready. Flask-Script is available now: https://flask-script.readthedocs.io/en/latest/ See git diff v0.3 v0.4 between these two tags to understand necessary changes.","title":"3. Create an Application Package (tag: v0.4) - Use Flask-Script"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#4-refactoring-api-authentication-tag-v05-","text":"Moved auth stuff to auth.py. There were three auth functions finally imported. Again see git diff v0.4 v0.5 for details.","title":"4. Refactoring API Authentication (tag: v0.5) -"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#5-refactoring-tests-tag-v06-change-to-a-package-style-folder-structure","text":"To get the overview, checkout this tag and manage.py. Look at file structure. Now we are in a django style construction. tests folder exists alongside flack folder.","title":"5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#6-refactoring-configuration-tag-v07-add-a-configpy-next-to-managepy","text":"Add a config.py. This is pretty hairy even in django. People solve configuration in different ways. I have a pretty good django dev.cfg/prod.cfg pattern that I would use here.","title":"6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#7-create-an-api-blueprint-separate-the-api","text":"Create: flack/api.py . Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py.","title":"7. Create an API Blueprint - separate the api."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#8-create-stats-package","text":"See git diff v0.8 v0.9","title":"8. Create Stats package."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#9-using-an-application-factory-function-tag-v010-use-a-blueprint-for-app","text":"Sometimes it is desirable to work with more than one application Best Example: Unit tests that need applications with different configurations.","title":"9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#special-note","text":"Having app blueprints allows you to have a really elegant test setup and teardown.","title":"SPECIAL NOTE:"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#howto-get-the-blueprint-working-see-git-diff-v09-v10-for-exact-code","text":"We need to get rid of app because it will exist outside the context of the controller. Now we can no longer reference app. We must refactor app.config and other references to app. That means no app.debug. To achieve this we can use a Blueprint. Use the current_app context variable to access application. Put application factory function in init .py, see create_app function here. To create an app you now call create_app, pass an application name, and get the app. SQLAlchemy needs the models in init .py because it introspects on the app. You can miss this and maybe the models get imported elsewhere but that is sloppy.","title":"Howto get the Blueprint working (see git diff v0.9 v.10 for exact code)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#10-creating-an-api-package-tag-v011-turn-apipy-into-a-package","text":"This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users. tokens, messages, users become modules inside of the api package.","title":"10. Creating an API Package (tag: v0.11) - Turn api.py into a package."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#part-ii-scaling-flask-for-production","text":"Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link.","title":"Part II - Scaling Flask for Production."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#scaling-web-servers","text":"Problem - one request at a time. Not great.","title":"Scaling Web Servers"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#multiple-threads","text":"Limited use of multiple threads because of GIL. Not really great.","title":"Multiple Threads"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#multiple-processes","text":"Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy?","title":"Multiple processes"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#green-threads-coroutines-asyncio-gevent-eventlet","text":"Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).","title":"Green threads / coroutines - asyncio, gevent, eventlet."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#using-production-web-servers-tag-v012","text":"","title":"Using Production Web Servers (tag: v0.12)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#gunicorn","text":"Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads.","title":"gunicorn"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#uwsgi","text":"","title":"uwsgi"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#nginx","text":"Written in C. Ideal for serving static files in production. You expose the static file in the nginx config.","title":"nginx"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#bottlenecks-io-bound-and-cpu-bound","text":"","title":"Bottlenecks: I/O Bound and CPU Bound"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#io-bottlenecks","text":"Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous.","title":"I/O Bottlenecks"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#cpu-bottlenecks","text":"Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.","title":"CPU Bottlenecks"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#asynchronous-http-requests-tag-v013","text":"Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.","title":"Asynchronous HTTP Requests (tag: v0.13)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#celery-workers-tag-v014","text":"There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.","title":"Celery Workers (tag: v0.14)"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#websocket-tag-v015-clients-must-poll-to-stay-up-to-date-we-need-to-use-server-push-to-reduce-load-when-new-stuff-happens","text":"This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket)","title":"Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#streaming","text":"One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask","title":"Streaming"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#long-polling","text":"client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.","title":"Long polling"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#websocket","text":"HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.","title":"WebSocket"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#socketio","text":"written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides.","title":"SocketIO"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#even-more-socketio-we-can-now-only-use-gevent-or-eventlet","text":"See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.","title":"Even more Socket.IO. We can now only use gevent or eventlet."},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#flask-socketio","text":"Miguel's project Pure python, translation of the Socket.IO node project for flask.","title":"Flask-SocketIO"},{"location":"docs/talks/pycon2016_grinberg_flaskprod/#questions-notes","text":"Flask has a Python profiler.","title":"Questions / Notes"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/","text":"Laser Cutters and 3D Printers How to use Python to build stuff to be laser cut or 3d printed. Talk: https://github.com/vishnubob/pycon2016 Speaker: Giles Hall Additional Resources: https://github.com/vishnubob/pyscad https://github.com/vishnubob/rockit https://github.com/vishnubob/snowflake Laser Cutters Process Select material (wood, plastic, etc.) Size Build design (vector graphics allows scaling without losing fidelity eg svg) Determine which lines are cut Determine which lines are etched Lay out material on laser bed Upload your design and begin to cut. The individual processes above are defined by the particular laser cutter and its software. Can use PDF, EPS, etc. But preferred is SVG: Path is a great way to specify a zigzaggy line in your SVG. So how do we use Python to generate our SVG for our laser cut image? We'll cut 2D shapes and assemble them into a 3D shape. His cube is a really great sample of using one huge single cut to make six interlocking pieces. This cube was cut with wood and you can see the burns on the edges of the wood from the laser. I could easily modify this to build the cups I want to make for tea. Really just need to know the guts of the SVG path specification, the N commands and L commands that let you specify a complex set of line segments. Then we get more complex by etching onto the sides of the teacups. He uses fermat's spiral, but I could do anything or free draw something, or get a raster/pixelart off the web and convert to svg circles. Maybe skyrim mug 3D Printers Most common are fuse deposition models. Cut 3d object into 2d slices and build a model up. Extruders extrude plastic to do this. Uses XY plane for each layer, Z advances to the next 2D slice. Generate STL file Produce GCODE STL is very hard to generate by hand. Not great way to think about 3d designs (mesh of triangles). There must be a better way to design!! Most 3D modelling tools are expensive, difficult, or run in windows or all three. OpenSCAD -> * open source, * uses constructive solid geomoetry. Drinking glass can be constructed with two cylinders. 1. Describe outside surface. 2. Describe negative space inside, slightly smaller radius, slightly offset from bottom. # very easy to build a drinking glass, nested cylinders difference() { cylinder(r=20, h=80); translate([0,0,1]]) { cylinder(r=18, h=90); } } We can very easily generate OpenSCAD from Python using PythonSCAD! How about a Flower Pot? It's a cone but we call that a cylinder in scad with 2 different radiuses on each end. Lip at the top. A few different Python Libraries: PythonSCAD written by the Speaker. You can accomplish with the other alternative libraries but we use his here. \"\"\" PythonSCAD Sample of a flowerpot. \"\"\" class FlowerPot ( SCAD_Object ): radius_ratio = 0.6 # from flowerpots in his house collar_height_raidus = 0.2 height = inch2mm ( 2.5 ) thickness # ... # theres more but he moved on def scad ( self ): outer_pot = Cylinder ( r1 = self . bottom_radius , r2 = self . top_radius ) # ... # theres more but he moved on # this is all the code! Other things to check out in PythonSCAD Translate math from \"Modeling a Snow Flake....\" research document into Python. They used this to make snowflakes 3D printed. The math used a complex automata and was computationally expensive - done in the cloud. The program provides a raster of the automata cells and then is converted to SVG. Two SVGs are merged, one of the densest bands of automata another of the outline. Then sent to the 3D printer (laser cutter?).","title":"Pycon2016 Lasercutter 3Dprinter Python"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#laser-cutters-and-3d-printers","text":"How to use Python to build stuff to be laser cut or 3d printed. Talk: https://github.com/vishnubob/pycon2016 Speaker: Giles Hall","title":"Laser Cutters and 3D Printers"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#additional-resources","text":"https://github.com/vishnubob/pyscad https://github.com/vishnubob/rockit https://github.com/vishnubob/snowflake","title":"Additional Resources:"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#laser-cutters","text":"","title":"Laser Cutters"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#process","text":"Select material (wood, plastic, etc.) Size Build design (vector graphics allows scaling without losing fidelity eg svg) Determine which lines are cut Determine which lines are etched Lay out material on laser bed Upload your design and begin to cut. The individual processes above are defined by the particular laser cutter and its software. Can use PDF, EPS, etc. But preferred is SVG: Path is a great way to specify a zigzaggy line in your SVG.","title":"Process"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#so-how-do-we-use-python-to-generate-our-svg-for-our-laser-cut-image","text":"We'll cut 2D shapes and assemble them into a 3D shape. His cube is a really great sample of using one huge single cut to make six interlocking pieces. This cube was cut with wood and you can see the burns on the edges of the wood from the laser. I could easily modify this to build the cups I want to make for tea. Really just need to know the guts of the SVG path specification, the N commands and L commands that let you specify a complex set of line segments. Then we get more complex by etching onto the sides of the teacups. He uses fermat's spiral, but I could do anything or free draw something, or get a raster/pixelart off the web and convert to svg circles. Maybe skyrim mug","title":"So how do we use Python to generate our SVG for our laser cut image?"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#3d-printers","text":"Most common are fuse deposition models. Cut 3d object into 2d slices and build a model up. Extruders extrude plastic to do this. Uses XY plane for each layer, Z advances to the next 2D slice. Generate STL file Produce GCODE STL is very hard to generate by hand. Not great way to think about 3d designs (mesh of triangles).","title":"3D Printers"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#there-must-be-a-better-way-to-design","text":"Most 3D modelling tools are expensive, difficult, or run in windows or all three. OpenSCAD -> * open source, * uses constructive solid geomoetry. Drinking glass can be constructed with two cylinders. 1. Describe outside surface. 2. Describe negative space inside, slightly smaller radius, slightly offset from bottom. # very easy to build a drinking glass, nested cylinders difference() { cylinder(r=20, h=80); translate([0,0,1]]) { cylinder(r=18, h=90); } }","title":"There must be a better way to design!!"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#we-can-very-easily-generate-openscad-from-python-using-pythonscad","text":"How about a Flower Pot? It's a cone but we call that a cylinder in scad with 2 different radiuses on each end. Lip at the top. A few different Python Libraries: PythonSCAD written by the Speaker. You can accomplish with the other alternative libraries but we use his here. \"\"\" PythonSCAD Sample of a flowerpot. \"\"\" class FlowerPot ( SCAD_Object ): radius_ratio = 0.6 # from flowerpots in his house collar_height_raidus = 0.2 height = inch2mm ( 2.5 ) thickness # ... # theres more but he moved on def scad ( self ): outer_pot = Cylinder ( r1 = self . bottom_radius , r2 = self . top_radius ) # ... # theres more but he moved on # this is all the code!","title":"We can very easily generate OpenSCAD from Python using PythonSCAD!"},{"location":"docs/talks/pycon2016_lasercutter_3dprinter_python/#other-things-to-check-out-in-pythonscad","text":"Translate math from \"Modeling a Snow Flake....\" research document into Python. They used this to make snowflakes 3D printed. The math used a complex automata and was computationally expensive - done in the cloud. The program provides a raster of the automata cells and then is converted to SVG. Two SVGs are merged, one of the densest bands of automata another of the outline. Then sent to the 3D printer (laser cutter?).","title":"Other things to check out in PythonSCAD"},{"location":"docs/talks/pycon2016_sqlite_tricks/","text":"Why SQLite? Speaker: Dave Sawyer Talk: Pycon 2016 Monday May 30 - SQLite gotchas and gimmes. Talk URL: Search/Sort Efficiently transactions with rollback safe format handle large datasets. 32/64 bit agnostic little/big endian agnostic concurrency. Gotchas! Remember to commit your db changes (duh) => try/finally SQLite autocommits by default. Probably want to turn this off to control your commits. Close your cursor because writers have to wait for readers etc. Gimmees! SQLite has a built in context manager! Use with statement! python with connection: connection.execute(MY_SQLITE_STATEMENT, (data,)) ``` python even better, generate the cursor in the with context. with closing(self.connection.cursor()) as cursor: cursor.execute(MY_SQLITE_STATEMENT, (data,)) ``` See the code from the talk for his class. It's very compact and general. WAL mode - SQLite 3.7. Write Ahead Logging. Lets you read and write at the same time. It's like a delta and the writers write then the readers use the delta to read. sqlite3.version = python module version sqlite3.sqlite_version = gives sqlite installation version sqlite3 :memory: -- in-memory model and very fast obviously. No writes to disk. SQLite isolation levels: deferred, immediate, exclusive. Lets just implement deferred. The other two are easy and not totally necessary. Questions:","title":"Pycon2016 Sqlite Tricks"},{"location":"docs/talks/pycon2016_sqlite_tricks/#why-sqlite","text":"Speaker: Dave Sawyer Talk: Pycon 2016 Monday May 30 - SQLite gotchas and gimmes. Talk URL: Search/Sort Efficiently transactions with rollback safe format handle large datasets. 32/64 bit agnostic little/big endian agnostic concurrency.","title":"Why SQLite?"},{"location":"docs/talks/pycon2016_sqlite_tricks/#gotchas","text":"Remember to commit your db changes (duh) => try/finally SQLite autocommits by default. Probably want to turn this off to control your commits. Close your cursor because writers have to wait for readers etc.","title":"Gotchas!"},{"location":"docs/talks/pycon2016_sqlite_tricks/#gimmees","text":"SQLite has a built in context manager! Use with statement! python with connection: connection.execute(MY_SQLITE_STATEMENT, (data,)) ``` python","title":"Gimmees!"},{"location":"docs/talks/pycon2016_sqlite_tricks/#even-better-generate-the-cursor-in-the-with-context","text":"with closing(self.connection.cursor()) as cursor: cursor.execute(MY_SQLITE_STATEMENT, (data,)) ``` See the code from the talk for his class. It's very compact and general. WAL mode - SQLite 3.7. Write Ahead Logging. Lets you read and write at the same time. It's like a delta and the writers write then the readers use the delta to read. sqlite3.version = python module version sqlite3.sqlite_version = gives sqlite installation version sqlite3 :memory: -- in-memory model and very fast obviously. No writes to disk.","title":"even better, generate the cursor in the with context."},{"location":"docs/talks/pycon2016_sqlite_tricks/#sqlite-isolation-levels-deferred-immediate-exclusive","text":"Lets just implement deferred. The other two are easy and not totally necessary.","title":"SQLite isolation levels: deferred, immediate, exclusive."},{"location":"docs/talks/pycon2016_sqlite_tricks/#questions","text":"","title":"Questions:"},{"location":"docs/talks/pycon2016_typeannotations/","text":"Why use static typing? (Dropbox talk) Date: 2016-05-29 Talk: PyCon 2016 Who: Guido van Rossum et al, Dropbox Inc. Spreadsheet URL: At dropbox, 40% of time was used on reading/understanding code (2015 survey) Static typing helps understanding of code. Problem: Finding a type of an input can be impossible. Worst case: recursively hunt backwards in the codebase until you enumerate everything constructing your input. Massive search tree required. More complex problem: type can even vary, maybe a method is overloaded (eek). Computer science says this is undecidable. Another problem: Over time, expectations for the code change and comments that were true become lies. Now we have to go back to the original problem. \"Explicit is better than implicit.\" -> \"Checked is better than unchecked.\" Lets make our types explicit have a computer check our types. New Strategy: Make types explicit and checked. Write types at def and where not obvious. Run mypy to check types, routinely like your tests Read code, learning types i easy. A definition for \"static typing\" Static Typing - The expectation the author had for the piece of code when they were writing it. Using Type Hints in Python 2 (Static Typing) Simply use a comment. def function(a, b): # a: int, b: int => int Using Type Hints in Python 3 (Static Typing) Use mypy as a checker for type hints in python 3. History of static typing (Guido) Guido has been considering this over a decade. The technology really has come around in the last six months. 2004-2005 - Artima blog posts: https://www.artima.com/weblogs/viewpost.jsp?thread=85551 2006 - PEP 3107 Compromise, 'function annotations' https://www.python.org/dev/peps/pep-3107/ Type annotations do nothing but are introspectable. 2012 - Jukka also started working with this, stsarted mypy as an \"experimental python variant\" - statically typed python. Used angular brackets because other languages do it in this way. Guido convinced him to use pep3107 and square brackets so mypy is completely compatible with Python 2014 - Bob Ippolito - EuroPython Talk (see youtube) - \"What Can Python Learn from Haskell\" His 3rd idea was to use mypy b/c static typing. https://www.youtube.com/watch?v=pJOmlFf5Je4 Discussion about PEP484 started right after PyCon 2014. https://www.python.org/dev/peps/pep-0484/ PyCharm and Google's pytype project started adopting this standard. Everything is optional and gradual. You can have annotations in one place and none elsewhere. Python ignores annotations. Except when you set annotations","title":"Pycon2016 Typeannotations"},{"location":"docs/talks/pycon2016_typeannotations/#why-use-static-typing-dropbox-talk","text":"Date: 2016-05-29 Talk: PyCon 2016 Who: Guido van Rossum et al, Dropbox Inc. Spreadsheet URL: At dropbox, 40% of time was used on reading/understanding code (2015 survey) Static typing helps understanding of code.","title":"Why use static typing? (Dropbox talk)"},{"location":"docs/talks/pycon2016_typeannotations/#problem","text":"Finding a type of an input can be impossible. Worst case: recursively hunt backwards in the codebase until you enumerate everything constructing your input. Massive search tree required. More complex problem: type can even vary, maybe a method is overloaded (eek). Computer science says this is undecidable.","title":"Problem:"},{"location":"docs/talks/pycon2016_typeannotations/#another-problem","text":"Over time, expectations for the code change and comments that were true become lies. Now we have to go back to the original problem. \"Explicit is better than implicit.\" -> \"Checked is better than unchecked.\" Lets make our types explicit have a computer check our types.","title":"Another problem:"},{"location":"docs/talks/pycon2016_typeannotations/#new-strategy-make-types-explicit-and-checked","text":"Write types at def and where not obvious. Run mypy to check types, routinely like your tests Read code, learning types i easy.","title":"New Strategy: Make types explicit and checked."},{"location":"docs/talks/pycon2016_typeannotations/#a-definition-for-static-typing","text":"Static Typing - The expectation the author had for the piece of code when they were writing it.","title":"A definition for \"static typing\""},{"location":"docs/talks/pycon2016_typeannotations/#using-type-hints-in-python-2-static-typing","text":"Simply use a comment. def function(a, b): # a: int, b: int => int","title":"Using Type Hints in Python 2 (Static Typing)"},{"location":"docs/talks/pycon2016_typeannotations/#using-type-hints-in-python-3-static-typing","text":"Use mypy as a checker for type hints in python 3.","title":"Using Type Hints in Python 3 (Static Typing)"},{"location":"docs/talks/pycon2016_typeannotations/#history-of-static-typing-guido","text":"Guido has been considering this over a decade. The technology really has come around in the last six months.","title":"History of static typing (Guido)"},{"location":"docs/talks/pycon2016_typeannotations/#2004-2005-artima-blog-posts","text":"https://www.artima.com/weblogs/viewpost.jsp?thread=85551","title":"2004-2005 - Artima blog posts:"},{"location":"docs/talks/pycon2016_typeannotations/#2006-pep-3107-compromise-function-annotations","text":"https://www.python.org/dev/peps/pep-3107/ Type annotations do nothing but are introspectable.","title":"2006 - PEP 3107 Compromise, 'function annotations'"},{"location":"docs/talks/pycon2016_typeannotations/#2012-jukka-also-started-working-with-this-stsarted-mypy-as-an-experimental-python-variant-statically-typed-python","text":"Used angular brackets because other languages do it in this way. Guido convinced him to use pep3107 and square brackets so mypy is completely compatible with Python","title":"2012 - Jukka also started working with this, stsarted mypy as an \"experimental python variant\" - statically typed python."},{"location":"docs/talks/pycon2016_typeannotations/#2014-bob-ippolito-europython-talk-see-youtube-what-can-python-learn-from-haskell","text":"His 3rd idea was to use mypy b/c static typing. https://www.youtube.com/watch?v=pJOmlFf5Je4 Discussion about PEP484 started right after PyCon 2014. https://www.python.org/dev/peps/pep-0484/ PyCharm and Google's pytype project started adopting this standard.","title":"2014 - Bob Ippolito - EuroPython Talk (see youtube) - \"What Can Python Learn from Haskell\""},{"location":"docs/talks/pycon2016_typeannotations/#everything-is-optional-and-gradual","text":"You can have annotations in one place and none elsewhere. Python ignores annotations. Except when you set annotations","title":"Everything is optional and gradual."},{"location":"docs/talks/trigger-point-massage/","text":"Lacrosse Ball Myofascial Release Speaker: ? Date: 2019-09-10 typically 40-60 seconds for any body part 2 rounds if you have time quads, hamstrings, glutes, back, everything the second round you really rolling pin it around do this type of stuff before a workout to open up your fascia and allow muscles to work through greater range of motion and minimize injury relax as much as you can, if you tighten it up the ball is tougher to get in there do every single part of the muscle this is different than stretching, surrounding every muscle is fascia, also attaches muscle to skin and other muscles ball breaks things up in there, if you are cringing a lot drink a lot of water - \"releasing a bunch of toxins and broken up stagnant toxins into your bloodstream\" never have any alcohol before/after a massage we tend to do the same movements over and over, sitting, walking, whatever... lots of stagnant tissue use straight up PVC pipe as a foam roller. Foam rollers get soft over time and won't work try not to use the muscles you are releasing to apply force what's the best exercise? foam rolling, decreases sore timing, keeps you from getting injured whenever i fly i bring a lacrosse ball and do it in the airport Sit on the ball on the ground - butt muscles get as close to the bone without being on the bone, that will hurt hip is a ball and socket joint, sit on the ball and trace the socket Sit on the ball on the chair put under hamstring against the wall - spine-shoulderblade, lats do sort of a wall sit put ball between shoulderblade and spine against the wall, lean into it explore around your back lats tend to get really tight, definitely try these extensors trace from your elbow out to your wrist outside of arm against wall while standing use inside of arm on the table, push it down with other arm Feet stand and apply force against bottom of foot... i guess just try everywhere... from right in front of your heel pull your toes back and roll forward on the foot towards the toes \"reconnect the neuromuscular connections\" do you notice crunchies in your feet? \"fascia starts to calcify... on a cellular level\" - lol wtf sure why not Calf ball on the floor, calf on the ball most people don't realize how tight they are until they do it pick your hips up a bit to float over, good to use a block to raise the hips on this one relax your ankle as you roll into it, don't flex it Foam Rollers Abbreviated Version For IT band definitely use this instead of the ball \"t something\" like a rolling pin, about 2 inches diameter, good for calves and easier to get in there some tool i missed for something something try softball instead of lacrosse ball, it's bigger, maybe a bit more manageable - good for hips, calves i don't really like the knobs on the foam roller (trent: i think tons of knobs like a texture). idea is that they're for pressure points, but it is hard to pinpoint pressure points. consistently firm foam roller is better Scalenes are some of the tightest muscles do it yourself with your fingers, push down and do normal 40-60 sec, 2 sessions i find right on the inside of my collarbone, then tilt my head back so pin it then stretch back (tilt head back) might feel ticklish, neck, nausea, address it carefully scalenes go in a lot of different directions, so feel those out text neck is horrible (looking down) Cheek muscles, also use your fingers relax your face before you start","title":"Trigger Point Massage"},{"location":"docs/talks/trigger-point-massage/#lacrosse-ball-myofascial-release","text":"Speaker: ? Date: 2019-09-10 typically 40-60 seconds for any body part 2 rounds if you have time quads, hamstrings, glutes, back, everything the second round you really rolling pin it around do this type of stuff before a workout to open up your fascia and allow muscles to work through greater range of motion and minimize injury relax as much as you can, if you tighten it up the ball is tougher to get in there do every single part of the muscle this is different than stretching, surrounding every muscle is fascia, also attaches muscle to skin and other muscles ball breaks things up in there, if you are cringing a lot drink a lot of water - \"releasing a bunch of toxins and broken up stagnant toxins into your bloodstream\" never have any alcohol before/after a massage we tend to do the same movements over and over, sitting, walking, whatever... lots of stagnant tissue use straight up PVC pipe as a foam roller. Foam rollers get soft over time and won't work try not to use the muscles you are releasing to apply force what's the best exercise? foam rolling, decreases sore timing, keeps you from getting injured whenever i fly i bring a lacrosse ball and do it in the airport","title":"Lacrosse Ball Myofascial Release"},{"location":"docs/talks/trigger-point-massage/#sit-on-the-ball-on-the-ground-butt-muscles","text":"get as close to the bone without being on the bone, that will hurt hip is a ball and socket joint, sit on the ball and trace the socket","title":"Sit on the ball on the ground - butt muscles"},{"location":"docs/talks/trigger-point-massage/#sit-on-the-ball-on-the-chair","text":"put under hamstring","title":"Sit on the ball on the chair"},{"location":"docs/talks/trigger-point-massage/#against-the-wall-spine-shoulderblade-lats","text":"do sort of a wall sit put ball between shoulderblade and spine against the wall, lean into it explore around your back lats tend to get really tight, definitely try these","title":"against the wall - spine-shoulderblade, lats"},{"location":"docs/talks/trigger-point-massage/#extensors","text":"trace from your elbow out to your wrist outside of arm against wall while standing use inside of arm on the table, push it down with other arm","title":"extensors"},{"location":"docs/talks/trigger-point-massage/#feet","text":"stand and apply force against bottom of foot... i guess just try everywhere... from right in front of your heel pull your toes back and roll forward on the foot towards the toes \"reconnect the neuromuscular connections\" do you notice crunchies in your feet? \"fascia starts to calcify... on a cellular level\" - lol wtf sure why not","title":"Feet"},{"location":"docs/talks/trigger-point-massage/#calf","text":"ball on the floor, calf on the ball most people don't realize how tight they are until they do it pick your hips up a bit to float over, good to use a block to raise the hips on this one relax your ankle as you roll into it, don't flex it","title":"Calf"},{"location":"docs/talks/trigger-point-massage/#foam-rollers-abbreviated-version","text":"For IT band definitely use this instead of the ball \"t something\" like a rolling pin, about 2 inches diameter, good for calves and easier to get in there some tool i missed for something something try softball instead of lacrosse ball, it's bigger, maybe a bit more manageable - good for hips, calves i don't really like the knobs on the foam roller (trent: i think tons of knobs like a texture). idea is that they're for pressure points, but it is hard to pinpoint pressure points. consistently firm foam roller is better","title":"Foam Rollers Abbreviated Version"},{"location":"docs/talks/trigger-point-massage/#scalenes-are-some-of-the-tightest-muscles","text":"do it yourself with your fingers, push down and do normal 40-60 sec, 2 sessions i find right on the inside of my collarbone, then tilt my head back so pin it then stretch back (tilt head back) might feel ticklish, neck, nausea, address it carefully scalenes go in a lot of different directions, so feel those out text neck is horrible (looking down)","title":"Scalenes are some of the tightest muscles"},{"location":"docs/talks/trigger-point-massage/#cheek-muscles-also-use-your-fingers","text":"relax your face before you start","title":"Cheek muscles, also use your fingers"},{"location":"docs/talks/aws.training.solarchitect/","text":"AWS Solutions Architect Daylong Training Purpose: Prep for AWS Solutions Architect exam. Can you take cloud practitioner exam online? acloud.guru videos These videos were specifically called out for their VPC lab: https://acloud.guru/learn/aws-certified-solutions-architect-associate`o I took an Udemy \"Backspace Academy\" 10-part VPC lab which I found quite good. I have not done the acloud.guru one to compare. Whizlabs Practice Exams Solutions Architect Practice Exams are Recommended: https://www.whizlabs.com/aws-solutions-architect-associate/ Someone in this class said it's the best bang for the buck. great details about why the answer is the answer tons of question for $20 use the discount code on the homepage Test Taking There's a markdown file on this Test is on 5 pillars of a \"well-architected framework\" see \"resources\" for whitepaper and pillars People say that they get practice test questions on their real exam. SA questions can be really wordy and long. Practice exam is the same. Exam Tips Which service is best for decoupling architecture? SQS Determine how to design a Multi-tier Resources AWS Well-Architected Framework Whitepaper Reliability Security Performance Cost-optimized Operationally Excellent These five pillars are on the exam. There's a file for each of the presentations covering these 5 pillars AWS IQ will be GA later this year: https://aws.amazon.com/iq/ A way to tap into AWS certified consultants acloud.guru 2.5 hour cert prep: acloud.guru/join/awspartners can get these guys on udemy, they do that to try to get you into their bigger program Linux Academy Trainings Linux academy will spin up services for you (and delete them for you) so it's really clean Cloud Academy Trainings: cloudacademy.com $449/year use \"learn-aws-25\" at checkout for 25% discount code is a little old \"probably still valid\"... Building it out in cloud academy with labs \"is really helpful\" aws.training - \"architecting on aws\" search terms, try the \"architecting on aws\" course. There are also 5 others. Official Study Guide book: \"AWS Certified Solutions Architect: Official Study Guide\" - $42.63 on amazon.com The networking version of this is supposed to be excellent Read whiteppaers: aws.amazon.com/whitepapers - at least the well-architected one Read FAQ for services we talked about today Watch old AWS Reinvent Videos Study Groups: Coworkers taking the cert Brown bag lunch and learn Wrapup You have to register for the exam, not sure how rescheduling works Don't take it if you don't feel prepared, you can reschedule for 1 week 1 time or something... I think you can reschedule longer if you pay more... Apparently you can take cloud practitioner online? Look into this. Bring 2 forms of ID, regular ID plus credit card or other secondary?","title":"Readme"},{"location":"docs/talks/aws.training.solarchitect/#aws-solutions-architect-daylong-training","text":"Purpose: Prep for AWS Solutions Architect exam. Can you take cloud practitioner exam online?","title":"AWS Solutions Architect Daylong Training"},{"location":"docs/talks/aws.training.solarchitect/#acloudguru-videos","text":"These videos were specifically called out for their VPC lab: https://acloud.guru/learn/aws-certified-solutions-architect-associate`o I took an Udemy \"Backspace Academy\" 10-part VPC lab which I found quite good. I have not done the acloud.guru one to compare.","title":"acloud.guru videos"},{"location":"docs/talks/aws.training.solarchitect/#whizlabs-practice-exams","text":"Solutions Architect Practice Exams are Recommended: https://www.whizlabs.com/aws-solutions-architect-associate/ Someone in this class said it's the best bang for the buck. great details about why the answer is the answer tons of question for $20 use the discount code on the homepage","title":"Whizlabs Practice Exams"},{"location":"docs/talks/aws.training.solarchitect/#test-taking","text":"There's a markdown file on this Test is on 5 pillars of a \"well-architected framework\" see \"resources\" for whitepaper and pillars People say that they get practice test questions on their real exam. SA questions can be really wordy and long. Practice exam is the same.","title":"Test Taking"},{"location":"docs/talks/aws.training.solarchitect/#exam-tips","text":"Which service is best for decoupling architecture? SQS Determine how to design a Multi-tier","title":"Exam Tips"},{"location":"docs/talks/aws.training.solarchitect/#resources","text":"AWS Well-Architected Framework Whitepaper Reliability Security Performance Cost-optimized Operationally Excellent These five pillars are on the exam. There's a file for each of the presentations covering these 5 pillars AWS IQ will be GA later this year: https://aws.amazon.com/iq/ A way to tap into AWS certified consultants acloud.guru 2.5 hour cert prep: acloud.guru/join/awspartners can get these guys on udemy, they do that to try to get you into their bigger program Linux Academy Trainings Linux academy will spin up services for you (and delete them for you) so it's really clean Cloud Academy Trainings: cloudacademy.com $449/year use \"learn-aws-25\" at checkout for 25% discount code is a little old \"probably still valid\"... Building it out in cloud academy with labs \"is really helpful\" aws.training - \"architecting on aws\" search terms, try the \"architecting on aws\" course. There are also 5 others. Official Study Guide book: \"AWS Certified Solutions Architect: Official Study Guide\" - $42.63 on amazon.com The networking version of this is supposed to be excellent Read whiteppaers: aws.amazon.com/whitepapers - at least the well-architected one Read FAQ for services we talked about today Watch old AWS Reinvent Videos Study Groups: Coworkers taking the cert Brown bag lunch and learn","title":"Resources"},{"location":"docs/talks/aws.training.solarchitect/#wrapup","text":"You have to register for the exam, not sure how rescheduling works Don't take it if you don't feel prepared, you can reschedule for 1 week 1 time or something... I think you can reschedule longer if you pay more... Apparently you can take cloud practitioner online? Look into this. Bring 2 forms of ID, regular ID plus credit card or other secondary?","title":"Wrapup"},{"location":"docs/talks/aws.training.solarchitect/#_1","text":"","title":""},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/","text":"Design Cost Optimized Architectures How often and how quickly do you need to access your data? How large is your data set? How transient is your data? Clickstream How much are you prepared to pay to store the data? Durability: The average, expected annual data loss S3 Standard, S3 IA (infrequent access), S3 Archive Does your data require high IOPS? EBS block storage Throughput - HDD IOPS - SSD Remember the \"provisioned iops\" ssd has much higher IOPS... 32000 iops cannot be boot volume probably need to pay monthly or annual instead of by minute/hour S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA) Throughput oriented, lowest cost: Cold HDD (sc1) Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM. You will get charged for 2 hours (not 1.5 hours) Some instances you can pay per second Spot Instances Cheapest option, up to 90% off the price You place a bid on amazon EC2 instances, you get unused extra capacity. Instance can get terminated at any time. You get a 2 minute warning, so there's solutions. Apparently we can predict this and shut down the application. Also apparently you don't get kicked off these very often most of the time, but you COULD BE!! Availability Zones are load balanced behind the scenes But instructor says this is changing, so all users will have the same AZ in the future Users are binned because everyone would use the first one: us-east-1a Reserved Instances - RI Up to 75% discount compared to on-demand instances Capacity Reservation - 1 to 3 years AWS particular AZ can run out of capacity on-demand for a particular type of instance RI Marketplace Lambda acloud.guru is 100% lambda He says he didn't pay a cent for the first 18 months! 1 million requests per month free, forever Developer exam question: what is the max time you can set for lambda? API Gateway Used for lambda, we did not touch on the details very much","title":"Design Cost Optimized Architectures"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#design-cost-optimized-architectures","text":"How often and how quickly do you need to access your data? How large is your data set? How transient is your data? Clickstream How much are you prepared to pay to store the data? Durability: The average, expected annual data loss S3 Standard, S3 IA (infrequent access), S3 Archive Does your data require high IOPS? EBS block storage Throughput - HDD IOPS - SSD Remember the \"provisioned iops\" ssd has much higher IOPS... 32000 iops cannot be boot volume probably need to pay monthly or annual instead of by minute/hour S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA) Throughput oriented, lowest cost: Cold HDD (sc1) Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM. You will get charged for 2 hours (not 1.5 hours) Some instances you can pay per second","title":"Design Cost Optimized Architectures"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#spot-instances","text":"Cheapest option, up to 90% off the price You place a bid on amazon EC2 instances, you get unused extra capacity. Instance can get terminated at any time. You get a 2 minute warning, so there's solutions. Apparently we can predict this and shut down the application. Also apparently you don't get kicked off these very often most of the time, but you COULD BE!!","title":"Spot Instances"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#availability-zones-are-load-balanced-behind-the-scenes","text":"But instructor says this is changing, so all users will have the same AZ in the future Users are binned because everyone would use the first one: us-east-1a","title":"Availability Zones are load balanced behind the scenes"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#reserved-instances-ri","text":"Up to 75% discount compared to on-demand instances Capacity Reservation - 1 to 3 years AWS particular AZ can run out of capacity on-demand for a particular type of instance RI Marketplace","title":"Reserved Instances - RI"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#lambda","text":"acloud.guru is 100% lambda He says he didn't pay a cent for the first 18 months! 1 million requests per month free, forever Developer exam question: what is the max time you can set for lambda?","title":"Lambda"},{"location":"docs/talks/aws.training.solarchitect/design-cost-optimized-architectures/#api-gateway","text":"Used for lambda, we did not touch on the details very much","title":"API Gateway"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/","text":"Exam Questions These are copied from each section of the day-long course Resilient Architecture EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK. EBS is an Independent Lifecycle from EC2 instance Exam question, we need 12000 iops, so which one do you pick? You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS Provisioned is for large database workloads, production environments st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations EBS Volume Types: https://aws.amazon.com/iq/ gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances. Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C C = customer S3 = ?? probably what you assume KMS = ?? probably what you assume S3 has a multi-part upload API Use this for large files S3: AWS will never move data to a different region unless you tell us to Data soverignty laws EBS: You can move across AZs within a region by creating a snapshot To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ EBS: Snapshots go to S3 S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" EFS is block storage, S3 is object storage CloudFormation Exam Questions A free service, you only pay for resources it uses is important to High Availability because you can create and replicate resources easily What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Storage gateway: know the types and what they are meant for LOOK IT UP Design Cost Optimized Architectures How often and how quickly do you need to access your data? How large is your data set? How transient is your data? Clickstream How much are you prepared to pay to store the data? Durability: The average, expected annual data loss S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA) Throughput oriented, lowest cost: Cold HDD (sc1) Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM. You will get charged for 2 hours (not 1.5 hours) Some instances you can pay per second Define Operationally Excellent Architectures 5.1 Choose design features in solutions that enable operational excellence. metrics: latency, http, 4xx errors, 5xx errors, etc. cloudwatch can give metrics on ec2 based on what we can measure can't measure how much data you have stored on ebs volume - no metric cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers Performant Architectures Elasticache - Whenever they say \"relational\" - use RDS Whenever they say \"nosql\" - DynamoDB Whenever they say \"data warehouse\" - \"Redshift!\" Not going to get tested on relational vs nonrelational not an exam question, interview question! 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc) Not going to get tested on using aurora vs rds choices Do know what engines are supported RDS: Which engines does RDS support read replica for? Question: \"offload main database because it's hit hard\" Use READ REPLICA Question: \"You need HA\" and then multi AZ deployment Use MULTI AZ DEPLOYMENT Bring content closer to viewers and increase performance of website: CloudFront Can cache dynamic or static content Your clients are complaining that viewing your videos is really slow Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Exam Question Exam Anecdote: More exam questions about classic load balancer Heard from 2 recent exam takers Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance (replaces unhealthy instances with healthy instances) Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address EC2 Families: They might ask you what CPU instance type based on your needs Specify Secure Applications Security is Job 0 on AWS. big part of exam: how to secure application tiers how to secure data networking infrastructure for a single VPC application acloud.guru vpc training lab (very long) IAM User: Console access versus programmatic access Console requires username + password Guaranteed exam question: Programmatic access just needs access key and secret Not username / password IAM Policy: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy) IAM Roles: When asked, always pick IAM roles over access keys Exam questions will try to confuse you: cloudtrail vs. cloudwatch cloudtrail is a trail - logs cloudwatch is like watching - metrics VPC: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. VPC: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1 Shared Responsibility Model Shared between AWS and the customer (me).","title":"Exam Questions Copied"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#exam-questions","text":"These are copied from each section of the day-long course","title":"Exam Questions"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#resilient-architecture","text":"EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK. EBS is an Independent Lifecycle from EC2 instance Exam question, we need 12000 iops, so which one do you pick? You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS Provisioned is for large database workloads, production environments st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations EBS Volume Types: https://aws.amazon.com/iq/ gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances. Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C C = customer S3 = ?? probably what you assume KMS = ?? probably what you assume S3 has a multi-part upload API Use this for large files S3: AWS will never move data to a different region unless you tell us to Data soverignty laws EBS: You can move across AZs within a region by creating a snapshot To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ EBS: Snapshots go to S3 S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" EFS is block storage, S3 is object storage CloudFormation Exam Questions A free service, you only pay for resources it uses is important to High Availability because you can create and replicate resources easily What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Storage gateway: know the types and what they are meant for LOOK IT UP","title":"Resilient Architecture"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#design-cost-optimized-architectures","text":"How often and how quickly do you need to access your data? How large is your data set? How transient is your data? Clickstream How much are you prepared to pay to store the data? Durability: The average, expected annual data loss S3 Resiliency: Almost all S3 Resilient against single AD (except for 1-zone IA) Throughput oriented, lowest cost: Cold HDD (sc1) Exam Question: I have an on demand instance, it costs $10/hour, I started at 930 AM and terminated at 1100 AM. You will get charged for 2 hours (not 1.5 hours) Some instances you can pay per second","title":"Design Cost Optimized Architectures"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#define-operationally-excellent-architectures","text":"5.1 Choose design features in solutions that enable operational excellence. metrics: latency, http, 4xx errors, 5xx errors, etc. cloudwatch can give metrics on ec2 based on what we can measure can't measure how much data you have stored on ebs volume - no metric cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers","title":"Define Operationally Excellent Architectures"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#performant-architectures","text":"Elasticache - Whenever they say \"relational\" - use RDS Whenever they say \"nosql\" - DynamoDB Whenever they say \"data warehouse\" - \"Redshift!\" Not going to get tested on relational vs nonrelational not an exam question, interview question! 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc) Not going to get tested on using aurora vs rds choices Do know what engines are supported RDS: Which engines does RDS support read replica for? Question: \"offload main database because it's hit hard\" Use READ REPLICA Question: \"You need HA\" and then multi AZ deployment Use MULTI AZ DEPLOYMENT Bring content closer to viewers and increase performance of website: CloudFront Can cache dynamic or static content Your clients are complaining that viewing your videos is really slow Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Exam Question Exam Anecdote: More exam questions about classic load balancer Heard from 2 recent exam takers Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance (replaces unhealthy instances with healthy instances) Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address EC2 Families: They might ask you what CPU instance type based on your needs","title":"Performant Architectures"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#specify-secure-applications","text":"Security is Job 0 on AWS. big part of exam: how to secure application tiers how to secure data networking infrastructure for a single VPC application acloud.guru vpc training lab (very long) IAM User: Console access versus programmatic access Console requires username + password Guaranteed exam question: Programmatic access just needs access key and secret Not username / password IAM Policy: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy) IAM Roles: When asked, always pick IAM roles over access keys Exam questions will try to confuse you: cloudtrail vs. cloudwatch cloudtrail is a trail - logs cloudwatch is like watching - metrics VPC: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. VPC: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1","title":"Specify Secure Applications"},{"location":"docs/talks/aws.training.solarchitect/exam-questions-copied/#shared-responsibility-model","text":"Shared between AWS and the customer (me).","title":"Shared Responsibility Model"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/","text":"Exam Taking Strategies Sleep well, eat well, arrive a few minutes early to the testing center. It's a long exam period (2 hours?), the guy next to me was done in an hour. Keep track of your time, mark a tough question and go back. Remember the relative grading. Exams are on a curve You want to aim for above 70% There's no set passing score If you get a very low score you could still pass You get your score Tips Read the question carefully Seriously All of it Read the answers Use process of elimination Refer to other questions you can go back and forth between questions Time management is critical When in doubt GUESS Test Axioms \"Single AZ\": NEVER the right answer Using AWS managed services should always be preferred RDS over setting up a database on EC2 Fault Tolerance is DIFFERENT THAN Fault Tolerance HA == Multiple AZs Fault Tolerant = What happens when everything everywhere goes down Sample Exam Question 1 I took a photo of it. Strategy: eliminate 2, then focus on the key features of the problem (highlighted in red). Sample Exam Question 2: SELECT TWO Strategy: Eliminate 2, validate remaining two. Watch out for where one is \"all of the above\" lol Sample Exam Question 3: SELECT THREE Which is NOT right? Sample Exam Question 4: SELECT TWO Sample Exam Question 5: SELECT TWO Eliminate Single AZ Since cost is a priority, we use exactly what we need: 4 instances Sample Exam Question 6: Elimination Probably not on SA exam, probably on developer Need to know a lot: - What are mappings, parameters in cloudformation, are AMI ids different or the same? Sample Question 7: Elimination Sample Question 8: Need to know RTO and RPO... how can we deduce... Specific to Disaster Recovery Plan Recovery Time Objective Recovery Point Objective Gotta know this one! Sample Question 9: Eliminate 2 Remove 2, know what each one is. Sample Question 10: know the facts Sample question 12: know the facts","title":"Exam Taking Strategies"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#exam-taking-strategies","text":"Sleep well, eat well, arrive a few minutes early to the testing center. It's a long exam period (2 hours?), the guy next to me was done in an hour. Keep track of your time, mark a tough question and go back. Remember the relative grading.","title":"Exam Taking Strategies"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#exams-are-on-a-curve","text":"You want to aim for above 70% There's no set passing score If you get a very low score you could still pass You get your score","title":"Exams are on a curve"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#tips","text":"Read the question carefully Seriously All of it Read the answers Use process of elimination Refer to other questions you can go back and forth between questions Time management is critical When in doubt GUESS","title":"Tips"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#test-axioms","text":"\"Single AZ\": NEVER the right answer Using AWS managed services should always be preferred RDS over setting up a database on EC2 Fault Tolerance is DIFFERENT THAN Fault Tolerance HA == Multiple AZs Fault Tolerant = What happens when everything everywhere goes down","title":"Test Axioms"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-1","text":"I took a photo of it. Strategy: eliminate 2, then focus on the key features of the problem (highlighted in red).","title":"Sample Exam Question 1"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-2-select-two","text":"Strategy: Eliminate 2, validate remaining two. Watch out for where one is \"all of the above\" lol","title":"Sample Exam Question 2: SELECT TWO"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-3-select-three","text":"Which is NOT right?","title":"Sample Exam Question 3: SELECT THREE"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-4-select-two","text":"","title":"Sample Exam Question 4: SELECT TWO"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-5-select-two","text":"Eliminate Single AZ Since cost is a priority, we use exactly what we need: 4 instances","title":"Sample Exam Question 5: SELECT TWO"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-exam-question-6-elimination","text":"Probably not on SA exam, probably on developer Need to know a lot: - What are mappings, parameters in cloudformation, are AMI ids different or the same?","title":"Sample Exam Question 6: Elimination"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-question-7-elimination","text":"","title":"Sample Question 7: Elimination"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-question-8-need-to-know-rto-and-rpo-how-can-we-deduce","text":"Specific to Disaster Recovery Plan Recovery Time Objective Recovery Point Objective Gotta know this one!","title":"Sample Question 8: Need to know RTO and RPO... how can we deduce..."},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-question-9-eliminate-2","text":"Remove 2, know what each one is.","title":"Sample Question 9: Eliminate 2"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-question-10-know-the-facts","text":"","title":"Sample Question 10: know the facts"},{"location":"docs/talks/aws.training.solarchitect/exam-taking-strategies/#sample-question-12-know-the-facts","text":"","title":"Sample question 12: know the facts"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/","text":"Define Operationally Excellent Architectures 5.1 Choose design features in solutions that enable operational excellence. metrics: latency, http, 4xx errors, 5xx errors, etc. cloudwatch can give metrics on ec2 based on what we can measure can't measure how much data you have stored on ebs volume - no metric cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms Exam Questions CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers Infrastructure as Code CloudFormation Version your infrastructure Applications can rely on specific changes to infrastructure Branch your infastructure (e.g. git) Work on multiple things concurrently Run version 2 while working on version 3. Audit changes Traceability: who and why AWS CodeCommit Not on SA Associate - but on developer. Need to know codesuite. Fully managed source control service HA, durable Encryption IAM No limit on repo size Does it support LFS? Need to think about what LFS even is... AWS CodeDeploy Fully managed deployment services Blue/Green Deployments Deployment Health Tracking Automatically rollback if failure is detected Exam Question: Amazon EC2, Fargate, lambda, on-prem servers AWS CodePipeline We skipped over this, don't really need to know about it for this purpose.","title":"Operationally Excellent Architectures"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#define-operationally-excellent-architectures","text":"5.1 Choose design features in solutions that enable operational excellence. metrics: latency, http, 4xx errors, 5xx errors, etc. cloudwatch can give metrics on ec2 based on what we can measure can't measure how much data you have stored on ebs volume - no metric cloudwatch custom metrics - you can report your own metrics to cloudwatch then set alarms","title":"Define Operationally Excellent Architectures"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#exam-questions","text":"CodeDeploy: Amazon EC2, Fargate, lambda, on-prem servers","title":"Exam Questions"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#infrastructure-as-code","text":"","title":"Infrastructure as Code"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#cloudformation","text":"Version your infrastructure Applications can rely on specific changes to infrastructure Branch your infastructure (e.g. git) Work on multiple things concurrently Run version 2 while working on version 3. Audit changes Traceability: who and why","title":"CloudFormation"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#aws-codecommit","text":"Not on SA Associate - but on developer. Need to know codesuite. Fully managed source control service HA, durable Encryption IAM No limit on repo size Does it support LFS? Need to think about what LFS even is...","title":"AWS CodeCommit"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#aws-codedeploy","text":"Fully managed deployment services Blue/Green Deployments Deployment Health Tracking Automatically rollback if failure is detected Exam Question: Amazon EC2, Fargate, lambda, on-prem servers","title":"AWS CodeDeploy"},{"location":"docs/talks/aws.training.solarchitect/operationally-excellent-architectures/#aws-codepipeline","text":"We skipped over this, don't really need to know about it for this purpose.","title":"AWS CodePipeline"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/","text":"Performant Architectures Exam Questions Elasticache - Whenever they say \"relational\" - use RDS Whenever they say \"nosql\" - DynamoDB Whenever they say \"data warehouse\" - \"Redshift!\" Not going to get tested on relational vs nonrelational not an exam question, interview question! 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc) Not going to get tested on using aurora vs rds choices Do know what engines are supported RDS: Which engines does RDS support read replica for? Question: \"offload main database because it's hit hard\" Use READ REPLICA Question: \"You need HA\" and then multi AZ deployment Use MULTI AZ DEPLOYMENT Bring content closer to viewers and increase performance of website: CloudFront Can cache dynamic or static content Your clients are complaining that viewing your videos is really slow Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Exam Question Exam Anecdote: More exam questions about classic load balancer Heard from 2 recent exam takers Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance (replaces unhealthy instances with healthy instances) Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address EC2 Families: They might ask you what CPU instance type based on your needs Topics RDS You pick a maintenance window and they apply the maintenance Automated backups Multi AZ deployments Encryption at rest and in transit Scalability: Read Replicas - same AZ or different AZ Send some read requests there Exam Question: Which engines does RDS support read replica for? All except oracle? DynamoDB key-value and document database nosql single-digit millisecond performance multi-master available now also available in aurora multi-region available (up to you) durable RCU: Read Capacity Unit: One strongly consistent read per second OR 2 eventually consistent reads per second Item up to 4kb in size Need this for developer, I need so many reads/writes per second WCU: Write Capacity Unit - item up to 1kb in size 1 write per second CloudFront Fast CDN service Dynamic or Static Content Global Edge Network Origins: S3, EC2, ELB, HTTP servers Even if you have an on-prem HTTP server, you can still use cloudfront Security: AWS Shield, AWS WAF (firewall) Protect Private Content Elasticache memcached and redis - sysops and devops ask you to distinguish One of these: memcached, redis Scale Up Increase size of hardware more processing, more storage Bigger EC2 instances Scale Out Adding more servers Share the workload Can be done on the flo Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Trent: This goes into HA as well, instances can fail, we want to have a lot of instances Trent: Probably save a lot of money scaling out with spot instances because they are so cheap, especially for http workers Load Balancers Exam Anecdote: More exam questions about classic load balancer Classic Load Balancer Layer 4 and Layer 7 (4 = transport layer, 7 = application layer) Sticky sessions per user Manages SSL - does all 4 protocols Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance Application Load Balancer Layer 7 (application layer) Route traffic to targets only HTTP, HTTPS protocols support Sysops & network certs native ipv6 Target Groups: cannot assign instances, must make them a member of a target group concept is specific to application load balancer, not done with classic load balancer sticky sessions advanced routing Network Load Balancer All about transport (layer 4) Best performance load balancer static IP support Exam question: always use DNS name of load balancer, don't point your website at the load balancer IP address TLS offloading Supports SSL now Auto Scaling Better fault tolerance, better availability, better cost management Cost Management Elastic: Adjust number of instances Health Check: terminate unhealthy instance and start a new one Cattle vs Pets Launch systems based on launch configuration Scaling policy if cpu > 95 add x instances any other metric, whatever is good for application EC2 Instance Types Know the family and what they are for. Exam Question EC2 Families: They might ask you what CPU instance type based on your needs You don't need to know how many versions for each family, just know the family. Some Handy mnemonics someone made up T Family: general - burstable, good for dynamic workloads M family: main for application - static, good for consistent workloads C family: compute - good for small memory footprint and high compute R family: RAM - high memory to CPU ratio X family: extreme - high memory for CPU, general in-memory usage P family: pictures - general graphics F family: FPGA G family: graphics intensive applications H family: HDD backed I family: SDD D family: Dense - High disk ratio","title":"Performant Architectures"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#performant-architectures","text":"","title":"Performant Architectures"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#exam-questions","text":"Elasticache - Whenever they say \"relational\" - use RDS Whenever they say \"nosql\" - DynamoDB Whenever they say \"data warehouse\" - \"Redshift!\" Not going to get tested on relational vs nonrelational not an exam question, interview question! 6 RDS Flavors - know them - look on the RDS homepage (mysql, postgres, etc) Not going to get tested on using aurora vs rds choices Do know what engines are supported RDS: Which engines does RDS support read replica for? Question: \"offload main database because it's hit hard\" Use READ REPLICA Question: \"You need HA\" and then multi AZ deployment Use MULTI AZ DEPLOYMENT Bring content closer to viewers and increase performance of website: CloudFront Can cache dynamic or static content Your clients are complaining that viewing your videos is really slow Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Exam Question Exam Anecdote: More exam questions about classic load balancer Heard from 2 recent exam takers Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance (replaces unhealthy instances with healthy instances) Network Load Balancer: always use DNS name of load balancer, don't point your website at the load balancer IP address EC2 Families: They might ask you what CPU instance type based on your needs","title":"Exam Questions"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#topics","text":"","title":"Topics"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#rds","text":"You pick a maintenance window and they apply the maintenance Automated backups Multi AZ deployments Encryption at rest and in transit Scalability: Read Replicas - same AZ or different AZ Send some read requests there Exam Question: Which engines does RDS support read replica for? All except oracle?","title":"RDS"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#dynamodb","text":"key-value and document database nosql single-digit millisecond performance multi-master available now also available in aurora multi-region available (up to you) durable RCU: Read Capacity Unit: One strongly consistent read per second OR 2 eventually consistent reads per second Item up to 4kb in size Need this for developer, I need so many reads/writes per second WCU: Write Capacity Unit - item up to 1kb in size 1 write per second","title":"DynamoDB"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#cloudfront","text":"Fast CDN service Dynamic or Static Content Global Edge Network Origins: S3, EC2, ELB, HTTP servers Even if you have an on-prem HTTP server, you can still use cloudfront Security: AWS Shield, AWS WAF (firewall) Protect Private Content","title":"CloudFront"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#elasticache","text":"memcached and redis - sysops and devops ask you to distinguish One of these: memcached, redis","title":"Elasticache"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#scale-up","text":"Increase size of hardware more processing, more storage Bigger EC2 instances","title":"Scale Up"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#scale-out","text":"Adding more servers Share the workload Can be done on the flo Scale Out: I need better performance, should I increase the size of my instance or add a server? The answer is ALWAYS add a server: scale out, add instances, use EC2 instance Trent: This goes into HA as well, instances can fail, we want to have a lot of instances Trent: Probably save a lot of money scaling out with spot instances because they are so cheap, especially for http workers","title":"Scale Out"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#load-balancers","text":"Exam Anecdote: More exam questions about classic load balancer Classic Load Balancer Layer 4 and Layer 7 (4 = transport layer, 7 = application layer) Sticky sessions per user Manages SSL - does all 4 protocols Exam Question: Load Balancer checks health of ec2 instances behind load balancer Question: \"What happens then?\" Load balancer just stops routing requests until the instance is replaced or healthy Auto scale manages health of the instance Application Load Balancer Layer 7 (application layer) Route traffic to targets only HTTP, HTTPS protocols support Sysops & network certs native ipv6 Target Groups: cannot assign instances, must make them a member of a target group concept is specific to application load balancer, not done with classic load balancer sticky sessions advanced routing Network Load Balancer All about transport (layer 4) Best performance load balancer static IP support Exam question: always use DNS name of load balancer, don't point your website at the load balancer IP address TLS offloading Supports SSL now","title":"Load Balancers"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#auto-scaling","text":"Better fault tolerance, better availability, better cost management Cost Management Elastic: Adjust number of instances Health Check: terminate unhealthy instance and start a new one Cattle vs Pets Launch systems based on launch configuration Scaling policy if cpu > 95 add x instances any other metric, whatever is good for application","title":"Auto Scaling"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#ec2-instance-types","text":"Know the family and what they are for. Exam Question EC2 Families: They might ask you what CPU instance type based on your needs You don't need to know how many versions for each family, just know the family.","title":"EC2 Instance Types"},{"location":"docs/talks/aws.training.solarchitect/performant-architectures/#some-handy-mnemonics-someone-made-up","text":"T Family: general - burstable, good for dynamic workloads M family: main for application - static, good for consistent workloads C family: compute - good for small memory footprint and high compute R family: RAM - high memory to CPU ratio X family: extreme - high memory for CPU, general in-memory usage P family: pictures - general graphics F family: FPGA G family: graphics intensive applications H family: HDD backed I family: SDD D family: Dense - High disk ratio","title":"Some Handy mnemonics someone made up"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/","text":"Designing Resilient Architectures Overview SQS: Decoupling Mechanism for architecture Determine how to design a multi-tier architecture Global Availability Zone - ALWAYS Exam Questions It's better to do the labs than read the documentation. Anecdotally, the questions are really clear, there's no ambiguity if you really parse each question. There's always something that discounts one of the two best questions. Keep the pillars of well-architected systems in mind. The question will always say \"high availabity\" or \"low cost\". Solutions Architect EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK. EBS is an Independent Lifecycle from EC2 instance Exam question, we need 12000 iops, so which one do you pick? You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS Provisioned is for large database workloads, production environments st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations EBS Volume Types: https://aws.amazon.com/iq/ gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances. Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C C = customer S3 = ?? probably what you assume KMS = ?? probably what you assume S3 has a multi-part upload API Use this for large files S3: AWS will never move data to a different region unless you tell us to Data soverignty laws EBS: You can move across AZs within a region by creating a snapshot To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ EBS: Snapshots go to S3 S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" EFS is block storage, S3 is object storage CloudFormation Exam Questions A free service, you only pay for resources it uses is important to High Availability because you can create and replicate resources easily What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Storage gateway: know the types and what they are meant for LOOK IT UP Sysops (NOT the focus today) Associate Developer (NOT the focus today) CloudFormation: what's wrong with a template, what's missing from a template Elastic Block Store Whitepaper: AWS Storage Services Overview MiB is Million bytes not megabytes (GiB is 1000x1000x1000) Different Volume Types gp2, io1, st1, sc1 max size you can get of any one is 16 TB Snapshots Supports Encryption Independent Lifecycle than EC2 instance EBS snapshots are backed up to S3 EFS - Know that efs exists Network filesystem, can attach to multiple efs instances Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible S3 Cross-region replication, cross-account replication 5 terabytes is limit on object size 11 nines supports server-side encryption: SSE-S3, SSE-KMS, SSE-C Supports versioning files as you update but you are paying for new versions multi-part upload API cross-region replication S3 Storage Classes Table = see photo There is S3-RRS: 4 nines reduced-redundancy probably NOT on exam: https://aws.amazon.com/s3/reduced-redundancy/ Charged for a minimum of 30 days S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" Glacier Retrieval options: expedited, standard, bulk Deep archive is always a few hours Cloudfront: CDN Service It will be on the exam. We'll talk about it later. One person used it to host a video. AWS CloudFormation Associate developer certification goes in depth about CloudFormation templates. Free Infrastructure as code Model your entire infrastructure as text: YAML or JSON Uses templates and stacks to provision resources \"stack\" - create, update, delete resources as a single unit What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Declarative - aka idempotent, reapplying won't create a second set... must use tags? Storage Gateway Hybrid environment - move data between on-prem and the cloud Exam Question: know the types and what they are meant for Availability Zones Diagram AWS contains regions (currently: 22 regions) Regions contain Availability Zones (AZs) At least 2 AZs in every region, typically 3 Each AZ can have multiple data centers (typically 3 data centers) High Availability (HA) You need to deploy in at least 2 AZs for HA. Diagram AWS contains Regions, Regions each contain their own AZs Regions are NOT connected by lines AZs are connected by lines","title":"Resilient Architectures"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#designing-resilient-architectures","text":"","title":"Designing Resilient Architectures"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#overview","text":"SQS: Decoupling Mechanism for architecture Determine how to design a multi-tier architecture Global Availability Zone - ALWAYS","title":"Overview"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#exam-questions","text":"It's better to do the labs than read the documentation. Anecdotally, the questions are really clear, there's no ambiguity if you really parse each question. There's always something that discounts one of the two best questions. Keep the pillars of well-architected systems in mind. The question will always say \"high availabity\" or \"low cost\".","title":"Exam Questions"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#solutions-architect","text":"EC2 Ephemeral volume - you lose your data if you terminate the instance (stop), if you reset it's OK. EBS is an Independent Lifecycle from EC2 instance Exam question, we need 12000 iops, so which one do you pick? You need Provisioned IOPS SSD (io1) (32000 iops) because gp2 (general purpose SSD) is only 10000 IOPS Provisioned is for large database workloads, production environments st1, sc1 is good for log processing, data warehouses, when storage cost is more important than other considerations EBS Volume Types: https://aws.amazon.com/iq/ gp2, io1, st1, sc1: LOTS OF EXAM QUESTIONS ON THIS TABLE - see photo in phone Can only attach EBS volume to 1 instance at a time, EFS can work with multiple EC2 instances. Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible S3 supports server-side encryption: SSE-S3, SSE-KMS, SSE-C C = customer S3 = ?? probably what you assume KMS = ?? probably what you assume S3 has a multi-part upload API Use this for large files S3: AWS will never move data to a different region unless you tell us to Data soverignty laws EBS: You can move across AZs within a region by creating a snapshot To get volume into new AZ: You restore the snapshot to a new volume, and you select the AZ EBS: Snapshots go to S3 S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" EFS is block storage, S3 is object storage CloudFormation Exam Questions A free service, you only pay for resources it uses is important to High Availability because you can create and replicate resources easily What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Storage gateway: know the types and what they are meant for LOOK IT UP","title":"Solutions Architect"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#sysops-not-the-focus-today","text":"","title":"Sysops (NOT the focus today)"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#associate-developer-not-the-focus-today","text":"CloudFormation: what's wrong with a template, what's missing from a template","title":"Associate Developer (NOT the focus today)"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#elastic-block-store","text":"Whitepaper: AWS Storage Services Overview MiB is Million bytes not megabytes (GiB is 1000x1000x1000) Different Volume Types gp2, io1, st1, sc1 max size you can get of any one is 16 TB Snapshots Supports Encryption Independent Lifecycle than EC2 instance EBS snapshots are backed up to S3","title":"Elastic Block Store"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#efs-know-that-efs-exists","text":"Network filesystem, can attach to multiple efs instances Supports NFS version v4.0 and 4.1 - need to know EFS is NFS compatible","title":"EFS - Know that efs exists"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#s3","text":"Cross-region replication, cross-account replication 5 terabytes is limit on object size 11 nines supports server-side encryption: SSE-S3, SSE-KMS, SSE-C Supports versioning files as you update but you are paying for new versions multi-part upload API cross-region replication S3 Storage Classes Table = see photo There is S3-RRS: 4 nines reduced-redundancy probably NOT on exam: https://aws.amazon.com/s3/reduced-redundancy/ Charged for a minimum of 30 days S3 Replicates across all AZs in a region except \"IA one-zone\" which only has 1 zone S3 Exam question, how to save cost? Set up lifecycle policy! 30 days: move to IA, 60 days: move to Glacier delete after 365 days. Durability: \"Am I going to lose my data, eleven nines.\" Availability: \"Can I go get my data right now? Ever?\" Glacier Retrieval options: expedited, standard, bulk Deep archive is always a few hours","title":"S3"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#cloudfront-cdn-service","text":"It will be on the exam. We'll talk about it later. One person used it to host a video.","title":"Cloudfront: CDN Service"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#aws-cloudformation","text":"Associate developer certification goes in depth about CloudFormation templates. Free Infrastructure as code Model your entire infrastructure as text: YAML or JSON Uses templates and stacks to provision resources \"stack\" - create, update, delete resources as a single unit What's a template? The JSON or YAML text file What's a stack? The actual stack of resources created in the account Declarative - aka idempotent, reapplying won't create a second set... must use tags?","title":"AWS CloudFormation"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#storage-gateway","text":"Hybrid environment - move data between on-prem and the cloud Exam Question: know the types and what they are meant for","title":"Storage Gateway"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#availability-zones-diagram","text":"AWS contains regions (currently: 22 regions) Regions contain Availability Zones (AZs) At least 2 AZs in every region, typically 3 Each AZ can have multiple data centers (typically 3 data centers)","title":"Availability Zones Diagram"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#high-availability-ha","text":"You need to deploy in at least 2 AZs for HA.","title":"High Availability (HA)"},{"location":"docs/talks/aws.training.solarchitect/resilient-architectures/#diagram","text":"AWS contains Regions, Regions each contain their own AZs Regions are NOT connected by lines AZs are connected by lines","title":"Diagram"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/","text":"Specify Secure Applications Security is Job 0 on AWS. big part of exam: how to secure application tiers how to secure data networking infrastructure for a single VPC application cloud guru vpc (I did this last night) Exam Questions IAM User: Console access versus programmatic access Console requires username + password Guaranteed exam question: Programmatic access just needs access key and secret Not username / password IAM Policy: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy) IAM Roles: When asked, always pick IAM roles over access keys Exam questions will try to confuse you: cloudtrail vs. cloudwatch cloudtrail is a trail - logs cloudwatch is like watching - metrics VPC: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. VPC: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1 Shared Responsibility Model Shared between AWS and the customer (me). AAA: Authenticate, Authorize, Audit Authenticate IAM Username/Password Access Key (+ MFA) Federation Authorize IAM Policies Audit CloudTrail - region specific logging IAM Groups Groups can be nested Attach IAM Policy to group You don't want to attach policies to users. Users can be in multiple groups There is no default group for all users Exam Question: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy) IAM Roles Identity created for specific permissions Can be assumed by people who need it (and have perms to do so) Roles can be assumed by users, applications, or assigned to resources/services. You can only assume one role at a time When asked, always pick IAM roles over access keys Best solution for giving access to security in multiple accounts Cross account ?? Best way to give access to other organizations Need to use API to enumerate roles for a user, then compare permissions Web Identity Federation AWS Security Token Service (STS) Temporary credentials for access to resources (e.g. 24 hour max) IAM Policies There is a great simulation tool for testing Attach permissions specify type of access actions that can be performed resources on which actions can be performed etc Principle of least privilege JSON format Calculating Permissions Everything implicitly denied Explicit allows override implicit denies Explicit denies override explicit allows AWS CloudTrail Logging (see page for details) S3 Security Bucket Policy ACL (Access Control Lists) Applied to specific objects within the bucket Encryption Encrypt S3 Buckets Off by default S3 Versioning Once turned on, cannot turn off maybe possible to suspend Increases storage costs, previous versions are not deleted Security Groups versus ACLs - Whiteboarding See the guru 10 part VPC lab course I took last night (udemy) for more VPC details. VPC goes in a region Security group is a firewall Security group vs Access Control List (SG vs ACL) ACL attached to subnet So it applies to all EC2 instances Security Group attached to EC2 instance Exam question: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. Exam Question: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1 ACL you can set allow or deny Security in layers, so we want Firewall, ACL, and Security Group Security Group is stateful -- ACL is stateless This matters because ACL will not allow outbound response during a single network action Security group allows 2-way connection Networking in General \"Need to know networking to pass the exam.\"","title":"Secure Applications And Architectures"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#specify-secure-applications","text":"Security is Job 0 on AWS. big part of exam: how to secure application tiers how to secure data networking infrastructure for a single VPC application cloud guru vpc (I did this last night)","title":"Specify Secure Applications"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#exam-questions","text":"IAM User: Console access versus programmatic access Console requires username + password Guaranteed exam question: Programmatic access just needs access key and secret Not username / password IAM Policy: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy) IAM Roles: When asked, always pick IAM roles over access keys Exam questions will try to confuse you: cloudtrail vs. cloudwatch cloudtrail is a trail - logs cloudwatch is like watching - metrics VPC: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. VPC: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1","title":"Exam Questions"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#shared-responsibility-model","text":"Shared between AWS and the customer (me).","title":"Shared Responsibility Model"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#aaa-authenticate-authorize-audit","text":"","title":"AAA: Authenticate, Authorize, Audit"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#authenticate","text":"IAM Username/Password Access Key (+ MFA) Federation","title":"Authenticate"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#authorize","text":"IAM Policies","title":"Authorize"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#audit","text":"CloudTrail - region specific logging","title":"Audit"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#iam-groups","text":"Groups can be nested Attach IAM Policy to group You don't want to attach policies to users. Users can be in multiple groups There is no default group for all users Exam Question: By default users have access to nothing You must attach an IAM policy (or group with an IAM policy)","title":"IAM Groups"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#iam-roles","text":"Identity created for specific permissions Can be assumed by people who need it (and have perms to do so) Roles can be assumed by users, applications, or assigned to resources/services. You can only assume one role at a time When asked, always pick IAM roles over access keys Best solution for giving access to security in multiple accounts Cross account ?? Best way to give access to other organizations Need to use API to enumerate roles for a user, then compare permissions","title":"IAM Roles"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#web-identity-federation","text":"AWS Security Token Service (STS) Temporary credentials for access to resources (e.g. 24 hour max)","title":"Web Identity Federation"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#iam-policies","text":"There is a great simulation tool for testing Attach permissions specify type of access actions that can be performed resources on which actions can be performed etc Principle of least privilege JSON format","title":"IAM Policies"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#calculating-permissions","text":"Everything implicitly denied Explicit allows override implicit denies Explicit denies override explicit allows","title":"Calculating Permissions"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#aws-cloudtrail","text":"Logging (see page for details)","title":"AWS CloudTrail"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#s3-security","text":"Bucket Policy ACL (Access Control Lists) Applied to specific objects within the bucket","title":"S3 Security"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#encryption","text":"Encrypt S3 Buckets Off by default S3 Versioning Once turned on, cannot turn off maybe possible to suspend Increases storage costs, previous versions are not deleted","title":"Encryption"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#security-groups-versus-acls-whiteboarding","text":"See the guru 10 part VPC lab course I took last night (udemy) for more VPC details. VPC goes in a region Security group is a firewall Security group vs Access Control List (SG vs ACL) ACL attached to subnet So it applies to all EC2 instances Security Group attached to EC2 instance Exam question: What is the biggest size and smallest size for VPC CIDR. Biggest: /16 Smallest: /28 The allowed block size is between a /28 netmask and /16 netmask. Exam Question: Only 1 IGW can be attached to 1 VPC I am not getting enough bandwidth, can I attack an additional internet gateway? NO you can ONLY have 1 ACL you can set allow or deny Security in layers, so we want Firewall, ACL, and Security Group Security Group is stateful -- ACL is stateless This matters because ACL will not allow outbound response during a single network action Security group allows 2-way connection","title":"Security Groups versus ACLs - Whiteboarding"},{"location":"docs/talks/aws.training.solarchitect/secure-applications-and-architectures/#networking-in-general","text":"\"Need to know networking to pass the exam.\"","title":"Networking in General"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/","text":"Part 2 - Scaling Flask for Production. Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link. Scaling Web Servers Problem - one request at a time. Not great. Multiple Threads Limited use of multiple threads because of GIL. Not really great. Multiple processes Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy? Green threads / coroutines - asyncio, gevent, eventlet. Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function). Using Production Web Servers (tag: v0.12) gunicorn Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads. uwsgi nginx Written in C. Ideal for serving static files in production. You expose the static file in the nginx config. Bottlenecks: I/O Bound and CPU Bound I/O Bottlenecks Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous. CPU Bottlenecks Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous. Asynchronous HTTP Requests (tag: v0.13) Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it. Celery Workers (tag: v0.14) There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular. Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens. This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket) Streaming One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask Long polling client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated. WebSocket HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time. SocketIO written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides. Even more Socket.IO. We can now only use gevent or eventlet. See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary. Flask-SocketIO Miguel's project Pure python, translation of the Socket.IO node project for flask. Questions / Notes Flask has a Python profiler.","title":"Notes Partii Trent"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#part-2-scaling-flask-for-production","text":"Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link.","title":"Part 2 - Scaling Flask for Production."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#scaling-web-servers","text":"Problem - one request at a time. Not great.","title":"Scaling Web Servers"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#multiple-threads","text":"Limited use of multiple threads because of GIL. Not really great.","title":"Multiple Threads"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#multiple-processes","text":"Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy?","title":"Multiple processes"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#green-threads-coroutines-asyncio-gevent-eventlet","text":"Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).","title":"Green threads / coroutines - asyncio, gevent, eventlet."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#using-production-web-servers-tag-v012","text":"","title":"Using Production Web Servers (tag: v0.12)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#gunicorn","text":"Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads.","title":"gunicorn"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#uwsgi","text":"","title":"uwsgi"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#nginx","text":"Written in C. Ideal for serving static files in production. You expose the static file in the nginx config.","title":"nginx"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#bottlenecks-io-bound-and-cpu-bound","text":"","title":"Bottlenecks: I/O Bound and CPU Bound"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#io-bottlenecks","text":"Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous.","title":"I/O Bottlenecks"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#cpu-bottlenecks","text":"Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.","title":"CPU Bottlenecks"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#asynchronous-http-requests-tag-v013","text":"Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.","title":"Asynchronous HTTP Requests (tag: v0.13)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#celery-workers-tag-v014","text":"There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.","title":"Celery Workers (tag: v0.14)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#websocket-tag-v015-clients-must-poll-to-stay-up-to-date-we-need-to-use-server-push-to-reduce-load-when-new-stuff-happens","text":"This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket)","title":"Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#streaming","text":"One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask","title":"Streaming"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#long-polling","text":"client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.","title":"Long polling"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#websocket","text":"HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.","title":"WebSocket"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#socketio","text":"written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides.","title":"SocketIO"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#even-more-socketio-we-can-now-only-use-gevent-or-eventlet","text":"See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.","title":"Even more Socket.IO. We can now only use gevent or eventlet."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#flask-socketio","text":"Miguel's project Pure python, translation of the Socket.IO node project for flask.","title":"Flask-SocketIO"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTII_trent/#questions-notes","text":"Flask has a Python profiler.","title":"Questions / Notes"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/","text":"Production Ready Flask App - Part I Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link. 1. Move utility functions to utils.py (tag: v0.2) url_for, timestamp functions. 2. Refactor database models. (tag: v0.3) Avoid cyclic dependency of importing db from controller then importing model from models.py Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded \"from flack import db\". 3. Create an Application Package (tag: v0.4) - Use Flask-Script A newer option exists over Flask-Script but is not yet production ready. Flask-Script is available now: https://flask-script.readthedocs.io/en/latest/ See git diff v0.3 v0.4 between these two tags to understand necessary changes. 4. Refactoring API Authentication (tag: v0.5) - Moved auth stuff to auth.py. There were three auth functions finally imported. Again see git diff v0.4 v0.5 for details. 5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure. To get the overview, checkout this tag and manage.py. Look at file structure. Now we are in a django style construction. tests folder exists alongside flack folder. 6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py. Add a config.py. This is pretty hairy even in django. People solve configuration in different ways. I have a pretty good django dev.cfg/prod.cfg pattern that I would use here. 7. Create an API Blueprint - separate the api. Create: flack/api.py . Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py. 8. Create Stats package. See git diff v0.8 v0.9 9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app. Sometimes it is desirable to work with more than one application Best Example: Unit tests that need applications with different configurations. SPECIAL NOTE: Having app blueprints allows you to have a really elegant test setup and teardown. Howto get the Blueprint working (see git diff v0.9 v.10 for exact code) We need to get rid of app because it will exist outside the context of the controller. Now we can no longer reference app. We must refactor app.config and other references to app. That means no app.debug. To achieve this we can use a Blueprint. Use the current_app context variable to access application. Put application factory function in init .py, see create_app function here. To create an app you now call create_app, pass an application name, and get the app. SQLAlchemy needs the models in init .py because it introspects on the app. You can miss this and maybe the models get imported elsewhere but that is sloppy. 10. Creating an API Package (tag: v0.11) - Turn api.py into a package. This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users. tokens, messages, users become modules inside of the api package. Part 2 - Scaling Flask for Production. Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link. Scaling Web Servers Problem - one request at a time. Not great. Multiple Threads Limited use of multiple threads because of GIL. Not really great. Multiple processes Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy? Green threads / coroutines - asyncio, gevent, eventlet. Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function). Using Production Web Servers (tag: v0.12) gunicorn Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads. uwsgi nginx Written in C. Ideal for serving static files in production. You expose the static file in the nginx config. Bottlenecks: I/O Bound and CPU Bound I/O Bottlenecks Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous. CPU Bottlenecks Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous. Asynchronous HTTP Requests (tag: v0.13) Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it. Celery Workers (tag: v0.14) There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular. Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens. This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket) Streaming One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask Long polling client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated. WebSocket HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time. SocketIO written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides. Even more Socket.IO. We can now only use gevent or eventlet. See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary. Flask-SocketIO Miguel's project Pure python, translation of the Socket.IO node project for flask. Questions / Notes Flask has a Python profiler.","title":"Notes Parti Trent"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#production-ready-flask-app-part-i","text":"Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link.","title":"Production Ready Flask App - Part I"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#1-move-utility-functions-to-utilspy-tag-v02","text":"url_for, timestamp functions.","title":"1. Move utility functions to utils.py (tag: v0.2)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#2-refactor-database-models-tag-v03","text":"Avoid cyclic dependency of importing db from controller then importing model from models.py Add a check for main in models.py, if there isn't a main then fallback to ugly hardcoded \"from flack import db\".","title":"2. Refactor database models. (tag: v0.3)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#3-create-an-application-package-tag-v04-use-flask-script","text":"A newer option exists over Flask-Script but is not yet production ready. Flask-Script is available now: https://flask-script.readthedocs.io/en/latest/ See git diff v0.3 v0.4 between these two tags to understand necessary changes.","title":"3. Create an Application Package (tag: v0.4) - Use Flask-Script"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#4-refactoring-api-authentication-tag-v05-","text":"Moved auth stuff to auth.py. There were three auth functions finally imported. Again see git diff v0.4 v0.5 for details.","title":"4. Refactoring API Authentication (tag: v0.5) -"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#5-refactoring-tests-tag-v06-change-to-a-package-style-folder-structure","text":"To get the overview, checkout this tag and manage.py. Look at file structure. Now we are in a django style construction. tests folder exists alongside flack folder.","title":"5. Refactoring Tests (tag: v0.6) - Change to a package style folder structure."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#6-refactoring-configuration-tag-v07-add-a-configpy-next-to-managepy","text":"Add a config.py. This is pretty hairy even in django. People solve configuration in different ways. I have a pretty good django dev.cfg/prod.cfg pattern that I would use here.","title":"6. Refactoring Configuration (tag: v0.7) - Add a config.py next to manage.py."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#7-create-an-api-blueprint-separate-the-api","text":"Create: flack/api.py . Use a Blueprint. Blueprint is initialized where app creation is done, currently flack.py.","title":"7. Create an API Blueprint - separate the api."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#8-create-stats-package","text":"See git diff v0.8 v0.9","title":"8. Create Stats package."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#9-using-an-application-factory-function-tag-v010-use-a-blueprint-for-app","text":"Sometimes it is desirable to work with more than one application Best Example: Unit tests that need applications with different configurations.","title":"9. Using an application Factory Function (tag: v0.10) - use a Blueprint for app."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#special-note","text":"Having app blueprints allows you to have a really elegant test setup and teardown.","title":"SPECIAL NOTE:"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#howto-get-the-blueprint-working-see-git-diff-v09-v10-for-exact-code","text":"We need to get rid of app because it will exist outside the context of the controller. Now we can no longer reference app. We must refactor app.config and other references to app. That means no app.debug. To achieve this we can use a Blueprint. Use the current_app context variable to access application. Put application factory function in init .py, see create_app function here. To create an app you now call create_app, pass an application name, and get the app. SQLAlchemy needs the models in init .py because it introspects on the app. You can miss this and maybe the models get imported elsewhere but that is sloppy.","title":"Howto get the Blueprint working (see git diff v0.9 v.10 for exact code)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#10-creating-an-api-package-tag-v011-turn-apipy-into-a-package","text":"This is a simple step, make an api folder and break the components of api.py down into the 3 files/modules: tokens, messages, users. tokens, messages, users become modules inside of the api package.","title":"10. Creating an API Package (tag: v0.11) - Turn api.py into a package."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#part-2-scaling-flask-for-production","text":"Notes from Miguel Grinberg's talk on making a production flask app. PyCon 2016 - 20160528 0900 PST Presentation URL: Miguel will put a URL in the github readme and tweet the link.","title":"Part 2 - Scaling Flask for Production."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#scaling-web-servers","text":"Problem - one request at a time. Not great.","title":"Scaling Web Servers"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#multiple-threads","text":"Limited use of multiple threads because of GIL. Not really great.","title":"Multiple Threads"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#multiple-processes","text":"Obviously multiple apps sounds nice. Each process has its own set of things. What about SQLAlchemy?","title":"Multiple processes"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#green-threads-coroutines-asyncio-gevent-eventlet","text":"Flask doesn't support asyncio. Flask does support gevent, eventlet. IO and standard library threading functions are incompatible. How about manually triggering a switch? - sleep function to take a break and let other threads have a turn. Note on gevent and eventlet -- A lot of people get this wrong on stack overflow. This stuff isn't for cpu intensive work. All green threads need a chance to run and CPU must be available or sleeps must run very often to let the scheduler switch. Miguel's IO library is for this. Read more about this. I have it in other notes but a google search will suffice. Both eventlet and gevent allow monkeypatching to coroutine friendly functions (overwrite standard library function with the coroutine friendly function).","title":"Green threads / coroutines - asyncio, gevent, eventlet."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#using-production-web-servers-tag-v012","text":"","title":"Using Production Web Servers (tag: v0.12)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#gunicorn","text":"Limited load balancing - Why limited? I will have to look this up. Written in Python - robust but not lightning fast Supports multiple processes, and eventlet or gevent green threads.","title":"gunicorn"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#uwsgi","text":"","title":"uwsgi"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#nginx","text":"Written in C. Ideal for serving static files in production. You expose the static file in the nginx config.","title":"nginx"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#bottlenecks-io-bound-and-cpu-bound","text":"","title":"Bottlenecks: I/O Bound and CPU Bound"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#io-bottlenecks","text":"Flack example: scraping links included in posts Solution: concurrent request handlers through multiple threads, processes, or green threads. Make I/O heavy requests asynchronous.","title":"I/O Bottlenecks"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#cpu-bottlenecks","text":"Flack example: rendering posts from markdown to HTML Solution: Offload CPU intensive requests to auxiliary threads or processes to keep the server unblocked. Rephrased: make CPU intensive requests asynchronous.","title":"CPU Bottlenecks"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#asynchronous-http-requests-tag-v013","text":"Request starts background work, gives a status 202. Goes back to listening requests. Location header has a status URL where the client can ask for status for the asynchronous task. Request to status URL returns 202 while the request is still in progress. When complete, (see presentation for details) There is a decorator for this in flack , migue's app.... @async decorator. That's all that is necessary!!! This is almost too easy. If you git diff v0.12 v0.13 and view the tasks module, you can see async implemenation. note that request.environ has environmental information to build a request object. This way miguel can build his own request object. Miguel uses threading here, I think this won't matter because the threads are being used inside of a single request. We went into great detail about the @async decorator code. Miguel mentioned maybe he should test it more and build a flask extension out of it. Probably production ready but definitely not widely tested. Async really gets into the guts of flask and does a lot of stuff flask does manually building the response etc. it looks good but it just isn't vetted and I don't know enough flask futs to vet it.","title":"Asynchronous HTTP Requests (tag: v0.13)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#celery-workers-tag-v014","text":"There's a wrapper in manage.py . Celery is integrated into the previous async section. For quick setup redis works with Celery. Celery needs to be available in init .py for the same reason as the model. Flask uses the context apparently. There must be something else since flask doesn't really 'expect' celery. Maybe celery is loaded up in the app then refers to stuff.. Still seems a little circular.","title":"Celery Workers (tag: v0.14)"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#websocket-tag-v015-clients-must-poll-to-stay-up-to-date-we-need-to-use-server-push-to-reduce-load-when-new-stuff-happens","text":"This \"server-push\" websocket model will reduce load, removing all redundant quests. The previous version used 2 requests per second per client just to stay up to date. Options: 1. Streaming 2. Long-polling 3. WebSocket 4. Socket.IO (long-polling + WebSocket)","title":"Websocket (tag: v0.15) - clients must 'poll' to stay up to date... we need to use 'server-push' to reduce load when new stuff happens."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#streaming","text":"One of Miguel Grinberg's Posts using Streaming (1): http://blog.miguelgrinberg.com/post/video-streaming-with-flask","title":"Streaming"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#long-polling","text":"client asks 'is there anything new?' but the server doesn't respond right away. it waits maybe 10 seconds because nothing happened. it does block the thread but it doesn't respond until something changes or until the long poll times out. A new one can then be generated.","title":"Long polling"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#websocket","text":"HTML5 Standard. Not HTTP anymore. Both connections can write to the other side at any time. Any side can write/read at any time.","title":"WebSocket"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#socketio","text":"written in JS. Node.js service. SocketIO Protocol supports WebSocket and falls aback to long-polling if WebSocket isn't supported by the client. Type 1: Python client: use socketio.emit class in a push_model method. See slides. Javascript server: socketio node.js service Type 2: Python Server: @socketio.on() decorator Javascript client: socket.emit(). See slides.","title":"SocketIO"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#even-more-socketio-we-can-now-only-use-gevent-or-eventlet","text":"See the events.py module git diff v0.14 v0.15 , added to manage events. I'm pretty far afield of things I have actually done at this point so my thoughts aren't very helpful. This code is starting to look a ton like django. However, I don't think Django has async built in either, so maybe this is a limit for out-of-the-box django as well. More research needed. Need an auxiliary wsgi process for socketio. There is a second wsgi_aux.py or something in the source. Miguel used eventlet.monkey_patch() to replace a bunch of stuff with eventlet counterparts. This seems pretty specific, better know what you are doing and read the monkey patch code. manage.py runserver needs socketio stuff. Socketio needs socketio.run, rather than app.run, so this gets added in. Also see tests. socketio has its own test client. Finally nginx has requirements for load balancing. Nginx option \"sticky sessions\" Grep the flack.conf in the nginx folder for ip_hash and read about this nginx option. Socketio is stateful and rest APIs are stateless so this option is necessary.","title":"Even more Socket.IO. We can now only use gevent or eventlet."},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#flask-socketio","text":"Miguel's project Pure python, translation of the Socket.IO node project for flask.","title":"Flask-SocketIO"},{"location":"docs/talks/flack_miguel_grinberg/NOTES_PARTI_trent/#questions-notes","text":"Flask has a Python profiler.","title":"Questions / Notes"},{"location":"reference/portray/","text":"Module portray Sub-modules portray.api portray.cli portray.config portray.exceptions portray.logo portray.render","title":"Index"},{"location":"reference/portray/#module-portray","text":"","title":"Module portray"},{"location":"reference/portray/#sub-modules","text":"portray.api portray.cli portray.config portray.exceptions portray.logo portray.render","title":"Sub-modules"},{"location":"reference/portray/api/","text":"Module portray.api This module defines the programmatic API that can be used to interact with portray to generate and view documentation. If you want to extend portray or use it directly from within Python - this is the place to start. View Source \"\"\"This module defines the programmatic API that can be used to interact with `portray` to generate and view documentation. If you want to extend `portray` or use it directly from within Python - this is the place to start. \"\"\" import os import webbrowser from typing import Dict , Union import mkdocs.commands.gh_deploy from livereload import Server from portray import config , logo , render def as_html ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , output_dir : str = \"site\" , overwrite : bool = False , modules : list = None , # type: ignore ) -> None : \"\"\"Produces HTML documentation for a Python project placing it into output_dir. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *output_dir*: The directory to place the generated HTML into. - *overwrite*: If set to `True` any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified `output_dir` the command will fail with a `DocumentationAlreadyExists` exception. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () render . documentation ( project_configuration ( directory , config_file , modules = modules , output_dir = output_dir ), overwrite = overwrite , ) print ( logo . ascii_art ) print ( f \"Documentation successfully generated into ` { os . path . abspath ( output_dir ) } ` !\" ) def in_browser ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , port : int = None , # type: ignore host : str = None , # type: ignore modules : list = None , # type: ignore reload : bool = False , ) -> None : \"\"\"Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\"127.0.0.1\"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () server ( directory = directory , config_file = config_file , open_browser = True , port = port , host = host , modules = modules , reload = reload , ) def server ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , open_browser : bool = False , port : int = None , # type: ignore host : str = None , # type: ignore modules : list = None , # type: ignore reload : bool = False , ) -> None : \"\"\"Runs a development webserver enabling you to browse documentation locally. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *open_browser*: If true a browser will be opened pointing at the documentation server - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\"127.0.0.1\"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules = modules ) host = host or project_config [ \"host\" ] port = port or project_config [ \"port\" ] with render . documentation_in_temp_folder ( project_config ) as ( sources_folder , docs_folder ): print ( logo . ascii_art ) live_server = Server () if reload : def reloader (): # pragma: no cover sources_old = sources_folder + \".old\" docs_old = docs_folder + \".old\" with render . documentation_in_temp_folder ( project_config ) as ( sources_new , docs_new ): # cause as little churn as possible to the server watchers os . rename ( sources_folder , sources_old ) os . rename ( sources_new , sources_folder ) os . rename ( sources_old , sources_new ) os . rename ( docs_folder , docs_old ) os . rename ( docs_new , docs_folder ) os . rename ( docs_old , docs_new ) # all directories that feed documentation_in_temp_folder watch_dirs = set ( ( project_config [ \"directory\" ], project_config [ \"docs_dir\" ], * project_config [ \"extra_dirs\" ], ) ) if \"docs_dir\" in project_config [ \"mkdocs\" ]: watch_dirs . add ( project_config [ \"mkdocs\" ][ \"docs_dir\" ]) if \"site_dir\" in project_config [ \"mkdocs\" ]: watch_dirs . add ( project_config [ \"mkdocs\" ][ \"site_dir\" ]) for watch_dir in watch_dirs . difference ( set (( sources_folder , docs_folder ))): live_server . watch ( watch_dir , reloader ) if open_browser : webbrowser . open_new ( f \"http:// { host } : { port } \" ) live_server . serve ( root = docs_folder , host = host , port = port , restart_delay = 0 ) def project_configuration ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , modules : list = None , # type: ignore output_dir : str = None , # type: ignore ) -> dict : \"\"\"Returns the configuration associated with a project. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *modules*: One or more modules to include in the configuration for reference rendering \"\"\" overrides : Dict [ str , Union [ str , list ]] = {} if modules : overrides [ \"modules\" ] = modules if output_dir : overrides [ \"output_dir\" ] = output_dir directory = directory if directory else os . getcwd () return config . project ( directory = directory , config_file = config_file , ** overrides ) def on_github_pages ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , message : str = None , # type: ignore force : bool = False , ignore_version : bool = False , modules : list = None , # type: ignore ) -> None : \"\"\"Regenerates and deploys the documentation to GitHub pages. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *message*: The commit message to use when uploading your documentation. - *force*: Force the push to the repository. - *ignore_version*: Ignore check that build is not being deployed with an old version. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules ) with render . documentation_in_temp_folder ( project_config ) as ( _ , site_dir ): project_config [ \"mkdocs\" ][ \"site_dir\" ] = site_dir conf = render . _mkdocs_config ( project_config [ \"mkdocs\" ]) conf . config_file_path = directory mkdocs . commands . gh_deploy . gh_deploy ( conf , message = message , force = force , ignore_version = ignore_version ) print ( logo . ascii_art ) print ( \"Documentation successfully generated and pushed!\" ) Functions as_html def as_html ( directory : str = '' , config_file : str = 'pyproject.toml' , output_dir : str = 'site' , overwrite : bool = False , modules : list = None ) -> None Produces HTML documentation for a Python project placing it into output_dir. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. output_dir : The directory to place the generated HTML into. overwrite : If set to True any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified output_dir the command will fail with a DocumentationAlreadyExists exception. modules : One or more modules to render reference documentation for View Source def as_html ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , output_dir : str = \"site\" , overwrite : bool = False , modules : list = None , # type: ignore ) -> None : \" \"\" Produces HTML documentation for a Python project placing it into output_dir. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *output_dir*: The directory to place the generated HTML into. - *overwrite*: If set to `True` any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified `output_dir` the command will fail with a `DocumentationAlreadyExists` exception. - *modules*: One or more modules to render reference documentation for \"\" \" directory = directory if directory else os . getcwd () render . documentation ( project_configuration ( directory , config_file , modules = modules , output_dir = output_dir ), overwrite = overwrite , ) print ( logo . ascii_art ) print ( f \"Documentation successfully generated into `{os.path.abspath(output_dir)}` !\" ) in_browser def in_browser ( directory : str = '' , config_file : str = 'pyproject.toml' , port : int = None , host : str = None , modules : list = None , reload : bool = False ) -> None Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. port : The port to expose your documentation on (defaults to: 8000 ) host : The host to expose your documentation on (defaults to \"127.0.0.1\" ) modules : One or more modules to render reference documentation for reload : If true the server will live load any changes View Source def in_browser ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , port : int = None , # type : ignore host : str = None , # type : ignore modules : list = None , # type : ignore reload : bool = False , ) -> None : \"\"\"Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\" 127.0.0.1 \"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () server ( directory = directory , config_file = config_file , open_browser = True , port = port , host = host , modules = modules , reload = reload , ) on_github_pages def on_github_pages ( directory : str = '' , config_file : str = 'pyproject.toml' , message : str = None , force : bool = False , ignore_version : bool = False , modules : list = None ) -> None Regenerates and deploys the documentation to GitHub pages. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. message : The commit message to use when uploading your documentation. force : Force the push to the repository. ignore_version : Ignore check that build is not being deployed with an old version. modules : One or more modules to render reference documentation for View Source def on_github_pages ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , message : str = None , # type : ignore force : bool = False , ignore_version : bool = False , modules : list = None , # type : ignore ) -> None : \"\"\"Regenerates and deploys the documentation to GitHub pages. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *message*: The commit message to use when uploading your documentation. - *force*: Force the push to the repository. - *ignore_version*: Ignore check that build is not being deployed with an old version. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules ) with render . documentation_in_temp_folder ( project_config ) as ( _ , site_dir ) : project_config [ \"mkdocs\" ][ \"site_dir\" ] = site_dir conf = render . _mkdocs_config ( project_config [ \"mkdocs\" ] ) conf . config_file_path = directory mkdocs . commands . gh_deploy . gh_deploy ( conf , message = message , force = force , ignore_version = ignore_version ) print ( logo . ascii_art ) print ( \"Documentation successfully generated and pushed!\" ) project_configuration def project_configuration ( directory : str = '' , config_file : str = 'pyproject.toml' , modules : list = None , output_dir : str = None ) -> dict Returns the configuration associated with a project. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. modules : One or more modules to include in the configuration for reference rendering View Source def project_configuration ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , modules : list = None , # type : ignore output_dir : str = None , # type : ignore ) -> dict : \"\"\"Returns the configuration associated with a project. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *modules*: One or more modules to include in the configuration for reference rendering \"\"\" overrides : Dict [ str, Union[str, list ] ] = {} if modules : overrides [ \"modules\" ] = modules if output_dir : overrides [ \"output_dir\" ] = output_dir directory = directory if directory else os . getcwd () return config . project ( directory = directory , config_file = config_file , ** overrides ) server def server ( directory : str = '' , config_file : str = 'pyproject.toml' , open_browser : bool = False , port : int = None , host : str = None , modules : list = None , reload : bool = False ) -> None Runs a development webserver enabling you to browse documentation locally. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. open_browser : If true a browser will be opened pointing at the documentation server port : The port to expose your documentation on (defaults to: 8000 ) host : The host to expose your documentation on (defaults to \"127.0.0.1\" ) modules : One or more modules to render reference documentation for reload : If true the server will live load any changes View Source def server ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , open_browser : bool = False , port : int = None , # type : ignore host : str = None , # type : ignore modules : list = None , # type : ignore reload : bool = False , ) -> None : \"\"\"Runs a development webserver enabling you to browse documentation locally. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *open_browser*: If true a browser will be opened pointing at the documentation server - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\" 127.0.0.1 \"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules = modules ) host = host or project_config [ \"host\" ] port = port or project_config [ \"port\" ] with render . documentation_in_temp_folder ( project_config ) as ( sources_folder , docs_folder ) : print ( logo . ascii_art ) live_server = Server () if reload : def reloader () : # pragma : no cover sources_old = sources_folder + \".old\" docs_old = docs_folder + \".old\" with render . documentation_in_temp_folder ( project_config ) as ( sources_new , docs_new ) : # cause as little churn as possible to the server watchers os . rename ( sources_folder , sources_old ) os . rename ( sources_new , sources_folder ) os . rename ( sources_old , sources_new ) os . rename ( docs_folder , docs_old ) os . rename ( docs_new , docs_folder ) os . rename ( docs_old , docs_new ) # all directories that feed documentation_in_temp_folder watch_dirs = set ( ( project_config [ \"directory\" ] , project_config [ \"docs_dir\" ] , * project_config [ \"extra_dirs\" ] , ) ) if \"docs_dir\" in project_config [ \"mkdocs\" ] : watch_dirs . add ( project_config [ \"mkdocs\" ][ \"docs_dir\" ] ) if \"site_dir\" in project_config [ \"mkdocs\" ] : watch_dirs . add ( project_config [ \"mkdocs\" ][ \"site_dir\" ] ) for watch_dir in watch_dirs . difference ( set (( sources_folder , docs_folder ))) : live_server . watch ( watch_dir , reloader ) if open_browser : webbrowser . open_new ( f \"http://{host}:{port}\" ) live_server . serve ( root = docs_folder , host = host , port = port , restart_delay = 0 )","title":"API"},{"location":"reference/portray/api/#module-portrayapi","text":"This module defines the programmatic API that can be used to interact with portray to generate and view documentation. If you want to extend portray or use it directly from within Python - this is the place to start. View Source \"\"\"This module defines the programmatic API that can be used to interact with `portray` to generate and view documentation. If you want to extend `portray` or use it directly from within Python - this is the place to start. \"\"\" import os import webbrowser from typing import Dict , Union import mkdocs.commands.gh_deploy from livereload import Server from portray import config , logo , render def as_html ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , output_dir : str = \"site\" , overwrite : bool = False , modules : list = None , # type: ignore ) -> None : \"\"\"Produces HTML documentation for a Python project placing it into output_dir. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *output_dir*: The directory to place the generated HTML into. - *overwrite*: If set to `True` any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified `output_dir` the command will fail with a `DocumentationAlreadyExists` exception. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () render . documentation ( project_configuration ( directory , config_file , modules = modules , output_dir = output_dir ), overwrite = overwrite , ) print ( logo . ascii_art ) print ( f \"Documentation successfully generated into ` { os . path . abspath ( output_dir ) } ` !\" ) def in_browser ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , port : int = None , # type: ignore host : str = None , # type: ignore modules : list = None , # type: ignore reload : bool = False , ) -> None : \"\"\"Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\"127.0.0.1\"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () server ( directory = directory , config_file = config_file , open_browser = True , port = port , host = host , modules = modules , reload = reload , ) def server ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , open_browser : bool = False , port : int = None , # type: ignore host : str = None , # type: ignore modules : list = None , # type: ignore reload : bool = False , ) -> None : \"\"\"Runs a development webserver enabling you to browse documentation locally. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *open_browser*: If true a browser will be opened pointing at the documentation server - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\"127.0.0.1\"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules = modules ) host = host or project_config [ \"host\" ] port = port or project_config [ \"port\" ] with render . documentation_in_temp_folder ( project_config ) as ( sources_folder , docs_folder ): print ( logo . ascii_art ) live_server = Server () if reload : def reloader (): # pragma: no cover sources_old = sources_folder + \".old\" docs_old = docs_folder + \".old\" with render . documentation_in_temp_folder ( project_config ) as ( sources_new , docs_new ): # cause as little churn as possible to the server watchers os . rename ( sources_folder , sources_old ) os . rename ( sources_new , sources_folder ) os . rename ( sources_old , sources_new ) os . rename ( docs_folder , docs_old ) os . rename ( docs_new , docs_folder ) os . rename ( docs_old , docs_new ) # all directories that feed documentation_in_temp_folder watch_dirs = set ( ( project_config [ \"directory\" ], project_config [ \"docs_dir\" ], * project_config [ \"extra_dirs\" ], ) ) if \"docs_dir\" in project_config [ \"mkdocs\" ]: watch_dirs . add ( project_config [ \"mkdocs\" ][ \"docs_dir\" ]) if \"site_dir\" in project_config [ \"mkdocs\" ]: watch_dirs . add ( project_config [ \"mkdocs\" ][ \"site_dir\" ]) for watch_dir in watch_dirs . difference ( set (( sources_folder , docs_folder ))): live_server . watch ( watch_dir , reloader ) if open_browser : webbrowser . open_new ( f \"http:// { host } : { port } \" ) live_server . serve ( root = docs_folder , host = host , port = port , restart_delay = 0 ) def project_configuration ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , modules : list = None , # type: ignore output_dir : str = None , # type: ignore ) -> dict : \"\"\"Returns the configuration associated with a project. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *modules*: One or more modules to include in the configuration for reference rendering \"\"\" overrides : Dict [ str , Union [ str , list ]] = {} if modules : overrides [ \"modules\" ] = modules if output_dir : overrides [ \"output_dir\" ] = output_dir directory = directory if directory else os . getcwd () return config . project ( directory = directory , config_file = config_file , ** overrides ) def on_github_pages ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , message : str = None , # type: ignore force : bool = False , ignore_version : bool = False , modules : list = None , # type: ignore ) -> None : \"\"\"Regenerates and deploys the documentation to GitHub pages. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *message*: The commit message to use when uploading your documentation. - *force*: Force the push to the repository. - *ignore_version*: Ignore check that build is not being deployed with an old version. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules ) with render . documentation_in_temp_folder ( project_config ) as ( _ , site_dir ): project_config [ \"mkdocs\" ][ \"site_dir\" ] = site_dir conf = render . _mkdocs_config ( project_config [ \"mkdocs\" ]) conf . config_file_path = directory mkdocs . commands . gh_deploy . gh_deploy ( conf , message = message , force = force , ignore_version = ignore_version ) print ( logo . ascii_art ) print ( \"Documentation successfully generated and pushed!\" )","title":"Module portray.api"},{"location":"reference/portray/api/#functions","text":"","title":"Functions"},{"location":"reference/portray/api/#as_html","text":"def as_html ( directory : str = '' , config_file : str = 'pyproject.toml' , output_dir : str = 'site' , overwrite : bool = False , modules : list = None ) -> None Produces HTML documentation for a Python project placing it into output_dir. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. output_dir : The directory to place the generated HTML into. overwrite : If set to True any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified output_dir the command will fail with a DocumentationAlreadyExists exception. modules : One or more modules to render reference documentation for View Source def as_html ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , output_dir : str = \"site\" , overwrite : bool = False , modules : list = None , # type: ignore ) -> None : \" \"\" Produces HTML documentation for a Python project placing it into output_dir. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *output_dir*: The directory to place the generated HTML into. - *overwrite*: If set to `True` any existing documentation output will be removed before generating new documentation. Otherwise, if documentation exists in the specified `output_dir` the command will fail with a `DocumentationAlreadyExists` exception. - *modules*: One or more modules to render reference documentation for \"\" \" directory = directory if directory else os . getcwd () render . documentation ( project_configuration ( directory , config_file , modules = modules , output_dir = output_dir ), overwrite = overwrite , ) print ( logo . ascii_art ) print ( f \"Documentation successfully generated into `{os.path.abspath(output_dir)}` !\" )","title":"as_html"},{"location":"reference/portray/api/#in_browser","text":"def in_browser ( directory : str = '' , config_file : str = 'pyproject.toml' , port : int = None , host : str = None , modules : list = None , reload : bool = False ) -> None Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. port : The port to expose your documentation on (defaults to: 8000 ) host : The host to expose your documentation on (defaults to \"127.0.0.1\" ) modules : One or more modules to render reference documentation for reload : If true the server will live load any changes View Source def in_browser ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , port : int = None , # type : ignore host : str = None , # type : ignore modules : list = None , # type : ignore reload : bool = False , ) -> None : \"\"\"Opens your default webbrowser pointing to a locally started development webserver enabling you to browse documentation locally - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\" 127.0.0.1 \"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () server ( directory = directory , config_file = config_file , open_browser = True , port = port , host = host , modules = modules , reload = reload , )","title":"in_browser"},{"location":"reference/portray/api/#on_github_pages","text":"def on_github_pages ( directory : str = '' , config_file : str = 'pyproject.toml' , message : str = None , force : bool = False , ignore_version : bool = False , modules : list = None ) -> None Regenerates and deploys the documentation to GitHub pages. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. message : The commit message to use when uploading your documentation. force : Force the push to the repository. ignore_version : Ignore check that build is not being deployed with an old version. modules : One or more modules to render reference documentation for View Source def on_github_pages ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , message : str = None , # type : ignore force : bool = False , ignore_version : bool = False , modules : list = None , # type : ignore ) -> None : \"\"\"Regenerates and deploys the documentation to GitHub pages. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *message*: The commit message to use when uploading your documentation. - *force*: Force the push to the repository. - *ignore_version*: Ignore check that build is not being deployed with an old version. - *modules*: One or more modules to render reference documentation for \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules ) with render . documentation_in_temp_folder ( project_config ) as ( _ , site_dir ) : project_config [ \"mkdocs\" ][ \"site_dir\" ] = site_dir conf = render . _mkdocs_config ( project_config [ \"mkdocs\" ] ) conf . config_file_path = directory mkdocs . commands . gh_deploy . gh_deploy ( conf , message = message , force = force , ignore_version = ignore_version ) print ( logo . ascii_art ) print ( \"Documentation successfully generated and pushed!\" )","title":"on_github_pages"},{"location":"reference/portray/api/#project_configuration","text":"def project_configuration ( directory : str = '' , config_file : str = 'pyproject.toml' , modules : list = None , output_dir : str = None ) -> dict Returns the configuration associated with a project. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. modules : One or more modules to include in the configuration for reference rendering View Source def project_configuration ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , modules : list = None , # type : ignore output_dir : str = None , # type : ignore ) -> dict : \"\"\"Returns the configuration associated with a project. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *modules*: One or more modules to include in the configuration for reference rendering \"\"\" overrides : Dict [ str, Union[str, list ] ] = {} if modules : overrides [ \"modules\" ] = modules if output_dir : overrides [ \"output_dir\" ] = output_dir directory = directory if directory else os . getcwd () return config . project ( directory = directory , config_file = config_file , ** overrides )","title":"project_configuration"},{"location":"reference/portray/api/#server","text":"def server ( directory : str = '' , config_file : str = 'pyproject.toml' , open_browser : bool = False , port : int = None , host : str = None , modules : list = None , reload : bool = False ) -> None Runs a development webserver enabling you to browse documentation locally. directory : The root folder of your project. config_file : The TOML formatted config file you wish to use. open_browser : If true a browser will be opened pointing at the documentation server port : The port to expose your documentation on (defaults to: 8000 ) host : The host to expose your documentation on (defaults to \"127.0.0.1\" ) modules : One or more modules to render reference documentation for reload : If true the server will live load any changes View Source def server ( directory : str = \"\" , config_file : str = \"pyproject.toml\" , open_browser : bool = False , port : int = None , # type : ignore host : str = None , # type : ignore modules : list = None , # type : ignore reload : bool = False , ) -> None : \"\"\"Runs a development webserver enabling you to browse documentation locally. - *directory*: The root folder of your project. - *config_file*: The [TOML](https://github.com/toml-lang/toml#toml) formatted config file you wish to use. - *open_browser*: If true a browser will be opened pointing at the documentation server - *port*: The port to expose your documentation on (defaults to: `8000`) - *host*: The host to expose your documentation on (defaults to `\" 127.0.0.1 \"`) - *modules*: One or more modules to render reference documentation for - *reload*: If true the server will live load any changes \"\"\" directory = directory if directory else os . getcwd () project_config = project_configuration ( directory , config_file , modules = modules ) host = host or project_config [ \"host\" ] port = port or project_config [ \"port\" ] with render . documentation_in_temp_folder ( project_config ) as ( sources_folder , docs_folder ) : print ( logo . ascii_art ) live_server = Server () if reload : def reloader () : # pragma : no cover sources_old = sources_folder + \".old\" docs_old = docs_folder + \".old\" with render . documentation_in_temp_folder ( project_config ) as ( sources_new , docs_new ) : # cause as little churn as possible to the server watchers os . rename ( sources_folder , sources_old ) os . rename ( sources_new , sources_folder ) os . rename ( sources_old , sources_new ) os . rename ( docs_folder , docs_old ) os . rename ( docs_new , docs_folder ) os . rename ( docs_old , docs_new ) # all directories that feed documentation_in_temp_folder watch_dirs = set ( ( project_config [ \"directory\" ] , project_config [ \"docs_dir\" ] , * project_config [ \"extra_dirs\" ] , ) ) if \"docs_dir\" in project_config [ \"mkdocs\" ] : watch_dirs . add ( project_config [ \"mkdocs\" ][ \"docs_dir\" ] ) if \"site_dir\" in project_config [ \"mkdocs\" ] : watch_dirs . add ( project_config [ \"mkdocs\" ][ \"site_dir\" ] ) for watch_dir in watch_dirs . difference ( set (( sources_folder , docs_folder ))) : live_server . watch ( watch_dir , reloader ) if open_browser : webbrowser . open_new ( f \"http://{host}:{port}\" ) live_server . serve ( root = docs_folder , host = host , port = port , restart_delay = 0 )","title":"server"},{"location":"reference/portray/cli/","text":"Module portray.cli This module defines CLI interaction when using portray . This is powered by hug which means unless necessary it should maintain 1:1 compatibility with the programmatic API definition in the API module portray as_html : Renders the project as HTML into the site or other specified output directory portray in_browser : Runs a server with the rendered documentation pointing a browser to it portray server : Starts a local development server (by default at localhost:8000) portray project_configuration : Returns back the project configuration as determined by portray View Source \"\"\"This module defines CLI interaction when using `portray`. This is powered by [hug](https://github.com/hugapi/hug) which means unless necessary it should maintain 1:1 compatibility with the programmatic API definition in the [API module](/reference/portray/api) - `portray as_html`: Renders the project as HTML into the `site` or other specified output directory - `portray in_browser`: Runs a server with the rendered documentation pointing a browser to it - `portray server`: Starts a local development server (by default at localhost:8000) - `portray project_configuration`: Returns back the project configuration as determined by` portray` \"\"\" from pprint import pprint import hug from portray import api , logo cli = hug . cli ( api = hug . API ( __name__ , doc = logo . ascii_art )) cli ( api . as_html ) cli . output ( pprint )( api . project_configuration ) cli ( api . server ) cli ( api . in_browser ) cli ( api . on_github_pages ) Variables cli","title":"CLI"},{"location":"reference/portray/cli/#module-portraycli","text":"This module defines CLI interaction when using portray . This is powered by hug which means unless necessary it should maintain 1:1 compatibility with the programmatic API definition in the API module portray as_html : Renders the project as HTML into the site or other specified output directory portray in_browser : Runs a server with the rendered documentation pointing a browser to it portray server : Starts a local development server (by default at localhost:8000) portray project_configuration : Returns back the project configuration as determined by portray View Source \"\"\"This module defines CLI interaction when using `portray`. This is powered by [hug](https://github.com/hugapi/hug) which means unless necessary it should maintain 1:1 compatibility with the programmatic API definition in the [API module](/reference/portray/api) - `portray as_html`: Renders the project as HTML into the `site` or other specified output directory - `portray in_browser`: Runs a server with the rendered documentation pointing a browser to it - `portray server`: Starts a local development server (by default at localhost:8000) - `portray project_configuration`: Returns back the project configuration as determined by` portray` \"\"\" from pprint import pprint import hug from portray import api , logo cli = hug . cli ( api = hug . API ( __name__ , doc = logo . ascii_art )) cli ( api . as_html ) cli . output ( pprint )( api . project_configuration ) cli ( api . server ) cli ( api . in_browser ) cli ( api . on_github_pages )","title":"Module portray.cli"},{"location":"reference/portray/cli/#variables","text":"cli","title":"Variables"},{"location":"reference/portray/config/","text":"Module portray.config Defines the configuration defaults and load functions used by portray View Source \"\"\"Defines the configuration defaults and load functions used by `portray`\"\"\" import _ast import ast import os import re import warnings from pathlib import Path from typing import Any , Dict , Optional import mkdocs.config as _mkdocs_config # noqa import mkdocs.exceptions as _mkdocs_exceptions # noqa from git import Repo from toml import load as toml_load from portray.exceptions import NoProjectFound PORTRAY_DEFAULTS = { \"docs_dir\" : \"docs\" , \"extra_dirs\" : [ \"art\" , \"images\" , \"media\" ], \"output_dir\" : \"site\" , \"port\" : 8000 , \"host\" : \"127.0.0.1\" , \"append_directory_to_python_path\" : True , \"include_reference_documentation\" : True , \"labels\" : { \"Cli\" : \"CLI\" , \"Api\" : \"API\" , \"Http\" : \"HTTP\" , \"Pypi\" : \"PyPI\" }, \"extra_markdown_extensions\" : [], } MKDOCS_DEFAULTS : Dict [ str , Any ] = { \"site_name\" : os . path . basename ( os . getcwd ()), \"config_file_path\" : os . getcwd (), \"theme\" : { \"name\" : \"material\" , \"palette\" : { \"primary\" : \"green\" , \"accent\" : \"lightgreen\" }, \"custom_dir\" : os . path . join ( os . path . dirname ( __file__ ), \"mkdocs_templates\" ), }, \"markdown_extensions\" : [ \"admonition\" , \"codehilite\" , \"extra\" , \"pymdownx.details\" , \"pymdownx.highlight\" , ], } PDOCS_DEFAULTS : Dict = { \"overwrite\" : True , \"exclude_source\" : False } def project ( directory : str , config_file : str , ** overrides ) -> dict : \"\"\"Returns back the complete configuration - including all sub configuration components defined below that `portray` was able to determine for the project \"\"\" if not ( os . path . isfile ( os . path . join ( directory , config_file )) or os . path . isfile ( os . path . join ( directory , \"setup.py\" )) or \"modules\" in overrides ): raise NoProjectFound ( directory ) project_config : Dict [ str , Any ] = { ** PORTRAY_DEFAULTS , \"directory\" : directory } if os . path . isfile ( os . path . join ( directory , \"setup.py\" )): project_config . update ( setup_py ( os . path . join ( directory , \"setup.py\" ))) project_config . update ( toml ( os . path . join ( directory , config_file ))) project_config . update ( overrides ) project_config . setdefault ( \"modules\" , [ os . path . basename ( os . getcwd ()) . replace ( \"-\" , \"_\" )]) project_config . setdefault ( \"pdocs\" , {}) . setdefault ( \"modules\" , project_config [ \"modules\" ]) mkdocs_config = project_config . get ( \"mkdocs\" , {}) mkdocs_config . setdefault ( \"extra_markdown_extensions\" , project_config . get ( \"extra_markdown_extensions\" , []) ) project_config [ \"mkdocs\" ] = mkdocs ( directory , ** mkdocs_config ) if \"pdoc3\" in project_config : warnings . warn ( \"pdoc3 config usage is deprecated in favor of pdocs. \" \"pdoc3 section will be ignored. \" , DeprecationWarning , ) project_config [ \"pdocs\" ] = pdocs ( directory , ** project_config . get ( \"pdocs\" , {})) return project_config def setup_py ( location : str ) -> dict : \"\"\"Returns back any configuration info we are able to determine from a setup.py file\"\"\" setup_config = {} try : with open ( location ) as setup_py_file : for node in ast . walk ( ast . parse ( setup_py_file . read ())): if ( type ( node ) == _ast . Call and type ( getattr ( node , \"func\" , None )) == _ast . Name and node . func . id == \"setup\" # type: ignore ): for keyword in node . keywords : # type: ignore if keyword . arg == \"packages\" : setup_config [ \"modules\" ] = ast . literal_eval ( keyword . value ) break break except Exception as error : warnings . warn ( f \"Error ( { error } ) occurred trying to parse setup.py file: { location } \" ) return setup_config def toml ( location : str ) -> dict : \"\"\"Returns back the configuration found within the projects [TOML](https://github.com/toml-lang/toml#toml) config (if there is one). Generally this is a `pyproject.toml` file at the root of the project with a `[tool.portray]` section defined. \"\"\" try : location_exists = os . path . exists ( location ) if not location_exists : warnings . warn ( f ' \\n No config file found at location: \" { location } \"' ) return {} except Exception as detection_error : # pragma: no cover warnings . warn ( f ' \\n Unable to check config at \" { location } \" due to error: { detection_error } ' ) try : toml_config = toml_load ( location ) tools = toml_config . get ( \"tool\" , {}) config = tools . get ( \"portray\" , {}) config [ \"file\" ] = location if \"modules\" not in config : if \"poetry\" in tools and \"name\" in tools [ \"poetry\" ]: config [ \"modules\" ] = [ tools [ \"poetry\" ][ \"name\" ]] elif ( \"flit\" in tools and \"metadata\" in tools [ \"flit\" ] and \"module\" in tools [ \"flit\" ][ \"metadata\" ] ): config [ \"modules\" ] = [ tools [ \"flit\" ][ \"metadata\" ][ \"module\" ]] return config except Exception as load_config_error : warnings . warn ( f ' \\n Config file at \" { location } \" has errors: { load_config_error } ' ) return {} def repository ( directory : str , repo_url : Optional [ str ] = None , repo_name : Optional [ str ] = None , edit_uri : Optional [ str ] = None , normalize_repo_url : bool = True , ** kwargs , ) -> Dict [ str , Optional [ str ]]: \"\"\"Returns back any information that can be determined by introspecting the projects git repo (if there is one). \"\"\" try : if repo_url is None : repo_url = Repo ( directory ) . remotes . origin . url if repo_name is None : match = re . search ( r \"(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)?(/)?\" , repo_url ) if match : path = match . groups ()[ 2 ] else : path = repo_url repo_name = path . split ( \"/\" )[ - 1 ] if repo_name . endswith ( \".git\" ): repo_name = repo_name [: - len ( \".git\" )] if edit_uri is None : if \"github\" in repo_url or \"gitlab\" in repo_url : edit_uri = \"edit/main/\" elif \"bitbucket\" in repo_url : edit_uri = \"src/default/docs/\" if normalize_repo_url : if repo_url . startswith ( \"git@\" ) and \":\" in repo_url : tld , path = repo_url [ 4 :] . split ( \":\" ) repo_url = f \"https:// { tld } / { path } \" elif repo_url . startswith ( \"https://\" ) and \"@\" in repo_url : repo_url = f \"https:// { repo_url . split ( '@' )[ 1 ] } \" if repo_url and \"github\" in repo_url or \"gitlab\" in repo_url or \"bitbucket\" in repo_url : repo_url = repo_url . replace ( \".git\" , \"\" ) return { key : value for key , value in { \"repo_url\" : repo_url , \"repo_name\" : repo_name , \"edit_uri\" : edit_uri , } . items () if value } except Exception : warnings . warn ( \"Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.\" ) return {} def mkdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running mkdocs\"\"\" mkdocs_config : Dict [ str , Any ] = { ** MKDOCS_DEFAULTS , ** repository ( directory , ** overrides ), ** overrides , } theme = mkdocs_config [ \"theme\" ] if theme [ \"name\" ] . lower () == \"material\" : if \"custom_dir\" in theme : theme [ \"custom_dir\" ] = Path ( theme [ \"custom_dir\" ]) . absolute () . as_posix () else : theme [ \"custom_dir\" ] = MKDOCS_DEFAULTS [ \"theme\" ][ \"custom_dir\" ] nav = mkdocs_config . get ( \"nav\" , None ) if nav and hasattr ( nav [ 0 ], \"copy\" ): mkdocs_config [ \"nav\" ] = [ nav_item . copy () for nav_item in nav ] mkdocs_config [ \"markdown_extensions\" ] = mkdocs_config [ \"markdown_extensions\" ] + mkdocs_config . pop ( \"extra_markdown_extensions\" , [] ) return mkdocs_config def pdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running pdocs\"\"\" defaults = { ** PDOCS_DEFAULTS } defaults . update ( overrides ) return defaults Variables MKDOCS_DEFAULTS PDOCS_DEFAULTS PORTRAY_DEFAULTS Functions mkdocs def mkdocs ( directory : str , ** overrides ) -> dict Returns back the configuration that will be used when running mkdocs View Source def mkdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running mkdocs\"\"\" mkdocs_config : Dict [ str , Any ] = { ** MKDOCS_DEFAULTS , ** repository ( directory , ** overrides ), ** overrides , } theme = mkdocs_config [ \"theme\" ] if theme [ \"name\" ]. lower () == \"material\" : if \"custom_dir\" in theme : theme [ \"custom_dir\" ] = Path ( theme [ \"custom_dir\" ]). absolute (). as_posix () else : theme [ \"custom_dir\" ] = MKDOCS_DEFAULTS [ \"theme\" ][ \"custom_dir\" ] nav = mkdocs_config . get ( \"nav\" , None ) if nav and hasattr ( nav [ 0 ], \"copy\" ) : mkdocs_config [ \"nav\" ] = [ nav_item . copy () for nav_item in nav ] mkdocs_config [ \"markdown_extensions\" ] = mkdocs_config [ \"markdown_extensions\" ] + mkdocs_config . pop ( \"extra_markdown_extensions\" , [] ) return mkdocs_config pdocs def pdocs ( directory : str , ** overrides ) -> dict Returns back the configuration that will be used when running pdocs View Source def pdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running pdocs\"\"\" defaults = { ** PDOCS_DEFAULTS } defaults . update ( overrides ) return defaults project def project ( directory : str , config_file : str , ** overrides ) -> dict Returns back the complete configuration - including all sub configuration components defined below that portray was able to determine for the project View Source def project ( directory : str , config_file : str , ** overrides ) -> dict : \" \"\" Returns back the complete configuration - including all sub configuration components defined below that `portray` was able to determine for the project \"\" \" if not ( os . path . isfile ( os . path . join ( directory , config_file )) or os . path . isfile ( os . path . join ( directory , \"setup.py\" )) or \"modules\" in overrides ) : raise NoProjectFound ( directory ) project_config : Dict [ str , Any ] = { ** PORTRAY_DEFAULTS , \"directory\" : directory } if os . path . isfile ( os . path . join ( directory , \"setup.py\" )) : project_config . update ( set up_py ( os . path . join ( directory , \"setup.py\" ))) project_config . update ( toml ( os . path . join ( directory , config_file ))) project_config . update ( overrides ) project_config . set default ( \"modules\" , [ os . path . basename ( os . getcwd ()). replace ( \"-\" , \"_\" ) ] ) project_config . set default ( \"pdocs\" , {} ). set default ( \"modules\" , project_config [ \"modules\" ] ) mkdocs_config = project_config . get ( \"mkdocs\" , {} ) mkdocs_config . set default ( \"extra_markdown_extensions\" , project_config . get ( \"extra_markdown_extensions\" , [] ) ) project_config [ \"mkdocs\" ] = mkdocs ( directory , ** mkdocs_config ) if \"pdoc3\" in project_config : warnings . warn ( \"pdoc3 config usage is deprecated in favor of pdocs. \" \"pdoc3 section will be ignored. \" , DeprecationWarning , ) project_config [ \"pdocs\" ] = pdocs ( directory , ** project_config . get ( \"pdocs\" , {} )) return project_config repository def repository ( directory : str , repo_url : Union [ str , NoneType ] = None , repo_name : Union [ str , NoneType ] = None , edit_uri : Union [ str , NoneType ] = None , normalize_repo_url : bool = True , ** kwargs ) -> Dict [ str , Union [ str , NoneType ]] Returns back any information that can be determined by introspecting the projects git repo (if there is one). View Source def repository ( directory : str , repo_url : Optional [ str ] = None , repo_name : Optional [ str ] = None , edit_uri : Optional [ str ] = None , normalize_repo_url : bool = True , ** kwargs , ) -> Dict [ str , Optional [ str ]] : \"\"\"Returns back any information that can be determined by introspecting the projects git repo ( if there is one ). \"\"\" try : if repo_url is None : repo_url = Repo ( directory ). remotes . origin . url if repo_name is None : match = re . search ( r \"(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)?(/)?\" , repo_url ) if match : path = match . groups ()[ 2 ] else : path = repo_url repo_name = path . split ( \"/\" )[ -1 ] if repo_name . endswith ( \".git\" ) : repo_name = repo_name [ : - len ( \".git\" )] if edit_uri is None : if \"github\" in repo_url or \"gitlab\" in repo_url : edit_uri = \"edit/main/\" elif \"bitbucket\" in repo_url : edit_uri = \"src/default/docs/\" if normalize_repo_url : if repo_url . startswith ( \"git@\" ) and \":\" in repo_url : tld , path = repo_url [ 4 : ]. split ( \":\" ) repo_url = f \"https://{tld}/{path}\" elif repo_url . startswith ( \"https://\" ) and \"@\" in repo_url : repo_url = f \"https://{repo_url.split('@')[1]}\" if repo_url and \"github\" in repo_url or \"gitlab\" in repo_url or \"bitbucket\" in repo_url : repo_url = repo_url . replace ( \".git\" , \"\" ) return { key : value for key , value in { \"repo_url\" : repo_url , \"repo_name\" : repo_name , \"edit_uri\" : edit_uri , }. items () if value } except Exception : warnings . warn ( \"Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.\" ) return {} setup_py def setup_py ( location : str ) -> dict Returns back any configuration info we are able to determine from a setup.py file View Source def setup_py ( location : str ) -> dict : \"\"\"Returns back any configuration info we are able to determine from a setup.py file\"\"\" setup_config = {} try : with open ( location ) as setup_py_file : for node in ast . walk ( ast . parse ( setup_py_file . read ())) : if ( type ( node ) == _ast . Call and type ( getattr ( node , \"func\" , None )) == _ast . Name and node . func . id == \"setup\" # type : ignore ) : for keyword in node . keywords : # type : ignore if keyword . arg == \"packages\" : setup_config [ \"modules\" ] = ast . literal_eval ( keyword . value ) break break except Exception as error : warnings . warn ( f \"Error ({error}) occurred trying to parse setup.py file: {location}\" ) return setup_config toml def toml ( location : str ) -> dict Returns back the configuration found within the projects TOML config (if there is one). Generally this is a pyproject.toml file at the root of the project with a [tool.portray] section defined. View Source def toml ( location : str ) -> dict : \"\"\"Returns back the configuration found within the projects [TOML](https://github.com/toml-lang/toml#toml) config (if there is one). Generally this is a `pyproject.toml` file at the root of the project with a `[tool.portray]` section defined. \"\"\" try : location_exists = os . path . exists ( location ) if not location_exists : warnings . warn ( f ' \\n No config file found at location: \"{location}\"' ) return {} except Exception as detection_error : # pragma: no cover warnings . warn ( f ' \\n Unable to check config at \"{location}\" due to error: {detection_error}' ) try : toml_config = toml_load ( location ) tools = toml_config . get ( \"tool\" , {}) config = tools . get ( \"portray\" , {}) config [ \"file\" ] = location if \"modules\" not in config : if \"poetry\" in tools and \"name\" in tools [ \"poetry\" ]: config [ \"modules\" ] = [ tools [ \"poetry\" ][ \"name\" ]] elif ( \"flit\" in tools and \"metadata\" in tools [ \"flit\" ] and \"module\" in tools [ \"flit\" ][ \"metadata\" ] ): config [ \"modules\" ] = [ tools [ \"flit\" ][ \"metadata\" ][ \"module\" ]] return config except Exception as load_config_error : warnings . warn ( f ' \\n Config file at \"{location}\" has errors: {load_config_error}' ) return {}","title":"Config"},{"location":"reference/portray/config/#module-portrayconfig","text":"Defines the configuration defaults and load functions used by portray View Source \"\"\"Defines the configuration defaults and load functions used by `portray`\"\"\" import _ast import ast import os import re import warnings from pathlib import Path from typing import Any , Dict , Optional import mkdocs.config as _mkdocs_config # noqa import mkdocs.exceptions as _mkdocs_exceptions # noqa from git import Repo from toml import load as toml_load from portray.exceptions import NoProjectFound PORTRAY_DEFAULTS = { \"docs_dir\" : \"docs\" , \"extra_dirs\" : [ \"art\" , \"images\" , \"media\" ], \"output_dir\" : \"site\" , \"port\" : 8000 , \"host\" : \"127.0.0.1\" , \"append_directory_to_python_path\" : True , \"include_reference_documentation\" : True , \"labels\" : { \"Cli\" : \"CLI\" , \"Api\" : \"API\" , \"Http\" : \"HTTP\" , \"Pypi\" : \"PyPI\" }, \"extra_markdown_extensions\" : [], } MKDOCS_DEFAULTS : Dict [ str , Any ] = { \"site_name\" : os . path . basename ( os . getcwd ()), \"config_file_path\" : os . getcwd (), \"theme\" : { \"name\" : \"material\" , \"palette\" : { \"primary\" : \"green\" , \"accent\" : \"lightgreen\" }, \"custom_dir\" : os . path . join ( os . path . dirname ( __file__ ), \"mkdocs_templates\" ), }, \"markdown_extensions\" : [ \"admonition\" , \"codehilite\" , \"extra\" , \"pymdownx.details\" , \"pymdownx.highlight\" , ], } PDOCS_DEFAULTS : Dict = { \"overwrite\" : True , \"exclude_source\" : False } def project ( directory : str , config_file : str , ** overrides ) -> dict : \"\"\"Returns back the complete configuration - including all sub configuration components defined below that `portray` was able to determine for the project \"\"\" if not ( os . path . isfile ( os . path . join ( directory , config_file )) or os . path . isfile ( os . path . join ( directory , \"setup.py\" )) or \"modules\" in overrides ): raise NoProjectFound ( directory ) project_config : Dict [ str , Any ] = { ** PORTRAY_DEFAULTS , \"directory\" : directory } if os . path . isfile ( os . path . join ( directory , \"setup.py\" )): project_config . update ( setup_py ( os . path . join ( directory , \"setup.py\" ))) project_config . update ( toml ( os . path . join ( directory , config_file ))) project_config . update ( overrides ) project_config . setdefault ( \"modules\" , [ os . path . basename ( os . getcwd ()) . replace ( \"-\" , \"_\" )]) project_config . setdefault ( \"pdocs\" , {}) . setdefault ( \"modules\" , project_config [ \"modules\" ]) mkdocs_config = project_config . get ( \"mkdocs\" , {}) mkdocs_config . setdefault ( \"extra_markdown_extensions\" , project_config . get ( \"extra_markdown_extensions\" , []) ) project_config [ \"mkdocs\" ] = mkdocs ( directory , ** mkdocs_config ) if \"pdoc3\" in project_config : warnings . warn ( \"pdoc3 config usage is deprecated in favor of pdocs. \" \"pdoc3 section will be ignored. \" , DeprecationWarning , ) project_config [ \"pdocs\" ] = pdocs ( directory , ** project_config . get ( \"pdocs\" , {})) return project_config def setup_py ( location : str ) -> dict : \"\"\"Returns back any configuration info we are able to determine from a setup.py file\"\"\" setup_config = {} try : with open ( location ) as setup_py_file : for node in ast . walk ( ast . parse ( setup_py_file . read ())): if ( type ( node ) == _ast . Call and type ( getattr ( node , \"func\" , None )) == _ast . Name and node . func . id == \"setup\" # type: ignore ): for keyword in node . keywords : # type: ignore if keyword . arg == \"packages\" : setup_config [ \"modules\" ] = ast . literal_eval ( keyword . value ) break break except Exception as error : warnings . warn ( f \"Error ( { error } ) occurred trying to parse setup.py file: { location } \" ) return setup_config def toml ( location : str ) -> dict : \"\"\"Returns back the configuration found within the projects [TOML](https://github.com/toml-lang/toml#toml) config (if there is one). Generally this is a `pyproject.toml` file at the root of the project with a `[tool.portray]` section defined. \"\"\" try : location_exists = os . path . exists ( location ) if not location_exists : warnings . warn ( f ' \\n No config file found at location: \" { location } \"' ) return {} except Exception as detection_error : # pragma: no cover warnings . warn ( f ' \\n Unable to check config at \" { location } \" due to error: { detection_error } ' ) try : toml_config = toml_load ( location ) tools = toml_config . get ( \"tool\" , {}) config = tools . get ( \"portray\" , {}) config [ \"file\" ] = location if \"modules\" not in config : if \"poetry\" in tools and \"name\" in tools [ \"poetry\" ]: config [ \"modules\" ] = [ tools [ \"poetry\" ][ \"name\" ]] elif ( \"flit\" in tools and \"metadata\" in tools [ \"flit\" ] and \"module\" in tools [ \"flit\" ][ \"metadata\" ] ): config [ \"modules\" ] = [ tools [ \"flit\" ][ \"metadata\" ][ \"module\" ]] return config except Exception as load_config_error : warnings . warn ( f ' \\n Config file at \" { location } \" has errors: { load_config_error } ' ) return {} def repository ( directory : str , repo_url : Optional [ str ] = None , repo_name : Optional [ str ] = None , edit_uri : Optional [ str ] = None , normalize_repo_url : bool = True , ** kwargs , ) -> Dict [ str , Optional [ str ]]: \"\"\"Returns back any information that can be determined by introspecting the projects git repo (if there is one). \"\"\" try : if repo_url is None : repo_url = Repo ( directory ) . remotes . origin . url if repo_name is None : match = re . search ( r \"(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)?(/)?\" , repo_url ) if match : path = match . groups ()[ 2 ] else : path = repo_url repo_name = path . split ( \"/\" )[ - 1 ] if repo_name . endswith ( \".git\" ): repo_name = repo_name [: - len ( \".git\" )] if edit_uri is None : if \"github\" in repo_url or \"gitlab\" in repo_url : edit_uri = \"edit/main/\" elif \"bitbucket\" in repo_url : edit_uri = \"src/default/docs/\" if normalize_repo_url : if repo_url . startswith ( \"git@\" ) and \":\" in repo_url : tld , path = repo_url [ 4 :] . split ( \":\" ) repo_url = f \"https:// { tld } / { path } \" elif repo_url . startswith ( \"https://\" ) and \"@\" in repo_url : repo_url = f \"https:// { repo_url . split ( '@' )[ 1 ] } \" if repo_url and \"github\" in repo_url or \"gitlab\" in repo_url or \"bitbucket\" in repo_url : repo_url = repo_url . replace ( \".git\" , \"\" ) return { key : value for key , value in { \"repo_url\" : repo_url , \"repo_name\" : repo_name , \"edit_uri\" : edit_uri , } . items () if value } except Exception : warnings . warn ( \"Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.\" ) return {} def mkdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running mkdocs\"\"\" mkdocs_config : Dict [ str , Any ] = { ** MKDOCS_DEFAULTS , ** repository ( directory , ** overrides ), ** overrides , } theme = mkdocs_config [ \"theme\" ] if theme [ \"name\" ] . lower () == \"material\" : if \"custom_dir\" in theme : theme [ \"custom_dir\" ] = Path ( theme [ \"custom_dir\" ]) . absolute () . as_posix () else : theme [ \"custom_dir\" ] = MKDOCS_DEFAULTS [ \"theme\" ][ \"custom_dir\" ] nav = mkdocs_config . get ( \"nav\" , None ) if nav and hasattr ( nav [ 0 ], \"copy\" ): mkdocs_config [ \"nav\" ] = [ nav_item . copy () for nav_item in nav ] mkdocs_config [ \"markdown_extensions\" ] = mkdocs_config [ \"markdown_extensions\" ] + mkdocs_config . pop ( \"extra_markdown_extensions\" , [] ) return mkdocs_config def pdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running pdocs\"\"\" defaults = { ** PDOCS_DEFAULTS } defaults . update ( overrides ) return defaults","title":"Module portray.config"},{"location":"reference/portray/config/#variables","text":"MKDOCS_DEFAULTS PDOCS_DEFAULTS PORTRAY_DEFAULTS","title":"Variables"},{"location":"reference/portray/config/#functions","text":"","title":"Functions"},{"location":"reference/portray/config/#mkdocs","text":"def mkdocs ( directory : str , ** overrides ) -> dict Returns back the configuration that will be used when running mkdocs View Source def mkdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running mkdocs\"\"\" mkdocs_config : Dict [ str , Any ] = { ** MKDOCS_DEFAULTS , ** repository ( directory , ** overrides ), ** overrides , } theme = mkdocs_config [ \"theme\" ] if theme [ \"name\" ]. lower () == \"material\" : if \"custom_dir\" in theme : theme [ \"custom_dir\" ] = Path ( theme [ \"custom_dir\" ]). absolute (). as_posix () else : theme [ \"custom_dir\" ] = MKDOCS_DEFAULTS [ \"theme\" ][ \"custom_dir\" ] nav = mkdocs_config . get ( \"nav\" , None ) if nav and hasattr ( nav [ 0 ], \"copy\" ) : mkdocs_config [ \"nav\" ] = [ nav_item . copy () for nav_item in nav ] mkdocs_config [ \"markdown_extensions\" ] = mkdocs_config [ \"markdown_extensions\" ] + mkdocs_config . pop ( \"extra_markdown_extensions\" , [] ) return mkdocs_config","title":"mkdocs"},{"location":"reference/portray/config/#pdocs","text":"def pdocs ( directory : str , ** overrides ) -> dict Returns back the configuration that will be used when running pdocs View Source def pdocs ( directory : str , ** overrides ) -> dict : \"\"\"Returns back the configuration that will be used when running pdocs\"\"\" defaults = { ** PDOCS_DEFAULTS } defaults . update ( overrides ) return defaults","title":"pdocs"},{"location":"reference/portray/config/#project","text":"def project ( directory : str , config_file : str , ** overrides ) -> dict Returns back the complete configuration - including all sub configuration components defined below that portray was able to determine for the project View Source def project ( directory : str , config_file : str , ** overrides ) -> dict : \" \"\" Returns back the complete configuration - including all sub configuration components defined below that `portray` was able to determine for the project \"\" \" if not ( os . path . isfile ( os . path . join ( directory , config_file )) or os . path . isfile ( os . path . join ( directory , \"setup.py\" )) or \"modules\" in overrides ) : raise NoProjectFound ( directory ) project_config : Dict [ str , Any ] = { ** PORTRAY_DEFAULTS , \"directory\" : directory } if os . path . isfile ( os . path . join ( directory , \"setup.py\" )) : project_config . update ( set up_py ( os . path . join ( directory , \"setup.py\" ))) project_config . update ( toml ( os . path . join ( directory , config_file ))) project_config . update ( overrides ) project_config . set default ( \"modules\" , [ os . path . basename ( os . getcwd ()). replace ( \"-\" , \"_\" ) ] ) project_config . set default ( \"pdocs\" , {} ). set default ( \"modules\" , project_config [ \"modules\" ] ) mkdocs_config = project_config . get ( \"mkdocs\" , {} ) mkdocs_config . set default ( \"extra_markdown_extensions\" , project_config . get ( \"extra_markdown_extensions\" , [] ) ) project_config [ \"mkdocs\" ] = mkdocs ( directory , ** mkdocs_config ) if \"pdoc3\" in project_config : warnings . warn ( \"pdoc3 config usage is deprecated in favor of pdocs. \" \"pdoc3 section will be ignored. \" , DeprecationWarning , ) project_config [ \"pdocs\" ] = pdocs ( directory , ** project_config . get ( \"pdocs\" , {} )) return project_config","title":"project"},{"location":"reference/portray/config/#repository","text":"def repository ( directory : str , repo_url : Union [ str , NoneType ] = None , repo_name : Union [ str , NoneType ] = None , edit_uri : Union [ str , NoneType ] = None , normalize_repo_url : bool = True , ** kwargs ) -> Dict [ str , Union [ str , NoneType ]] Returns back any information that can be determined by introspecting the projects git repo (if there is one). View Source def repository ( directory : str , repo_url : Optional [ str ] = None , repo_name : Optional [ str ] = None , edit_uri : Optional [ str ] = None , normalize_repo_url : bool = True , ** kwargs , ) -> Dict [ str , Optional [ str ]] : \"\"\"Returns back any information that can be determined by introspecting the projects git repo ( if there is one ). \"\"\" try : if repo_url is None : repo_url = Repo ( directory ). remotes . origin . url if repo_name is None : match = re . search ( r \"(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)?(/)?\" , repo_url ) if match : path = match . groups ()[ 2 ] else : path = repo_url repo_name = path . split ( \"/\" )[ -1 ] if repo_name . endswith ( \".git\" ) : repo_name = repo_name [ : - len ( \".git\" )] if edit_uri is None : if \"github\" in repo_url or \"gitlab\" in repo_url : edit_uri = \"edit/main/\" elif \"bitbucket\" in repo_url : edit_uri = \"src/default/docs/\" if normalize_repo_url : if repo_url . startswith ( \"git@\" ) and \":\" in repo_url : tld , path = repo_url [ 4 : ]. split ( \":\" ) repo_url = f \"https://{tld}/{path}\" elif repo_url . startswith ( \"https://\" ) and \"@\" in repo_url : repo_url = f \"https://{repo_url.split('@')[1]}\" if repo_url and \"github\" in repo_url or \"gitlab\" in repo_url or \"bitbucket\" in repo_url : repo_url = repo_url . replace ( \".git\" , \"\" ) return { key : value for key , value in { \"repo_url\" : repo_url , \"repo_name\" : repo_name , \"edit_uri\" : edit_uri , }. items () if value } except Exception : warnings . warn ( \"Unable to identify `repo_name`, `repo_url`, and `edit_uri` automatically.\" ) return {}","title":"repository"},{"location":"reference/portray/config/#setup_py","text":"def setup_py ( location : str ) -> dict Returns back any configuration info we are able to determine from a setup.py file View Source def setup_py ( location : str ) -> dict : \"\"\"Returns back any configuration info we are able to determine from a setup.py file\"\"\" setup_config = {} try : with open ( location ) as setup_py_file : for node in ast . walk ( ast . parse ( setup_py_file . read ())) : if ( type ( node ) == _ast . Call and type ( getattr ( node , \"func\" , None )) == _ast . Name and node . func . id == \"setup\" # type : ignore ) : for keyword in node . keywords : # type : ignore if keyword . arg == \"packages\" : setup_config [ \"modules\" ] = ast . literal_eval ( keyword . value ) break break except Exception as error : warnings . warn ( f \"Error ({error}) occurred trying to parse setup.py file: {location}\" ) return setup_config","title":"setup_py"},{"location":"reference/portray/config/#toml","text":"def toml ( location : str ) -> dict Returns back the configuration found within the projects TOML config (if there is one). Generally this is a pyproject.toml file at the root of the project with a [tool.portray] section defined. View Source def toml ( location : str ) -> dict : \"\"\"Returns back the configuration found within the projects [TOML](https://github.com/toml-lang/toml#toml) config (if there is one). Generally this is a `pyproject.toml` file at the root of the project with a `[tool.portray]` section defined. \"\"\" try : location_exists = os . path . exists ( location ) if not location_exists : warnings . warn ( f ' \\n No config file found at location: \"{location}\"' ) return {} except Exception as detection_error : # pragma: no cover warnings . warn ( f ' \\n Unable to check config at \"{location}\" due to error: {detection_error}' ) try : toml_config = toml_load ( location ) tools = toml_config . get ( \"tool\" , {}) config = tools . get ( \"portray\" , {}) config [ \"file\" ] = location if \"modules\" not in config : if \"poetry\" in tools and \"name\" in tools [ \"poetry\" ]: config [ \"modules\" ] = [ tools [ \"poetry\" ][ \"name\" ]] elif ( \"flit\" in tools and \"metadata\" in tools [ \"flit\" ] and \"module\" in tools [ \"flit\" ][ \"metadata\" ] ): config [ \"modules\" ] = [ tools [ \"flit\" ][ \"metadata\" ][ \"module\" ]] return config except Exception as load_config_error : warnings . warn ( f ' \\n Config file at \"{location}\" has errors: {load_config_error}' ) return {}","title":"toml"},{"location":"reference/portray/exceptions/","text":"Module portray.exceptions All portray specific exception classes should be defined here View Source \"\"\"All portray specific exception classes should be defined here\"\"\" class PortrayError ( Exception ) : \"\"\"Base class for all exceptions returned from portray\"\"\" pass class NoProjectFound ( PortrayError ) : \"\"\"Thrown when portray is ran in a directory with no Python project\"\"\" def __init__ ( self , directory : str ) : super () . __init__ ( self , f \"No Python project found in the given directory: '{directory}'\" + \" See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound\" , ) self . directory = directory class DocumentationAlreadyExists ( PortrayError ) : \"\"\"Thrown when portray has been told to output documentation where it already exists\"\"\" def __init__ ( self , directory : str ) : super () . __init__ ( self , f \"Documentation already exists in '{directory}'. Use --overwrite to ignore\" ) self . directory = directory Classes DocumentationAlreadyExists class DocumentationAlreadyExists ( directory : str ) Thrown when portray has been told to output documentation where it already exists View Source class DocumentationAlreadyExists ( PortrayError ): \"\"\"Thrown when portray has been told to output documentation where it already exists\"\"\" def __init__ ( self , directory: str ): super (). __init__ ( self , f \"Documentation already exists in '{directory}'. Use --overwrite to ignore\" ) self . directory = directory Ancestors (in MRO) portray.exceptions.PortrayError builtins.Exception builtins.BaseException Class variables args Methods with_traceback def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self. NoProjectFound class NoProjectFound ( directory : str ) Thrown when portray is ran in a directory with no Python project View Source class NoProjectFound ( PortrayError ): \"\"\"Thrown when portray is ran in a directory with no Python project\"\"\" def __init__ ( self , directory: str ): super (). __init__ ( self , f \"No Python project found in the given directory: '{directory}'\" + \" See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound\" , ) self . directory = directory Ancestors (in MRO) portray.exceptions.PortrayError builtins.Exception builtins.BaseException Class variables args Methods with_traceback def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self. PortrayError class PortrayError ( / , * args , ** kwargs ) Base class for all exceptions returned from portray View Source class PortrayError ( Exception ): \"\"\"Base class for all exceptions returned from portray\"\"\" pass Ancestors (in MRO) builtins.Exception builtins.BaseException Descendants portray.exceptions.NoProjectFound portray.exceptions.DocumentationAlreadyExists Class variables args Methods with_traceback def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self.","title":"Exceptions"},{"location":"reference/portray/exceptions/#module-portrayexceptions","text":"All portray specific exception classes should be defined here View Source \"\"\"All portray specific exception classes should be defined here\"\"\" class PortrayError ( Exception ) : \"\"\"Base class for all exceptions returned from portray\"\"\" pass class NoProjectFound ( PortrayError ) : \"\"\"Thrown when portray is ran in a directory with no Python project\"\"\" def __init__ ( self , directory : str ) : super () . __init__ ( self , f \"No Python project found in the given directory: '{directory}'\" + \" See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound\" , ) self . directory = directory class DocumentationAlreadyExists ( PortrayError ) : \"\"\"Thrown when portray has been told to output documentation where it already exists\"\"\" def __init__ ( self , directory : str ) : super () . __init__ ( self , f \"Documentation already exists in '{directory}'. Use --overwrite to ignore\" ) self . directory = directory","title":"Module portray.exceptions"},{"location":"reference/portray/exceptions/#classes","text":"","title":"Classes"},{"location":"reference/portray/exceptions/#documentationalreadyexists","text":"class DocumentationAlreadyExists ( directory : str ) Thrown when portray has been told to output documentation where it already exists View Source class DocumentationAlreadyExists ( PortrayError ): \"\"\"Thrown when portray has been told to output documentation where it already exists\"\"\" def __init__ ( self , directory: str ): super (). __init__ ( self , f \"Documentation already exists in '{directory}'. Use --overwrite to ignore\" ) self . directory = directory","title":"DocumentationAlreadyExists"},{"location":"reference/portray/exceptions/#ancestors-in-mro","text":"portray.exceptions.PortrayError builtins.Exception builtins.BaseException","title":"Ancestors (in MRO)"},{"location":"reference/portray/exceptions/#class-variables","text":"args","title":"Class variables"},{"location":"reference/portray/exceptions/#methods","text":"","title":"Methods"},{"location":"reference/portray/exceptions/#with_traceback","text":"def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self.","title":"with_traceback"},{"location":"reference/portray/exceptions/#noprojectfound","text":"class NoProjectFound ( directory : str ) Thrown when portray is ran in a directory with no Python project View Source class NoProjectFound ( PortrayError ): \"\"\"Thrown when portray is ran in a directory with no Python project\"\"\" def __init__ ( self , directory: str ): super (). __init__ ( self , f \"No Python project found in the given directory: '{directory}'\" + \" See: https://timothycrosley.github.io/portray/TROUBLESHOOTING/#noprojectfound\" , ) self . directory = directory","title":"NoProjectFound"},{"location":"reference/portray/exceptions/#ancestors-in-mro_1","text":"portray.exceptions.PortrayError builtins.Exception builtins.BaseException","title":"Ancestors (in MRO)"},{"location":"reference/portray/exceptions/#class-variables_1","text":"args","title":"Class variables"},{"location":"reference/portray/exceptions/#methods_1","text":"","title":"Methods"},{"location":"reference/portray/exceptions/#with_traceback_1","text":"def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self.","title":"with_traceback"},{"location":"reference/portray/exceptions/#portrayerror","text":"class PortrayError ( / , * args , ** kwargs ) Base class for all exceptions returned from portray View Source class PortrayError ( Exception ): \"\"\"Base class for all exceptions returned from portray\"\"\" pass","title":"PortrayError"},{"location":"reference/portray/exceptions/#ancestors-in-mro_2","text":"builtins.Exception builtins.BaseException","title":"Ancestors (in MRO)"},{"location":"reference/portray/exceptions/#descendants","text":"portray.exceptions.NoProjectFound portray.exceptions.DocumentationAlreadyExists","title":"Descendants"},{"location":"reference/portray/exceptions/#class-variables_2","text":"args","title":"Class variables"},{"location":"reference/portray/exceptions/#methods_2","text":"","title":"Methods"},{"location":"reference/portray/exceptions/#with_traceback_2","text":"def with_traceback ( ... ) Exception.with_traceback(tb) -- set self. traceback to tb and return self.","title":"with_traceback"},{"location":"reference/portray/logo/","text":"Module portray.logo __ / \\ \\ __ _____ ___ _ __ \\ \\ , _ \\ _ __ __ __ __ / \\ '__`\\ / __`\\/\\`' __ \\ \\ \\ / / \\ ` '__\\/' __ ` \\ / \\ \\ / \\ \\ \\ \\ \\ L \\ \\ / \\ \\ L \\ \\ \\ \\ / \\ \\ \\ _ \\ \\ \\ // \\ \\ L \\ . \\ _ \\ \\ \\ _ \\ \\ \\ \\ , __ / \\ \\ ____ / \\ \\ _ \\ \\ \\ __ \\\\ \\ _ \\\\ \\ __ /. \\ _ \\\\ / ` ____ \\ \\ \\ \\ / \\ / ___ / \\ / _ / \\ / __ / \\ / _ / \\ / __ / \\ / _ / ` / ___ /> \\ \\ \\ _ \\ / \\ ___ / \\ / _ / \\ / __ / Your Project with Great Documentation . Version : 1.8.0 Copyright Timothy Edmund Crosley 2019 MIT License View Source from portray._version import __version__ ascii_art = rf \"\"\" __ /\\ \\__ _____ ___ _ __\\ \\ ,_\\ _ __ __ __ __ /\\ '__`\\ / __`\\/\\`'__\\ \\ \\/ /\\`'__\\/'__`\\ /\\ \\/\\ \\ \\ \\ \\L\\ \\/\\ \\L\\ \\ \\ \\/ \\ \\ \\_\\ \\ \\//\\ \\L\\.\\_\\ \\ \\_\\ \\ \\ \\ ,__/\\ \\____/\\ \\_\\ \\ \\__\\\\ \\_\\\\ \\__/.\\_\\\\/`____ \\ \\ \\ \\/ \\/___/ \\/_/ \\/__/ \\/_/ \\/__/\\/_/ `/___/> \\ \\ \\_\\ /\\___/ \\/_/ \\/__/ Your Project with Great Documentation. Version: { __version__ } Copyright Timothy Edmund Crosley 2019 MIT License \"\"\" __doc__ = f \"\"\" ```python { ascii_art } ``` \"\"\" Variables ascii_art","title":"Logo"},{"location":"reference/portray/logo/#module-portraylogo","text":"__ / \\ \\ __ _____ ___ _ __ \\ \\ , _ \\ _ __ __ __ __ / \\ '__`\\ / __`\\/\\`' __ \\ \\ \\ / / \\ ` '__\\/' __ ` \\ / \\ \\ / \\ \\ \\ \\ \\ L \\ \\ / \\ \\ L \\ \\ \\ \\ / \\ \\ \\ _ \\ \\ \\ // \\ \\ L \\ . \\ _ \\ \\ \\ _ \\ \\ \\ \\ , __ / \\ \\ ____ / \\ \\ _ \\ \\ \\ __ \\\\ \\ _ \\\\ \\ __ /. \\ _ \\\\ / ` ____ \\ \\ \\ \\ / \\ / ___ / \\ / _ / \\ / __ / \\ / _ / \\ / __ / \\ / _ / ` / ___ /> \\ \\ \\ _ \\ / \\ ___ / \\ / _ / \\ / __ / Your Project with Great Documentation . Version : 1.8.0 Copyright Timothy Edmund Crosley 2019 MIT License View Source from portray._version import __version__ ascii_art = rf \"\"\" __ /\\ \\__ _____ ___ _ __\\ \\ ,_\\ _ __ __ __ __ /\\ '__`\\ / __`\\/\\`'__\\ \\ \\/ /\\`'__\\/'__`\\ /\\ \\/\\ \\ \\ \\ \\L\\ \\/\\ \\L\\ \\ \\ \\/ \\ \\ \\_\\ \\ \\//\\ \\L\\.\\_\\ \\ \\_\\ \\ \\ \\ ,__/\\ \\____/\\ \\_\\ \\ \\__\\\\ \\_\\\\ \\__/.\\_\\\\/`____ \\ \\ \\ \\/ \\/___/ \\/_/ \\/__/ \\/_/ \\/__/\\/_/ `/___/> \\ \\ \\_\\ /\\___/ \\/_/ \\/__/ Your Project with Great Documentation. Version: { __version__ } Copyright Timothy Edmund Crosley 2019 MIT License \"\"\" __doc__ = f \"\"\" ```python { ascii_art } ``` \"\"\"","title":"Module portray.logo"},{"location":"reference/portray/logo/#variables","text":"ascii_art","title":"Variables"},{"location":"reference/portray/render/","text":"Module portray.render Defines how to render the current project and project_config using the included documentation generation utilities. View Source \"\"\"Defines how to render the current project and project_config using the included documentation generation utilities. \"\"\" import os import shutil import sys import tempfile from contextlib import contextmanager from glob import glob from typing import Dict , Iterator , Tuple import mkdocs . config as mkdocs_config import mkdocs . exceptions as _ mkdocs_exceptions from mkdocs . commands . build import build as mkdocs_build from mkdocs . config . defaults import get_schema as mkdocs_schema from mkdocs . utils import is_markdown_file from pdocs import as_markdown as pdocs_as_markdown from yaspin import yaspin from portray . exceptions import DocumentationAlreadyExists NO_HOME_PAGE = \"\"\" # Nothing here `portray` uses README.md as your projects home page. It appears you do not yet have a README.md file created. \"\"\" def documentation ( config : dict , overwrite : bool = False ) -> None : \"\"\"Renders the entire project given the project config into the config's specified output directory. Behind the scenes: - A temporary directory is created and your code is copy and pasted there - pdoc is ran over your code with the output sent into the temporary directory as Markdown documents - MkDocs is ran over all of your projects Markdown documents including those generated py pdoc. MkDocs outputs an HTML representation to a new temporary directory. - The html temporary directory is copied into your specified output location - Both temporary directories are deleted. \"\"\" if os . path . exists ( config [ \"output_dir\" ]) : if overwrite : shutil . rmtree ( config [ \"output_dir\" ]) else : raise DocumentationAlreadyExists ( config [ \"output_dir\" ]) with documentation_in_temp_folder ( config ) as ( _ , documentation_output ) : shutil . copytree ( documentation_output , config [ \"output_dir\" ]) def pdocs ( config : dict ) -> None : \"\"\"Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. \"\"\" pdocs_as_markdown ( **config ) def mkdocs ( config : dict ) : \"\"\"Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs `build` command. This rendering is from `.md` Markdown documents into HTML \"\"\" config_instance = _ mkdocs_config ( config ) return mkdocs_build ( config_instance ) @contextmanager def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple [ str , str ]] : \"\"\"Build documentation within a temp folder, returning that folder name before it is deleted.\"\"\" if config [ \"append_directory_to_python_path\" ] and not config [ \"directory\" ] in sys . path : sys . path . append ( config [ \"directory\" ]) with tempfile . TemporaryDirectory () as input_dir : input_dir = os . path . join ( input_dir , \"input\" ) os . mkdir ( input_dir ) with tempfile . TemporaryDirectory () as temp_output_dir : with yaspin ( text= \"Copying source documentation to temporary compilation directory\" ) as spinner : for root_file in os . listdir ( config [ \"directory\" ]) : root_file_absolute = os . path . join ( config [ \"directory\" ], root_file ) if os . path . isfile ( root_file_absolute ) and is_markdown_file ( root_file_absolute ) : shutil . copyfile ( root_file_absolute , os . path . join ( input_dir , root_file )) for source_directory in [ config [ \"docs_dir\" ]] + config [ \"extra_dirs\" ] : directory_absolute = os . path . join ( config [ \"directory\" ], source_directory ) if os . path . isdir ( directory_absolute ) : shutil . copytree ( directory_absolute , os . path . join ( input_dir , source_directory ) ) spinner . ok ( \"Done\" ) if \"docs_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"docs_dir\" ] = input_dir if \"site_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"site_dir\" ] = temp_output_dir if \"nav\" not in config [ \"mkdocs\" ] : nav = config [ \"mkdocs\" ][ \"nav\" ] = [] root_docs = sorted ( glob ( os . path . join ( input_dir , \"*.md\" ))) readme_doc = os . path . join ( input_dir , \"README.md\" ) if readme_doc in root_docs : root_docs . remove ( readme_doc ) else : with open ( readme_doc , \"w\" ) as readme_doc_file : readme_doc_file . write ( NO_HOME_PAGE ) nav . append ({ \"Home\" : \"README.md\" }) nav . extend ( _ doc ( doc , input_dir , config ) for doc in root_docs ) nav . extend ( _ nested_docs ( os . path . join ( input_dir , config [ \"docs_dir\" ]), input_dir , config ) ) else : nav = config [ \"mkdocs\" ][ \"nav\" ] if nav : index_nav = nav [ 0 ] index_page : str = \"\" if index_nav and isinstance ( index_nav , dict ) : index_page = tuple ( index_nav . val ues ())[ 0 ] elif isinstance ( index_nav , str ) : # pragma : no cover index_page = index_nav if index_page : destination_index_page = os . path . join ( input_dir , \"index.md\" ) if ( index_page ! = \"README.md\" and index_page ! = \"index.md\" and not os . path . exists ( destination_index_page ) ) : shutil . copyfile ( os . path . join ( input_dir , index_page ), destination_index_page ) if config [ \"include_reference_documentation\" ] : with yaspin ( text= \"Auto generating reference documentation using pdocs\" ) as spinner : if \"output_dir\" not in config [ \"pdocs\" ] : config [ \"pdocs\" ][ \"output_dir\" ] = os . path . join ( input_dir , \"reference\" ) pdocs ( config [ \"pdocs\" ]) reference_docs = _ nested_docs ( config [ \"pdocs\" ][ \"output_dir\" ], input_dir , config ) nav . append ({ \"Reference\" : reference_docs }) # type : ignore spinner . ok ( \"Done\" ) with yaspin ( text= \"Rendering complete website from Markdown using MkDocs\" ) as spinner : mkdocs ( config [ \"mkdocs\" ]) spinner . ok ( \"Done\" ) # remove any settings pointing to the temp dirs if config [ \"mkdocs\" ][ \"docs_dir\" ]. startswith ( input_dir ) : del config [ \"mkdocs\" ][ \"docs_dir\" ] if config [ \"mkdocs\" ][ \"site_dir\" ]. startswith ( temp_output_dir ) : del config [ \"mkdocs\" ][ \"site_dir\" ] if config [ \"pdocs\" ][ \"output_dir\" ]. startswith ( input_dir ) : del config [ \"pdocs\" ][ \"output_dir\" ] if config [ \"include_reference_documentation\" ] : nav . pop () yield input_dir , temp_output_dir def _ mkdocs_config ( config : dict ) -> mkdocs_config . Config : config_instance = mkdocs_config . Config ( schema = mkdocs_schema ()) config_instance . load_dict ( config ) errors , warnings = config_instance . val idate () if errors : print ( errors ) raise _ mkdocs_exceptions . ConfigurationError ( f \"Aborted with {len(errors)} Configuration Errors!\" ) elif config . get ( \"strict\" , False ) and warnings : # pragma : no cover print ( warnings ) raise _ mkdocs_exceptions . ConfigurationError ( f \"Aborted with {len(warnings)} Configuration Warnings in 'strict' mode!\" ) config_instance . config_file_path = config [ \"config_file_path\" ] return config_instance def _ nested_docs ( directory : str , root_directory : str , config : dict ) -> list : nav = [ _ doc ( doc , root_directory , config ) for doc in sorted ( glob ( os . path . join ( directory , \"*.md\" ))) ] nested_dirs = sorted ( glob ( os . path . join ( directory , \"*/\" ))) for nested_dir in nested_dirs : if ( len ( glob ( os . path . join ( nested_dir , \"*.md\" )) + glob ( os . path . join ( nested_dir , \"**/*.md\" ))) > 0 ) : dir_nav = { _ label ( nested_dir [ :- 1 ], config ) : _ nested_docs ( nested_dir , root_directory , config ) } nav . append ( dir_nav ) # type : ignore return nav def _ label ( path : str , config : Dict ) -> str : label = os . path . basename ( path ) if \".\" in label : label = \".\" . join ( label . split ( \".\" )[ :- 1 ]) label = label . replace ( \"-\" , \" \" ). replace ( \"_\" , \" \" ). title () return config [ \"labels\" ]. get ( label , label ) def _ doc ( path : str , root_path : str , config : dict ) -> Dict [ str , str ] : path = os . path . relpath ( path , root_path ) return { _ label ( path , config ) : path } Variables NO_HOME_PAGE Functions documentation def documentation ( config : dict , overwrite : bool = False ) -> None Renders the entire project given the project config into the config's specified output directory. Behind the scenes: A temporary directory is created and your code is copy and pasted there pdoc is ran over your code with the output sent into the temporary directory as Markdown documents MkDocs is ran over all of your projects Markdown documents including those generated py pdoc. MkDocs outputs an HTML representation to a new temporary directory. The html temporary directory is copied into your specified output location Both temporary directories are deleted. View Source def documentation ( config : dict , overwrite : bool = False ) -> None : \"\"\"Renders the entire project given the project config into the config' s specified output directory . Behind the scenes : - A temporary directory is created and your code is copy and pasted there - pdoc is ran over your code with the output sent into the temporary directory as Markdown documents - MkDocs is ran over all of your projects Markdown documents including those generated py pdoc . MkDocs outputs an HTML representation to a new temporary directory . - The html temporary directory is copied into your specified output location - Both temporary directories are deleted . \"\"\" if os.path.exists(config[\" output_dir \"]): if overwrite: shutil.rmtree(config[\" output_dir \"]) else: raise DocumentationAlreadyExists(config[\" output_dir \"]) with documentation_in_temp_folder(config) as (_, documentation_output): shutil.copytree(documentation_output, config[\" output_dir \"]) documentation_in_temp_folder def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple [ str , str ]] Build documentation within a temp folder, returning that folder name before it is deleted. View Source @contextmanager def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple[str, str ] ]: \"\"\"Build documentation within a temp folder, returning that folder name before it is deleted.\"\"\" if config [ \"append_directory_to_python_path\" ] and not config [ \"directory\" ] in sys . path : sys . path . append ( config [ \"directory\" ] ) with tempfile . TemporaryDirectory () as input_dir : input_dir = os . path . join ( input_dir , \"input\" ) os . mkdir ( input_dir ) with tempfile . TemporaryDirectory () as temp_output_dir : with yaspin ( text = \"Copying source documentation to temporary compilation directory\" ) as spinner : for root_file in os . listdir ( config [ \"directory\" ] ) : root_file_absolute = os . path . join ( config [ \"directory\" ] , root_file ) if os . path . isfile ( root_file_absolute ) and is_markdown_file ( root_file_absolute ) : shutil . copyfile ( root_file_absolute , os . path . join ( input_dir , root_file )) for source_directory in [ config[\"docs_dir\" ] ] + config [ \"extra_dirs\" ] : directory_absolute = os . path . join ( config [ \"directory\" ] , source_directory ) if os . path . isdir ( directory_absolute ) : shutil . copytree ( directory_absolute , os . path . join ( input_dir , source_directory ) ) spinner . ok ( \"Done\" ) if \"docs_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"docs_dir\" ] = input_dir if \"site_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"site_dir\" ] = temp_output_dir if \"nav\" not in config [ \"mkdocs\" ] : nav = config [ \"mkdocs\" ][ \"nav\" ] = [] root_docs = sorted ( glob ( os . path . join ( input_dir , \"*.md\" ))) readme_doc = os . path . join ( input_dir , \"README.md\" ) if readme_doc in root_docs : root_docs . remove ( readme_doc ) else : with open ( readme_doc , \"w\" ) as readme_doc_file : readme_doc_file . write ( NO_HOME_PAGE ) nav . append ( { \"Home\" : \"README.md\" } ) nav . extend ( _doc ( doc , input_dir , config ) for doc in root_docs ) nav . extend ( _nested_docs ( os . path . join ( input_dir , config [ \"docs_dir\" ] ), input_dir , config ) ) else : nav = config [ \"mkdocs\" ][ \"nav\" ] if nav : index_nav = nav [ 0 ] index_page : str = \"\" if index_nav and isinstance ( index_nav , dict ) : index_page = tuple ( index_nav . values ()) [ 0 ] elif isinstance ( index_nav , str ) : # pragma : no cover index_page = index_nav if index_page : destination_index_page = os . path . join ( input_dir , \"index.md\" ) if ( index_page != \"README.md\" and index_page != \"index.md\" and not os . path . exists ( destination_index_page ) ) : shutil . copyfile ( os . path . join ( input_dir , index_page ), destination_index_page ) if config [ \"include_reference_documentation\" ] : with yaspin ( text = \"Auto generating reference documentation using pdocs\" ) as spinner : if \"output_dir\" not in config [ \"pdocs\" ] : config [ \"pdocs\" ][ \"output_dir\" ] = os . path . join ( input_dir , \"reference\" ) pdocs ( config [ \"pdocs\" ] ) reference_docs = _nested_docs ( config [ \"pdocs\" ][ \"output_dir\" ] , input_dir , config ) nav . append ( { \"Reference\" : reference_docs } ) # type : ignore spinner . ok ( \"Done\" ) with yaspin ( text = \"Rendering complete website from Markdown using MkDocs\" ) as spinner : mkdocs ( config [ \"mkdocs\" ] ) spinner . ok ( \"Done\" ) # remove any settings pointing to the temp dirs if config [ \"mkdocs\" ][ \"docs_dir\" ] . startswith ( input_dir ) : del config [ \"mkdocs\" ][ \"docs_dir\" ] if config [ \"mkdocs\" ][ \"site_dir\" ] . startswith ( temp_output_dir ) : del config [ \"mkdocs\" ][ \"site_dir\" ] if config [ \"pdocs\" ][ \"output_dir\" ] . startswith ( input_dir ) : del config [ \"pdocs\" ][ \"output_dir\" ] if config [ \"include_reference_documentation\" ] : nav . pop () yield input_dir , temp_output_dir mkdocs def mkdocs ( config : dict ) Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs build command. This rendering is from .md Markdown documents into HTML View Source def mkdocs ( config : dict ) : \" \"\" Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs `build` command. This rendering is from `.md` Markdown documents into HTML \"\" \" config_instance = _mkdocs_config ( config ) return mkdocs_build ( config_instance ) pdocs def pdocs ( config : dict ) -> None Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. View Source def pdocs ( config : dict ) -> None : \"\"\"Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. \"\"\" pdocs_as_markdown ( ** config )","title":"Render"},{"location":"reference/portray/render/#module-portrayrender","text":"Defines how to render the current project and project_config using the included documentation generation utilities. View Source \"\"\"Defines how to render the current project and project_config using the included documentation generation utilities. \"\"\" import os import shutil import sys import tempfile from contextlib import contextmanager from glob import glob from typing import Dict , Iterator , Tuple import mkdocs . config as mkdocs_config import mkdocs . exceptions as _ mkdocs_exceptions from mkdocs . commands . build import build as mkdocs_build from mkdocs . config . defaults import get_schema as mkdocs_schema from mkdocs . utils import is_markdown_file from pdocs import as_markdown as pdocs_as_markdown from yaspin import yaspin from portray . exceptions import DocumentationAlreadyExists NO_HOME_PAGE = \"\"\" # Nothing here `portray` uses README.md as your projects home page. It appears you do not yet have a README.md file created. \"\"\" def documentation ( config : dict , overwrite : bool = False ) -> None : \"\"\"Renders the entire project given the project config into the config's specified output directory. Behind the scenes: - A temporary directory is created and your code is copy and pasted there - pdoc is ran over your code with the output sent into the temporary directory as Markdown documents - MkDocs is ran over all of your projects Markdown documents including those generated py pdoc. MkDocs outputs an HTML representation to a new temporary directory. - The html temporary directory is copied into your specified output location - Both temporary directories are deleted. \"\"\" if os . path . exists ( config [ \"output_dir\" ]) : if overwrite : shutil . rmtree ( config [ \"output_dir\" ]) else : raise DocumentationAlreadyExists ( config [ \"output_dir\" ]) with documentation_in_temp_folder ( config ) as ( _ , documentation_output ) : shutil . copytree ( documentation_output , config [ \"output_dir\" ]) def pdocs ( config : dict ) -> None : \"\"\"Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. \"\"\" pdocs_as_markdown ( **config ) def mkdocs ( config : dict ) : \"\"\"Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs `build` command. This rendering is from `.md` Markdown documents into HTML \"\"\" config_instance = _ mkdocs_config ( config ) return mkdocs_build ( config_instance ) @contextmanager def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple [ str , str ]] : \"\"\"Build documentation within a temp folder, returning that folder name before it is deleted.\"\"\" if config [ \"append_directory_to_python_path\" ] and not config [ \"directory\" ] in sys . path : sys . path . append ( config [ \"directory\" ]) with tempfile . TemporaryDirectory () as input_dir : input_dir = os . path . join ( input_dir , \"input\" ) os . mkdir ( input_dir ) with tempfile . TemporaryDirectory () as temp_output_dir : with yaspin ( text= \"Copying source documentation to temporary compilation directory\" ) as spinner : for root_file in os . listdir ( config [ \"directory\" ]) : root_file_absolute = os . path . join ( config [ \"directory\" ], root_file ) if os . path . isfile ( root_file_absolute ) and is_markdown_file ( root_file_absolute ) : shutil . copyfile ( root_file_absolute , os . path . join ( input_dir , root_file )) for source_directory in [ config [ \"docs_dir\" ]] + config [ \"extra_dirs\" ] : directory_absolute = os . path . join ( config [ \"directory\" ], source_directory ) if os . path . isdir ( directory_absolute ) : shutil . copytree ( directory_absolute , os . path . join ( input_dir , source_directory ) ) spinner . ok ( \"Done\" ) if \"docs_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"docs_dir\" ] = input_dir if \"site_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"site_dir\" ] = temp_output_dir if \"nav\" not in config [ \"mkdocs\" ] : nav = config [ \"mkdocs\" ][ \"nav\" ] = [] root_docs = sorted ( glob ( os . path . join ( input_dir , \"*.md\" ))) readme_doc = os . path . join ( input_dir , \"README.md\" ) if readme_doc in root_docs : root_docs . remove ( readme_doc ) else : with open ( readme_doc , \"w\" ) as readme_doc_file : readme_doc_file . write ( NO_HOME_PAGE ) nav . append ({ \"Home\" : \"README.md\" }) nav . extend ( _ doc ( doc , input_dir , config ) for doc in root_docs ) nav . extend ( _ nested_docs ( os . path . join ( input_dir , config [ \"docs_dir\" ]), input_dir , config ) ) else : nav = config [ \"mkdocs\" ][ \"nav\" ] if nav : index_nav = nav [ 0 ] index_page : str = \"\" if index_nav and isinstance ( index_nav , dict ) : index_page = tuple ( index_nav . val ues ())[ 0 ] elif isinstance ( index_nav , str ) : # pragma : no cover index_page = index_nav if index_page : destination_index_page = os . path . join ( input_dir , \"index.md\" ) if ( index_page ! = \"README.md\" and index_page ! = \"index.md\" and not os . path . exists ( destination_index_page ) ) : shutil . copyfile ( os . path . join ( input_dir , index_page ), destination_index_page ) if config [ \"include_reference_documentation\" ] : with yaspin ( text= \"Auto generating reference documentation using pdocs\" ) as spinner : if \"output_dir\" not in config [ \"pdocs\" ] : config [ \"pdocs\" ][ \"output_dir\" ] = os . path . join ( input_dir , \"reference\" ) pdocs ( config [ \"pdocs\" ]) reference_docs = _ nested_docs ( config [ \"pdocs\" ][ \"output_dir\" ], input_dir , config ) nav . append ({ \"Reference\" : reference_docs }) # type : ignore spinner . ok ( \"Done\" ) with yaspin ( text= \"Rendering complete website from Markdown using MkDocs\" ) as spinner : mkdocs ( config [ \"mkdocs\" ]) spinner . ok ( \"Done\" ) # remove any settings pointing to the temp dirs if config [ \"mkdocs\" ][ \"docs_dir\" ]. startswith ( input_dir ) : del config [ \"mkdocs\" ][ \"docs_dir\" ] if config [ \"mkdocs\" ][ \"site_dir\" ]. startswith ( temp_output_dir ) : del config [ \"mkdocs\" ][ \"site_dir\" ] if config [ \"pdocs\" ][ \"output_dir\" ]. startswith ( input_dir ) : del config [ \"pdocs\" ][ \"output_dir\" ] if config [ \"include_reference_documentation\" ] : nav . pop () yield input_dir , temp_output_dir def _ mkdocs_config ( config : dict ) -> mkdocs_config . Config : config_instance = mkdocs_config . Config ( schema = mkdocs_schema ()) config_instance . load_dict ( config ) errors , warnings = config_instance . val idate () if errors : print ( errors ) raise _ mkdocs_exceptions . ConfigurationError ( f \"Aborted with {len(errors)} Configuration Errors!\" ) elif config . get ( \"strict\" , False ) and warnings : # pragma : no cover print ( warnings ) raise _ mkdocs_exceptions . ConfigurationError ( f \"Aborted with {len(warnings)} Configuration Warnings in 'strict' mode!\" ) config_instance . config_file_path = config [ \"config_file_path\" ] return config_instance def _ nested_docs ( directory : str , root_directory : str , config : dict ) -> list : nav = [ _ doc ( doc , root_directory , config ) for doc in sorted ( glob ( os . path . join ( directory , \"*.md\" ))) ] nested_dirs = sorted ( glob ( os . path . join ( directory , \"*/\" ))) for nested_dir in nested_dirs : if ( len ( glob ( os . path . join ( nested_dir , \"*.md\" )) + glob ( os . path . join ( nested_dir , \"**/*.md\" ))) > 0 ) : dir_nav = { _ label ( nested_dir [ :- 1 ], config ) : _ nested_docs ( nested_dir , root_directory , config ) } nav . append ( dir_nav ) # type : ignore return nav def _ label ( path : str , config : Dict ) -> str : label = os . path . basename ( path ) if \".\" in label : label = \".\" . join ( label . split ( \".\" )[ :- 1 ]) label = label . replace ( \"-\" , \" \" ). replace ( \"_\" , \" \" ). title () return config [ \"labels\" ]. get ( label , label ) def _ doc ( path : str , root_path : str , config : dict ) -> Dict [ str , str ] : path = os . path . relpath ( path , root_path ) return { _ label ( path , config ) : path }","title":"Module portray.render"},{"location":"reference/portray/render/#variables","text":"NO_HOME_PAGE","title":"Variables"},{"location":"reference/portray/render/#functions","text":"","title":"Functions"},{"location":"reference/portray/render/#documentation","text":"def documentation ( config : dict , overwrite : bool = False ) -> None Renders the entire project given the project config into the config's specified output directory. Behind the scenes: A temporary directory is created and your code is copy and pasted there pdoc is ran over your code with the output sent into the temporary directory as Markdown documents MkDocs is ran over all of your projects Markdown documents including those generated py pdoc. MkDocs outputs an HTML representation to a new temporary directory. The html temporary directory is copied into your specified output location Both temporary directories are deleted. View Source def documentation ( config : dict , overwrite : bool = False ) -> None : \"\"\"Renders the entire project given the project config into the config' s specified output directory . Behind the scenes : - A temporary directory is created and your code is copy and pasted there - pdoc is ran over your code with the output sent into the temporary directory as Markdown documents - MkDocs is ran over all of your projects Markdown documents including those generated py pdoc . MkDocs outputs an HTML representation to a new temporary directory . - The html temporary directory is copied into your specified output location - Both temporary directories are deleted . \"\"\" if os.path.exists(config[\" output_dir \"]): if overwrite: shutil.rmtree(config[\" output_dir \"]) else: raise DocumentationAlreadyExists(config[\" output_dir \"]) with documentation_in_temp_folder(config) as (_, documentation_output): shutil.copytree(documentation_output, config[\" output_dir \"])","title":"documentation"},{"location":"reference/portray/render/#documentation_in_temp_folder","text":"def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple [ str , str ]] Build documentation within a temp folder, returning that folder name before it is deleted. View Source @contextmanager def documentation_in_temp_folder ( config : dict ) -> Iterator [ Tuple[str, str ] ]: \"\"\"Build documentation within a temp folder, returning that folder name before it is deleted.\"\"\" if config [ \"append_directory_to_python_path\" ] and not config [ \"directory\" ] in sys . path : sys . path . append ( config [ \"directory\" ] ) with tempfile . TemporaryDirectory () as input_dir : input_dir = os . path . join ( input_dir , \"input\" ) os . mkdir ( input_dir ) with tempfile . TemporaryDirectory () as temp_output_dir : with yaspin ( text = \"Copying source documentation to temporary compilation directory\" ) as spinner : for root_file in os . listdir ( config [ \"directory\" ] ) : root_file_absolute = os . path . join ( config [ \"directory\" ] , root_file ) if os . path . isfile ( root_file_absolute ) and is_markdown_file ( root_file_absolute ) : shutil . copyfile ( root_file_absolute , os . path . join ( input_dir , root_file )) for source_directory in [ config[\"docs_dir\" ] ] + config [ \"extra_dirs\" ] : directory_absolute = os . path . join ( config [ \"directory\" ] , source_directory ) if os . path . isdir ( directory_absolute ) : shutil . copytree ( directory_absolute , os . path . join ( input_dir , source_directory ) ) spinner . ok ( \"Done\" ) if \"docs_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"docs_dir\" ] = input_dir if \"site_dir\" not in config [ \"mkdocs\" ] : config [ \"mkdocs\" ][ \"site_dir\" ] = temp_output_dir if \"nav\" not in config [ \"mkdocs\" ] : nav = config [ \"mkdocs\" ][ \"nav\" ] = [] root_docs = sorted ( glob ( os . path . join ( input_dir , \"*.md\" ))) readme_doc = os . path . join ( input_dir , \"README.md\" ) if readme_doc in root_docs : root_docs . remove ( readme_doc ) else : with open ( readme_doc , \"w\" ) as readme_doc_file : readme_doc_file . write ( NO_HOME_PAGE ) nav . append ( { \"Home\" : \"README.md\" } ) nav . extend ( _doc ( doc , input_dir , config ) for doc in root_docs ) nav . extend ( _nested_docs ( os . path . join ( input_dir , config [ \"docs_dir\" ] ), input_dir , config ) ) else : nav = config [ \"mkdocs\" ][ \"nav\" ] if nav : index_nav = nav [ 0 ] index_page : str = \"\" if index_nav and isinstance ( index_nav , dict ) : index_page = tuple ( index_nav . values ()) [ 0 ] elif isinstance ( index_nav , str ) : # pragma : no cover index_page = index_nav if index_page : destination_index_page = os . path . join ( input_dir , \"index.md\" ) if ( index_page != \"README.md\" and index_page != \"index.md\" and not os . path . exists ( destination_index_page ) ) : shutil . copyfile ( os . path . join ( input_dir , index_page ), destination_index_page ) if config [ \"include_reference_documentation\" ] : with yaspin ( text = \"Auto generating reference documentation using pdocs\" ) as spinner : if \"output_dir\" not in config [ \"pdocs\" ] : config [ \"pdocs\" ][ \"output_dir\" ] = os . path . join ( input_dir , \"reference\" ) pdocs ( config [ \"pdocs\" ] ) reference_docs = _nested_docs ( config [ \"pdocs\" ][ \"output_dir\" ] , input_dir , config ) nav . append ( { \"Reference\" : reference_docs } ) # type : ignore spinner . ok ( \"Done\" ) with yaspin ( text = \"Rendering complete website from Markdown using MkDocs\" ) as spinner : mkdocs ( config [ \"mkdocs\" ] ) spinner . ok ( \"Done\" ) # remove any settings pointing to the temp dirs if config [ \"mkdocs\" ][ \"docs_dir\" ] . startswith ( input_dir ) : del config [ \"mkdocs\" ][ \"docs_dir\" ] if config [ \"mkdocs\" ][ \"site_dir\" ] . startswith ( temp_output_dir ) : del config [ \"mkdocs\" ][ \"site_dir\" ] if config [ \"pdocs\" ][ \"output_dir\" ] . startswith ( input_dir ) : del config [ \"pdocs\" ][ \"output_dir\" ] if config [ \"include_reference_documentation\" ] : nav . pop () yield input_dir , temp_output_dir","title":"documentation_in_temp_folder"},{"location":"reference/portray/render/#mkdocs","text":"def mkdocs ( config : dict ) Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs build command. This rendering is from .md Markdown documents into HTML View Source def mkdocs ( config : dict ) : \" \"\" Render the project's associated Markdown documentation using the specified MkDocs config passed into the MkDocs `build` command. This rendering is from `.md` Markdown documents into HTML \"\" \" config_instance = _mkdocs_config ( config ) return mkdocs_build ( config_instance )","title":"mkdocs"},{"location":"reference/portray/render/#pdocs","text":"def pdocs ( config : dict ) -> None Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. View Source def pdocs ( config : dict ) -> None : \"\"\"Render this project using the specified pdoc config passed into pdoc. This rendering is from code definition to Markdown so that it will be compatible with MkDocs. \"\"\" pdocs_as_markdown ( ** config )","title":"pdocs"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..14a3f3fc --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,768 @@ + + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + + None + 2023-12-07 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 00000000..27cc31ee Binary files /dev/null and b/sitemap.xml.gz differ