Browse Source

convert to hugo

Jason 10 months ago
parent
commit
25a26b8307
100 changed files with 17198 additions and 24 deletions
  1. 6 0
      .gitmodules
  2. 6 0
      archetypes/default.md
  3. 0 14
      build.sh
  4. 0 9
      compiled/01-gists.sh
  5. 28 0
      config.toml
  6. 6 0
      content/_index.md
  7. 69 0
      content/posts/gist/2013-04-30/5486455.md
  8. 236 0
      content/posts/gist/2013-06-06/5719743.md
  9. 76 0
      content/posts/gist/2013-06-13/5770182.md
  10. 109 0
      content/posts/gist/2013-12-23/8105640.md
  11. 153 0
      content/posts/gist/2014-02-28/9264937.md
  12. 76 0
      content/posts/gist/2014-03-05/9359839.md
  13. 171 0
      content/posts/gist/2014-07-25/382ce730f1f4c0fa51c2.md
  14. 276 0
      content/posts/gist/2014-07-29/542f067143918c237834.md
  15. 209 0
      content/posts/gist/2014-07-30/e5d2776d44f7ee31820a.md
  16. 16 0
      content/posts/gist/2014-09-03/169489838b9e5ee0d100.md
  17. 436 0
      content/posts/gist/2014-12-18/0ac511e0a3ec0cd5cf4a.md
  18. 185 0
      content/posts/gist/2015-02-28/1e8f24628ab13282145a.md
  19. 215 0
      content/posts/gist/2015-02-28/ae3fe23d8b6e0e5a36d1.md
  20. 33 0
      content/posts/gist/2015-03-26/0199179c7f57ea7a379a.md
  21. 39 0
      content/posts/gist/2015-04-22/23dc705d3a181f532484.md
  22. 31 0
      content/posts/gist/2015-04-22/d75343d1a8f7761212f6.md
  23. 46 0
      content/posts/gist/2015-07-13/2f8bc9aeabf8045e34c0.md
  24. 38 0
      content/posts/gist/2015-08-06/7783eac88f2fc8d914a7.md
  25. 103 0
      content/posts/gist/2015-08-19/4cf9bf1096c5d113a01a.md
  26. 67 0
      content/posts/gist/2016-03-04/0edc8df5ed5916434da2.md
  27. 175 0
      content/posts/gist/2016-03-23/7e547987c77cef5aa9fa.md
  28. 100 0
      content/posts/gist/2016-07-24/ee246668d672385bc451feab8b5bbad9.md
  29. 16 0
      content/posts/gist/2017-01-24/b19b585ee2379266d03ac1ee8f53d29f.md
  30. 25 0
      content/posts/gist/2018-07-27/fc3aa1bb41da024989c51c6ba968c3da.md
  31. 182 0
      content/posts/gist/2019-02-12/04805514b1fc07310000e8c770b6486c.md
  32. 55 0
      content/posts/gist/2019-03-27/e5f8dc43c748032917b25af478ef94df.md
  33. 152 0
      content/posts/gist/2019-07-21/54405be477a30d3588e47838cc91df9d.md
  34. 27 0
      content/posts/gist/2019-08-20/7413a1559856fd251657d93b28fbc366.md
  35. 20 0
      content/posts/gist/2020-01-16/0cbebc6297f24e39bba841f0a88fc459.md
  36. 68 0
      content/posts/gist/2020-01-29/c4da3b99bcdbf9c01a3d82a73211233d.md
  37. 7 0
      content/posts/new-site-with-hugo.md
  38. 0 1
      html
  39. 0 0
      layouts/partials/footer.html
  40. 17 0
      layouts/partials/header.html
  41. 93 0
      public/categories/index.html
  42. 14 0
      public/categories/index.xml
  43. 29 0
      public/css/my.css
  44. 406 0
      public/css/style.css
  45. 0 0
      public/images/Schwarzenberger.png
  46. 0 0
      public/images/cows.jpg
  47. 3434 0
      public/index.xml
  48. 1 0
      public/page/1/index.html
  49. 479 0
      public/page/2/index.html
  50. 480 0
      public/page/3/index.html
  51. 148 0
      public/page/4/index.html
  52. 172 0
      public/posts/gist/2013-04-30/5486455/index.html
  53. 343 0
      public/posts/gist/2013-06-06/5719743/index.html
  54. 182 0
      public/posts/gist/2013-06-13/5770182/index.html
  55. 230 0
      public/posts/gist/2013-12-23/8105640/index.html
  56. 259 0
      public/posts/gist/2014-02-28/9264937/index.html
  57. 182 0
      public/posts/gist/2014-03-05/9359839/index.html
  58. 288 0
      public/posts/gist/2014-07-25/382ce730f1f4c0fa51c2/index.html
  59. 395 0
      public/posts/gist/2014-07-29/542f067143918c237834/index.html
  60. 326 0
      public/posts/gist/2014-07-30/e5d2776d44f7ee31820a/index.html
  61. 119 0
      public/posts/gist/2014-09-03/169489838b9e5ee0d100/index.html
  62. 556 0
      public/posts/gist/2014-12-18/0ac511e0a3ec0cd5cf4a/index.html
  63. 305 0
      public/posts/gist/2015-02-28/1e8f24628ab13282145a/index.html
  64. 335 0
      public/posts/gist/2015-02-28/ae3fe23d8b6e0e5a36d1/index.html
  65. 136 0
      public/posts/gist/2015-03-26/0199179c7f57ea7a379a/index.html
  66. 159 0
      public/posts/gist/2015-04-22/23dc705d3a181f532484/index.html
  67. 134 0
      public/posts/gist/2015-04-22/d75343d1a8f7761212f6/index.html
  68. 152 0
      public/posts/gist/2015-07-13/2f8bc9aeabf8045e34c0/index.html
  69. 141 0
      public/posts/gist/2015-08-06/7783eac88f2fc8d914a7/index.html
  70. 206 0
      public/posts/gist/2015-08-19/4cf9bf1096c5d113a01a/index.html
  71. 170 0
      public/posts/gist/2016-03-04/0edc8df5ed5916434da2/index.html
  72. 295 0
      public/posts/gist/2016-03-23/7e547987c77cef5aa9fa/index.html
  73. 192 0
      public/posts/gist/2016-07-24/ee246668d672385bc451feab8b5bbad9/index.html
  74. 122 0
      public/posts/gist/2017-01-24/b19b585ee2379266d03ac1ee8f53d29f/index.html
  75. 131 0
      public/posts/gist/2018-07-27/fc3aa1bb41da024989c51c6ba968c3da/index.html
  76. 303 0
      public/posts/gist/2019-02-12/04805514b1fc07310000e8c770b6486c/index.html
  77. 161 0
      public/posts/gist/2019-03-27/e5f8dc43c748032917b25af478ef94df/index.html
  78. 267 0
      public/posts/gist/2019-07-21/54405be477a30d3588e47838cc91df9d/index.html
  79. 136 0
      public/posts/gist/2019-08-20/7413a1559856fd251657d93b28fbc366/index.html
  80. 128 0
      public/posts/gist/2020-01-16/0cbebc6297f24e39bba841f0a88fc459/index.html
  81. 174 0
      public/posts/gist/2020-01-29/c4da3b99bcdbf9c01a3d82a73211233d/index.html
  82. 106 0
      public/posts/gist_0199179c7f57ea7a379a/index.html
  83. 109 0
      public/posts/gist_04805514b1fc07310000e8c770b6486c/index.html
  84. 109 0
      public/posts/gist_0ac511e0a3ec0cd5cf4a/index.html
  85. 109 0
      public/posts/gist_0cbebc6297f24e39bba841f0a88fc459/index.html
  86. 106 0
      public/posts/gist_0edc8df5ed5916434da2/index.html
  87. 106 0
      public/posts/gist_169489838b9e5ee0d100/index.html
  88. 109 0
      public/posts/gist_1e8f24628ab13282145a/index.html
  89. 109 0
      public/posts/gist_23dc705d3a181f532484/index.html
  90. 109 0
      public/posts/gist_2f8bc9aeabf8045e34c0/index.html
  91. 106 0
      public/posts/gist_382ce730f1f4c0fa51c2/index.html
  92. 106 0
      public/posts/gist_4cf9bf1096c5d113a01a/index.html
  93. 106 0
      public/posts/gist_542f067143918c237834/index.html
  94. 109 0
      public/posts/gist_54405be477a30d3588e47838cc91df9d/index.html
  95. 106 0
      public/posts/gist_5486455/index.html
  96. 112 0
      public/posts/gist_5719743/index.html
  97. 109 0
      public/posts/gist_5770182/index.html
  98. 109 0
      public/posts/gist_7413a1559856fd251657d93b28fbc366/index.html
  99. 106 0
      public/posts/gist_7783eac88f2fc8d914a7/index.html
  100. 0 0
      public/posts/gist_7e547987c77cef5aa9fa/index.html

+ 6 - 0
.gitmodules

@@ -0,0 +1,6 @@
+[submodule "themes/ananke"]
+	path = themes/ananke
+	url = https://github.com/budparr/gohugo-theme-ananke.git
+[submodule "themes/anubis"]
+	path = themes/anubis
+	url = https://github.com/mitrichius/hugo-theme-anubis.git

+ 6 - 0
archetypes/default.md

@@ -0,0 +1,6 @@
+---
+title: "{{ replace .Name "-" " " | title }}"
+date: {{ .Date }}
+draft: true
+---
+

+ 0 - 14
build.sh

@@ -1,14 +0,0 @@
-dir=/var/www/1j.nz/
-
-head -n 10 $dir/template/index.html
-
-cat $dir/template/header.html
-cat $dir/sections/*.html
-
-ls $dir/compiled/*.sh | bash
-
-cat $dir/template/footer.html
-
-echo "<!-- generated: $(date -Iseconds) -->"
-
-tail -n 3 $dir/template/index.html

+ 0 - 9
compiled/01-gists.sh

@@ -1,9 +0,0 @@
-echo "	<section class=\"gists\">"
-echo "		<h3>Gists</h3>"
-curl --silent -s "https://api.github.com/users/master5o1/gists" \
- | jq '.[0:10] | map("<article class=\"gist\"><a href=\"\(.html_url)\">\(.files | keys | .[0])</a><time datetime=\"\(.created_at)\">\(.created_at)</time><p class=\"caption\">\(.description)</p></article>") | add' \
- | sed -e 's/\\"/"/g' \
- | cut -c 2- | rev | cut -c 2- | rev \
- | sed -e 's/^/\t\t/'
-echo "	</section>"
-echo ""

+ 28 - 0
config.toml

@@ -0,0 +1,28 @@
+languageCode = 'en-us'
+baseUrl = 'https://jason.schwarzenberger.nz/'
+title = 'Jason Schwarzenberger'
+description = 'Software engineer from New Zealand.'
+theme = 'anubis'
+paginate = 10.0
+disqusShortname = ''
+googleAnalytics = ''
+[[menu.main]]
+identifier = 'posts'
+name = 'Archive'
+title = 'Archive'
+url = '/posts/'
+weight = 1.0
+
+[[menu.main]]
+identifier = 'tags'
+name = 'Tags'
+title = 'Tags'
+url = '/tags/'
+weight = 1.0
+
+[params]
+author = 'Jason'
+description = 'Software engineer from New Zealand.'
+images = ['images/Schwarzenberger.png']
+customCSS = ['css/my.css']
+dateFormat = '2006-01-02 15:04'

+ 6 - 0
content/_index.md

@@ -0,0 +1,6 @@
+**email:** jason@master5o1.com  
+**repositories:** [github.com/master5o1](https://github.com/master5o1), [git.1j.nz](https://git.1j.nz)  
+**twitter:** [https://twitter.com/master5o1](@master5o1)  
+**keybase:** [master5o1](https://keybase.io/master5o1)  
+
+![cows](/images/cows.jpg)

+ 69 - 0
content/posts/gist/2013-04-30/5486455.md

@@ -0,0 +1,69 @@
+---
+title: "lolcrypt.py"
+date: 2013-04-30T03:33:46Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/5486455)
+
+
+
+
+
+```python
+# vim: noai:ts=4:sw=4:expandtab:syntax=python
+
+import re
+from xbotpp.modules import Module
+
+
+class lolcrypt(Module):
+    """\
+    Provide lolcryption.
+    """
+
+    def __init__(self):
+        Module.__init__(self)
+
+    def action(self, bot, event, args, buf):
+        """\
+        Lolcrypt the given arguments, or the buffer (if present)
+
+        Pass "-d" as the first parameter to de-lolcrypt.
+        """
+
+        if len(args) is 0 and buf == "":
+            return "%slolcrypt [-d] <text> or %scommand | lolcrypt [-d]" % (self.bot.prefix, self.bot.prefix)
+
+        delol = (len(args) != 0 and args[0] == "-d")
+        cipher = list("aeioubcdfghjklmnpqrstvwxyz")
+        text = buf if buf != "" else " ".join(args[1:]) if delol else " ".join(args[0:])
+        mod = lambda a, n: ((a%n)+n)%n
+        buf = "" 
+
+        for char in text:
+            caps = re.match("[A-Z]", char)
+            char = char.lower()
+            
+            if not char in cipher:
+                buf += char.upper() if caps else char
+                continue
+            
+            i = cipher.index(char)
+            if re.match("[" + "".join(cipher[0:5]) + "]", char):
+                if delol:
+                    char = cipher[mod(i-2,5)]
+                else:
+                    char = cipher[(i+2)%5]
+            else:
+                if delol:
+                    char = cipher[mod(i-15,21)+5]
+                else:
+                    char = cipher[(i+5)%21+5]
+
+            buf += char.upper() if caps else char
+
+        return buf
+
+```
+

+ 236 - 0
content/posts/gist/2013-06-06/5719743.md

@@ -0,0 +1,236 @@
+---
+title: "array things.js"
+date: 2013-06-06T06:47:55Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/5719743)
+
+
+I've been nursing this in a JS Fiddle for a short time now. Just been playing with the LINQ methods and how they would be in JS.
+
+I find OrderBy and GroupBy are interesting.
+
+
+```javascript
+var run = function (arr) {
+    'use strict';
+    var onlyStrings = l('x => typeof x === "string"');
+    var onlyNums = l('x => typeof x === "number"');
+    var selector = l('x => typeof x');
+    var grouper = l('x => typeof x');
+    var selectE = l('x => x');
+    var evenIndex = l('(x, index) => index % 2 === 0');
+
+    console.clear();
+    console.log(l.memory());
+    console.log(arr.Select(), arr.Count());
+    console.log(arr.First(), arr.Last());
+    console.log('First', arr.First(onlyStrings));
+    console.log('Last', arr.Last(onlyStrings));
+    console.log('Select', arr.Select(selector));
+    console.log('Count', arr.Count(onlyStrings));
+    console.log('GroupBy', arr.GroupBy(grouper));
+    console.log('Sum', arr.Sum(selectE));
+    console.log('OrderBy', arr.OrderBy(selectE));
+    console.log('OrderByDescending', arr.OrderByDescending(selectE));
+    console.log('GroupBy (x, index) => index % 2 === 0', arr.GroupBy(evenIndex));
+    console.log('GroupBy (x, index) => index % 2 === 0', arr.GroupBy('(x, index) => index % 2 === 0'));
+
+};
+
+var l = (function () {
+    var memory = {};
+    var lx = function (lambdaString) {
+        if (memory[lambdaString] !== undefined) {
+            return memory[lambdaString];
+        }
+
+        var oneArg = /([a-zA-Z_][a-zA-Z0-9_]*)\ [\=\-]\>\ (.*)/;
+        var multiArgs = /\((([a-zA-Z_][a-zA-Z0-9_]*,?\ ?)+)\)\ [\=\-]\>\ (.*)/;
+        var parts = lambdaString.match(oneArg) || lambdaString.match(multiArgs);
+        var param = parts[1];
+        var body = parts[parts.length - 1];
+
+        body = body.split(/; ?/);
+        body = body.map(function (line, i) {
+            line = line.replace(/(^ +)|( +$)/, '');
+            if (i === (body.length - 1) && !/return/.test(line)) {
+                line = 'return ' + line;
+            }
+            return '  ' + line;
+        });
+        memory[lambdaString] = new Function(param, body.join(';\n') + ';');
+        return memory[lambdaString];
+    };
+    lx.memory = function () {
+        return memory;
+    };
+    return lx;
+})();
+
+var first = function (arr, filter) {
+    filter = filter || (function (e) {
+        return true;
+    });
+    var filtered = arr.filter(filter);
+    return filtered[0];
+};
+var last = function (arr, filter) {
+    filter = filter || (function (e) {
+        return true;
+    });
+    var filtered = arr.filter(filter);
+    return filtered[filtered.length - 1];
+};
+var select = function (arr, selector) {
+    selector = selector || (function (e) {
+        return e;
+    });
+    return arr.map(selector);
+};
+var count = function (arr, filter) {
+    filter = filter || (function (e) {
+        return true;
+    });
+    return arr.filter(filter).length;
+};
+var groupBy = function (arr, grouper) {
+    grouper = grouper || (function (e) {
+        return e;
+    });
+    var grouping = {};
+    arr.forEach(function (e, i, a) {
+        var groups = this;
+        var group = grouper(e, i, a);
+        if (groups[group] === undefined) {
+            groups[group] = [];
+        }
+        groups[group].push(e);
+    }, grouping);
+    return Object.keys(grouping).map(function (e) {
+        return grouping[e];
+    });
+};
+var sum = function (arr, selector, initial) {
+    initial = initial || 0;
+    selector = selector || (function (e) {
+        return e;
+    });
+    return arr.reduce(function (p, c) {
+        return p + selector(c);
+    }, initial);
+};
+var orderBy = function (arr, selector) {
+    selector = selector || (function (e) {
+        return e;
+    });
+    var compare = function (a, b) {
+        var type = typeof selector(a);
+        if (type === 'number') {
+            return selector(a) - selector(b);
+        } else if (type === 'string') {
+            return selector(a).localeCompare(selector(b));
+        }
+    };
+    return [].slice.call(arr).sort(compare);
+};
+var orderByDescending = function (arr, selector) {
+    return orderBy(arr, selector).reverse();
+};
+var take = function (arr, number) {
+    return arr.slice(0, number);
+};
+var skip = function (arr, number) {
+    return arr.slice(number);
+};
+var any = function (arr, condition) {
+    if (condition === null) {
+        return arr.length > 0;
+    }
+    return arr.some(condition);
+};
+var where = function (arr, condition) {
+    condition = condition || (function (e) {
+        return true;
+    });
+    return arr.filter(condition);
+};
+
+Array.prototype.First = function (filter) {
+    if (typeof filter === 'string') {
+        filter = l(filter);
+    }
+    return first(this, filter);
+};
+Array.prototype.Last = function (filter) {
+    if (typeof filter === 'string') {
+        filter = l(filter);
+    }
+    return last(this, filter);
+};
+Array.prototype.Select = function (selector) {
+    if (typeof selector === 'string') {
+        selector = l(selector);
+    }
+    return select(this, selector);
+};
+Array.prototype.Count = function (filter) {
+    if (typeof filter === 'string') {
+        filter = l(filter);
+    }
+
+    return count(this, filter);
+};
+Array.prototype.GroupBy = function (grouper) {
+    if (typeof grouper === 'string') {
+        grouper = l(grouper);
+    }
+    return groupBy(this, grouper);
+};
+Array.prototype.Sum = function (selector) {
+    if (typeof selector === 'string') {
+        selector = l(selector);
+    }
+    return sum(this, selector);
+};
+Array.prototype.OrderBy = function (selector) {
+    if (typeof selector === 'string') {
+        selector = l(selector);
+    }
+    return orderBy(this, selector);
+};
+Array.prototype.OrderByDescending = function (selector) {
+    if (typeof selector === 'string') {
+        selector = l(selector);
+    }
+    return orderByDescending(this, selector);
+};
+Array.prototype.Take = function (number) {
+    if (typeof number === 'string') {
+        number = l(number);
+    }
+    return take(this, number);
+};
+Array.prototype.Skip = function (number) {
+    if (typeof number === 'string') {
+        number = l(number);
+    }
+    return skip(this, number);
+};
+Array.prototype.Any = function (condition) {
+    if (typeof condition === 'string') {
+        condition = l(condition);
+    }
+    return any(this, condition);
+};
+Array.prototype.Where = function (condition) {
+    if (typeof condition === 'string') {
+        condition = l(condition);
+    }
+    return where(this, condition);
+};
+
+run([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'one', 'two', 'three']);
+```
+

+ 76 - 0
content/posts/gist/2013-06-13/5770182.md

@@ -0,0 +1,76 @@
+---
+title: "thing about Question.js"
+date: 2013-06-13T00:00:40Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/5770182)
+
+
+Why do I even do these things.
+
+
+```javascript
+// Consider this a class for the Question object.
+function Question(question) {
+  var self = this;
+  
+  // Private variables:
+  
+  var correct = null;
+  var answers = [];
+  
+  // Public Methods:
+  
+  self.getQuestion = function () {
+    // This is a 'Getter' method.
+    // It exposes the value of a (private) property of the object.
+    // The property value cannot be changed.
+    return question;
+  };
+  
+  self.getAnswers = function () {
+    // Because JavaScript passes by reference, if this Getter was set up as:
+    // return answers;
+    // Then it would be possible to overwrite the answers array.
+    // By concatenating answers onto an empty array we are actually passing
+    // a copy of the answers array.
+    return [].concat(answers);
+  };
+  
+  self.addAnswer = function (answer, isCorrect) {
+    // Add an answer to the answers array.
+    // If it exists in the array, set it as correct if it is also correct.
+    var index = answers.indexOf(answer);
+    if (index > -1) {
+      correct = isCorrect ? index : correct;
+      return;
+    }
+    answers.push(answer);
+    // Recursively call so that it can be set to correct.
+    self.addAnswer(answer, isCorrect);
+  };
+  
+  self.checkAnswer = function (answer, answerIndex) {
+    answerIndex = answerIndex || answers.indexOf(answer);
+    return answerIndex === correct;
+  };
+}
+
+
+var question = new Question('What colours are on the flag of Switzerland?');
+question.addAnswer('Black, Red and Yellow');
+question.addAnswer('Red, White and Blue');
+question.addAnswer('Red and White', true);
+question.addAnswer('Yellow and Green');
+
+console.log(question);
+
+console.log(question.getQuestion());
+
+console.log(question.getAnswers());
+
+console.log(question.checkAnswer('Black, Red and Yellow'));
+console.log(question.checkAnswer('Red and White'));
+```
+

+ 109 - 0
content/posts/gist/2013-12-23/8105640.md

@@ -0,0 +1,109 @@
+---
+title: "bookmarklet.js"
+date: 2013-12-23T22:02:42Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/8105640)
+
+
+
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [bookmarklet.js](https://gist.githubusercontent.com/master5o1/8105640/raw/470cf05c4cb7ac8c00723d3f4b696f218d4897c3/bookmarklet.js) | application/javascript | 498.0B |
+| [clickingbad_seconds_info.js](https://gist.githubusercontent.com/master5o1/8105640/raw/fb26590702f717e298df77c9b3b0ba8945877427/clickingbad_seconds_info.js) | application/javascript | 912.0B |
+| [fiddle.js](https://gist.githubusercontent.com/master5o1/8105640/raw/fb26590702f717e298df77c9b3b0ba8945877427/fiddle.js) | application/javascript | 912.0B |
+| [fiddle.manifest](https://gist.githubusercontent.com/master5o1/8105640/raw/bfdcda218c01b44ae6692d3e906dac41d6f04d45/fiddle.manifest) | text/cache-manifest | 126.0B |
+***
+
+### [bookmarklet.js](https://gist.githubusercontent.com/master5o1/8105640/raw/470cf05c4cb7ac8c00723d3f4b696f218d4897c3/bookmarklet.js) -- application/javascript, 498.0B
+```javascript
+javascript:window.setInterval(function(){$("#clickers, #sellers, #upgrades, #banks").find('[id$="_cst"]').each(function(){var b=$(this),a=b.text().replace(/[\$,]/g,""),c=a.replace(/[0-9\.]/g,""),a=1*a.replace(/[A-Z]/,""),c={Q:1E15,T:1E12,B:1E9,M:1E6}[c]||1,a=a*c,d=$("#seller_rps"),c=$("#sell_amt"),d=d.text().replace(/,/g,""),c=c.text().replace(/,/g,""),a=(a-c)/d,b="#"+b.attr("id").replace("_cst","_btn"),b=$(b);0<a?(a="Purchase in "+a.toFixed(0)+" seconds",b.html(a)):b.html("Purchase")})},1E3);
+```
+***
+### [clickingbad_seconds_info.js](https://gist.githubusercontent.com/master5o1/8105640/raw/fb26590702f717e298df77c9b3b0ba8945877427/clickingbad_seconds_info.js) -- application/javascript, 912.0B
+```javascript
+window.setInterval(function () {
+	$('#clickers, #sellers, #upgrades, #banks').find('[id$="_cst"]').each(function () {
+		var multipliers = {
+			Qt: 1E18,
+			Q: 1E15,
+			T: 1E12,
+			B: 1E9,
+			M: 1E6
+		};
+		var $this = $(this);
+		var price = $this.text().replace(/[\$,]/g, "");
+		var multiplier = price.replace(/[0-9\.]/g, "");
+		price = price.replace(/[A-Z]/gi, "") * 1;
+		multiplier = multipliers[multiplier] || 1;
+		price = price * multiplier;
+		var $income = $("#seller_rps");
+		var $cash = $("#sell_amt");
+		var income = $income.text()
+			.replace(/,/g, "");
+		var cash = $cash.text()
+			.replace(/,/g, "");
+		var seconds = (price - cash) / income;
+		var buybtn = "#" + $this.attr("id")
+				.replace("_cst", "_btn");
+		var $buybtn = $(buybtn);
+		if (seconds > 0) {
+			var text = "Purchase in " + seconds.toFixed(0) + " seconds";
+			$buybtn.html(text);
+		} else {
+			$buybtn.html('Purchase');
+		}
+	});
+}, 1E3);
+```
+***
+### [fiddle.js](https://gist.githubusercontent.com/master5o1/8105640/raw/fb26590702f717e298df77c9b3b0ba8945877427/fiddle.js) -- application/javascript, 912.0B
+```javascript
+window.setInterval(function () {
+	$('#clickers, #sellers, #upgrades, #banks').find('[id$="_cst"]').each(function () {
+		var multipliers = {
+			Qt: 1E18,
+			Q: 1E15,
+			T: 1E12,
+			B: 1E9,
+			M: 1E6
+		};
+		var $this = $(this);
+		var price = $this.text().replace(/[\$,]/g, "");
+		var multiplier = price.replace(/[0-9\.]/g, "");
+		price = price.replace(/[A-Z]/gi, "") * 1;
+		multiplier = multipliers[multiplier] || 1;
+		price = price * multiplier;
+		var $income = $("#seller_rps");
+		var $cash = $("#sell_amt");
+		var income = $income.text()
+			.replace(/,/g, "");
+		var cash = $cash.text()
+			.replace(/,/g, "");
+		var seconds = (price - cash) / income;
+		var buybtn = "#" + $this.attr("id")
+				.replace("_cst", "_btn");
+		var $buybtn = $(buybtn);
+		if (seconds > 0) {
+			var text = "Purchase in " + seconds.toFixed(0) + " seconds";
+			$buybtn.html(text);
+		} else {
+			$buybtn.html('Purchase');
+		}
+	});
+}, 1E3);
+```
+***
+### [fiddle.manifest](https://gist.githubusercontent.com/master5o1/8105640/raw/bfdcda218c01b44ae6692d3e906dac41d6f04d45/fiddle.manifest) -- text/cache-manifest, 126.0B
+```
+name: Clicking bad bookmarklet
+description: Clicking bad thing
+authors:
+  - Jason Schwarzenberger
+resources:
+normalize_css: no
+```
+

+ 153 - 0
content/posts/gist/2014-02-28/9264937.md

@@ -0,0 +1,153 @@
+---
+title: "brainfuck.js"
+date: 2014-02-28T03:56:45Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/9264937)
+
+
+unfinshed brainfuck interpreter in js. Still need to do [ and ].
+
+
+```javascript
+console.group('helloWorld');
+var helloWorldScript = 'this is hello world: ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.';
+var helloWorld = new BrainFuck(helloWorldScript);
+console.log('script:', helloWorldScript);
+console.log('validate:', helloWorld.validate());
+console.log('execute:', helloWorld.execute());
+console.groupEnd('helloWorld');
+
+
+function BrainFuck(str, cells) {
+    var script = str.replace(/[^<>\-\+\[\]\.\,]/g, '');
+    var MAX_CELLS = cells || 30000;
+
+    this.validate = function () {
+        return validate();
+    };
+    this.execute = function (stdin) {
+        return execute(stdin || '');
+    };
+
+    function checkBrackets() {
+        var stack = [];
+        var arr = script.replace(/[^\[\]]/g, '').split('');
+        var openers = [],
+            closers = [];
+        if (arr.length === 0) {
+            return true;
+        }
+        if (arr[0] !== '[') {
+            return false;
+        }
+        for (var i = 0; i < arr.length; i++) {
+            if (arr[i] === '[') {
+                stack.push(arr[i]);
+                openers.push(arr[i]);
+            } else if (arr[i] === ']') {
+                stack.pop();
+                closers.push(arr[i]);
+            }
+        }
+        if (stack.length > 0 || openers.length !== closers.length) {
+            return false;
+        }
+        return true;
+    }
+
+    function bracketsPc() {
+        var stack = [];
+        var brackets = {};
+        var arr = script.split('');
+        for (var i = 0; i < arr.length; i++) {
+            if (arr[i] === '[') {
+                stack.push(i);
+                brackets[i] = {
+                    '[': i,
+                    ']': -1
+                };
+            } else if (arr[i] === ']') {
+                var pc = stack.pop();
+                brackets[pc][']'] = i;
+                brackets[i] = {
+                    '[': pc,
+                    ']': i
+                };
+            }
+        }
+        return brackets;
+    }
+
+    function validate() {
+        var matchingBrackets = checkBrackets();
+        return matchingBrackets;
+    }
+
+    function execute(stdin) {
+        if (!validate()) {
+            throw new Error("Invalid Syntax");
+        }
+
+        var index = 0;
+        var arr = new Array(MAX_CELLS + 1).join('a').split('');
+        var stdin_arr = stdin.split('');
+        var stdout = [];
+        var pc_stack = [];
+        var brackets = bracketsPc();
+
+        arr = arr.map(function () {
+            return 0;
+        });
+
+        var opcodes = {};
+        opcodes['<'] = function (pc) {
+            index -= 1;
+            return pc;
+        };
+        opcodes['>'] = function (pc) {
+            index += 1;
+            return pc;
+        };
+        opcodes['+'] = function (pc) {
+            arr[index] += 1;
+            return pc;
+        };
+        opcodes['-'] = function (pc) {
+            arr[index] -= 1;
+            return pc;
+        };
+        opcodes['['] = function (pc) {
+            if (arr[index] === 0) {
+                pc = brackets[pc][']'];
+            }
+            return pc;
+        };
+        opcodes[']'] = function (pc) {
+            if (arr[index] !== 0) {
+                pc = brackets[pc]['['];
+            }
+            return pc;
+        };
+        opcodes[','] = function (pc) {
+            var chr = stdin_arr.shift();
+            arr[index] = chr.charCodeAt(0);
+            return pc;
+        };
+        opcodes['.'] = function (pc) {
+            stdout.push(String.fromCharCode(arr[index]));
+            return pc;
+        };
+
+        var ops = script.split('');
+        for (var pc = 0; pc < ops.length; pc++) {
+            var op = ops[pc];
+            pc = opcodes[op](pc);
+        }
+
+        return stdout.join('');
+    }
+}
+```
+

+ 76 - 0
content/posts/gist/2014-03-05/9359839.md

@@ -0,0 +1,76 @@
+---
+title: "gistfile1.txt"
+date: 2014-03-05T02:02:15Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/9359839)
+
+
+WIP: LOLcryption in BrainFuck. Cannot handle characters with a code less than 'a'. Will infinite loop in that case. If it isn't an [a-z] then it should just echo the character. Try it out at http://brainfuck.master5o1.com
+
+
+```text
+,[
+ ---------- ---------- ---------- ---------- ----------
+ ---------- ---------- ---------- ---------- -------              a
+ [-                                                               b
+  [-                                                              c
+   [-                                                             d
+    [-                                                            e
+     [-                                                           f
+      [-                                                          g
+       [-                                                         h
+         [-                                                       i
+          [-                                                      j
+           [-                                                     k
+            [-                                                    l
+             [-                                                   m
+              [-                                                  n
+               [-                                                 o
+                [-                                                p
+                 [-                                               q
+                  [-                                              r
+                   [-                                             s
+                    [-                                            t
+                     [-                                           u
+                      [-                                          v
+                       [-                                         w
+                        [-                                        x
+                         [-                                       y
+                          [-                                      z
+                           [-]
+                          >+<]
+                         >+<]
+                        >+<]
+                       >++<]
+                      >+++<]
+                     >--<]
+                    >+<]
+                   >++<]
+                  >+<]
+                 >+<]
+                >+<]
+               >----- ----- ----- ----- -----<]
+              >+<]
+             >+<]
+            >+<]
+           >+<]
+          >+<]
+         >+<]
+        >+<]
+       >+<]
+      >+++<]
+     >--<]
+    >+<]
+   >++<]
+  >+++++<]
+ >
+ ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
+ ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++
+ +++++
+ .
+ [-]<
+,]
+```
+

+ 171 - 0
content/posts/gist/2014-07-25/382ce730f1f4c0fa51c2.md

@@ -0,0 +1,171 @@
+---
+title: "BitNZ.js"
+date: 2014-07-25T23:27:46Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/382ce730f1f4c0fa51c2)
+
+
+
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [BitNZ.js](https://gist.githubusercontent.com/master5o1/382ce730f1f4c0fa51c2/raw/f1165dabdcb0ab8f14bd6d0318f80a91db84ddcd/BitNZ.js) | application/javascript | 3.2KiB |
+| [play.js](https://gist.githubusercontent.com/master5o1/382ce730f1f4c0fa51c2/raw/89824c3d61f06f5a10ddec274c943825497246eb/play.js) | application/javascript | 488.0B |
+***
+
+### [BitNZ.js](https://gist.githubusercontent.com/master5o1/382ce730f1f4c0fa51c2/raw/f1165dabdcb0ab8f14bd6d0318f80a91db84ddcd/BitNZ.js) -- application/javascript, 3.2KiB
+```javascript
+var crypto = require('crypto');
+var request = require('request');
+
+module.exports = function BitNZ(username, apiKey, apiSecret) {
+  var self = this;
+  var hostname = 'https://bitnz.com';
+  var api = '/api/0';
+  var noop = function() {};
+
+  var sign = function(obj){
+    obj = obj || {};
+    obj.nonce = new Date().getTime() + '' + new Date().getMilliseconds();
+    obj.signature = crypto.createHmac('sha256', apiSecret)
+                          .update(obj.nonce + username + apiKey)
+                          .digest('hex')
+                          .toUpperCase();
+    obj.key = apiKey;
+    return obj;
+  };
+
+  self.sign = sign;
+
+  var post = function(action, parameters, callback) {
+    callback = callback || noop;
+    console.log('URL', hostname + api + action, parameters);
+    request.post(hostname + api + action, {
+      form: parameters,
+      headers: {
+        'User-Agent': 'Mozilla/4.0 (compatible; bitNZ node.js client by master5o1)'
+      }
+    }, callback);
+  }
+
+  var get = function(action, parameters, callback) {
+    callback = callback || noop;
+    var params = [];
+    Object.keys(parameters).forEach(function(key){
+      this.push(key + '=' + parameters[key]);
+    }, params);
+    request.get(hostname + api + action + '?' + params.join('&'), callback);
+  };
+
+  // Open/Public API Calls:
+
+  self.getTicker = function(callback){
+    return get('/ticker', {}, callback);
+  };
+
+  self.getTrades = function(since, date, callback){
+    return get('/trades', {
+      since: since,
+      'since_date': date
+    }, callback);
+  };
+
+  self.getOrderBook = function(parmeters, callback){
+    return get('/orderbook', parameters, callback);
+  };
+
+  // Private API Calls:
+
+  self.getBalance = function(callback) {
+    return post('/private/balance', sign({}), callback);
+  };
+
+  self.openBids = function(callback) {
+    return post('/private/orders/buy/open', sign({}), callback);
+  };
+
+  self.openAsks = function(callback) {
+    return post('/private/orders/sell/open', sign({}), callback);
+  };
+
+  self.closedBids = function(skip, limit, callback) {
+    return post('/private/orders/buy/close', sign({
+      offset: skip,
+      limit: limit
+    }), callback);
+  };
+
+  self.closedAsks = function(skip, limit, callback) {
+    return post('/private/orders/sell/close', sign({
+      offset: skip,
+      limit: limit
+    }), callback);
+  };
+
+  self.cancelBid = function(id, callback) {
+    return post('/private/orders/buy/cancel', sign({
+      id: id
+    }), callback);
+  };
+
+  self.cancelAsk = function(id, callback) {
+    return post('/private/orders/sell/cancel', sign({
+      id: id
+    }), callback);
+  };
+
+  self.createBid = function(amount, price, callback) {
+    return post('/private/orders/buy/create', sign({
+      amount: amount,
+      price: price
+    }), callback);
+  };
+
+  self.createAsk = function(amount, price, callback) {
+    return post('/private/orders/sell/create', sign({
+      amount: amount,
+      price: price
+    }), callback);
+  };
+
+  self.depositAddress = function(callback) {
+    return post('/private/btc/address', sign({}), callback);
+  };
+
+  self.withdraw = function(address, amount, callback) {
+    return post('/private/btc/withdraw', sign({
+      address: address,
+      amount: amount
+    }), callback);
+  };
+};
+```
+***
+### [play.js](https://gist.githubusercontent.com/master5o1/382ce730f1f4c0fa51c2/raw/89824c3d61f06f5a10ddec274c943825497246eb/play.js) -- application/javascript, 488.0B
+```javascript
+var BitNZ = require('./BitNZ.js');
+
+var username = "username"
+  , apiKey = "key"
+  , apiSecret = "sekrit";
+
+var bitnz = new BitNZ(username, apiKey, apiSecret);
+
+bitnz.getBalance(function(error, response, body){
+  console.log(response.statusCode);
+  if (!error && response.statusCode === 200) {
+    console.log(body);
+  }
+});
+
+bitnz.getTicker(function(error, response, body){
+  console.log(response.statusCode);
+  if (!error && response.statusCode === 200) {
+    console.log(body);
+  }
+});
+```
+

+ 276 - 0
content/posts/gist/2014-07-29/542f067143918c237834.md

@@ -0,0 +1,276 @@
+---
+title: "BitNZService.js"
+date: 2014-07-29T10:23:12Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/542f067143918c237834)
+
+
+
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [BitNZService.js](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/9ba5b4c3876a0bdab45e6bcb4ecd1ba0ec56320e/BitNZService.js) | application/javascript | 3.8KiB |
+| [PlayApp.js](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/b7e80d8cd2ac0cc37586ab563670d006db445755/PlayApp.js) | application/javascript | 959.0B |
+| [index.html](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/5158c5dd6e0ff1b0cc98390bcae99a1ee6f79e2a/index.html) | text/html | 1.2KiB |
+***
+
+### [BitNZService.js](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/9ba5b4c3876a0bdab45e6bcb4ecd1ba0ec56320e/BitNZService.js) -- application/javascript, 3.8KiB
+```javascript
+angular.module('BitNZ', []).factory('Api', ['$http', '$log', function ($http, $log) {
+  'use strict';
+  var api = {};
+  var host = 'https://bitnz.com/api/0';
+
+  var config = {
+    username: '',
+    key: '',
+    secret: ''
+  };
+  
+  var sign = function(parameters){
+    parameters = parameters || {};
+    var d = new Date();
+    parameters.nonce = d.getTime() + ''+ d.getMilliseconds();
+    parameters.key = config.key;
+    parameters.signature = CryptoJS.algo.HMAC
+                                .create(CryptoJS.algo.SHA256, config.secret)
+                                .update(parameters.nonce + config.username + config.key)
+                                .finalize()
+                                .toString(CryptoJS.enc.Hex)
+                                .toUpperCase();
+    return parameters;
+  };
+
+  var serialize = function(parameters) {
+    var params = [];
+    Object.keys(parameters).forEach(function(key){
+      this.push(key + '=' + parameters[key]);
+    }, params);
+    return params.join('&');
+  };
+
+  var request = function(method, action, parameters){
+    var config = {
+      method: method,
+      url: host + action,
+      data: serialize(parameters),
+      headers: {}
+    };
+    if (method === 'GET') {
+      config.params = serialize(parameters);
+    }
+    if (method === 'POST') {
+      config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
+    }
+    return $http(config);
+  };
+ 
+  var get = function(action, parameters){
+      return request('GET', action, parameters);
+  };
+
+  var post = function(action, parameters){
+    return request('POST', '/private' + action, sign(parameters));
+  };
+
+  // Save keys:
+  api.authorize = function(username, key, secret){
+    if (username.key !== undefined) {
+      key = username.key;
+      secret = username.secret;
+      username = username.username;
+    }
+    config = {
+      username: username,
+      key: key,
+      secret: secret
+    };
+  };
+
+  api.sign = sign;
+
+  // Open/Public API Calls:
+  api.ticker = function(){
+    return get('/ticker', {});
+  };
+
+  api.trades = function(lastTrade, fromDate) {
+    return get('/trades', {
+      'since': lastTrade || 0,
+      'since_date': fromDate || 0
+    });
+  };
+
+  api.chart = function(fromDate, width, height, background) {
+    return host + '/trades_chart?' + serialize({
+      'since_date': fromDate || 0,
+      'width': width || 600,
+      'height': height || 400,
+      'bgcolor': background || ''
+    });
+  };
+
+  api.orderbook = function() {
+    return get('/orderbook', {});
+  };
+
+  // Private API Calls:
+
+  api.balance = function() {
+    return post('/balance', {});
+  };
+
+  api.orders_buy_open = function() {
+    return post('/orders/buy/open', {});
+  };
+
+  api.orders_sell_open = function() {
+    return post('/orders/sell/open', {});
+  };
+
+  api.orders_buy_closed = function(offset, limit) {
+    return post('/orders/buy/closed', {
+      offset: offset || 0,
+      limit: limit || 0
+    });
+  };
+
+  api.orders_sell_closed = function(offset, limit) {
+    return post('/orders/sell/closed', {
+      offset: offset || 0,
+      limit: limit || 0
+    });
+  };
+
+  api.orders_buy_cancel = function(id) {
+    return post('/orders/buy/cancel', {
+      id: id
+    });
+  };
+
+  api.orders_sell_cancel = function(id) {
+    return post('/orders/sell/cancel', {
+      id: id
+    });
+  };
+
+  api.orders_buy_create = function(amount, price) {
+    return post('/orders/buy/create', {
+      amount: amount,
+      price: price
+    });
+  };
+
+  api.orders_sell_create = function(amount, price) {
+    return post('/orders/sell/create', {
+      amount: amount,
+      price: price
+    });
+  };
+
+  api.btc_deposit_address = function() {
+    return post('/btc/address', {});
+  };
+
+  api.btc_withdraw = function(address, amount) {
+    return post('/btc/withdraw', {
+      address: address,
+      amount: amount
+    });
+  };
+
+  return api;
+}]);
+```
+***
+### [PlayApp.js](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/b7e80d8cd2ac0cc37586ab563670d006db445755/PlayApp.js) -- application/javascript, 959.0B
+```javascript
+ var app = angular.module('Play', ['BitNZ']);
+app.controller('Example', ['$scope', '$log', 'Api', function($scope, $log, bitnz){
+  
+  $log.log('bitNZ', bitnz);
+
+  $scope.config = {
+    username: '',
+    key: '',
+    secret: ''
+  };
+
+  $scope.results = [];
+
+  $scope.Authorize = function(){
+    bitnz.authorize($scope.config);
+  };
+
+  $scope.GetTicker = function(){
+    if (!bitnz) {
+      $log.log('Uh oh!');
+      return;
+    }
+    bitnz.ticker().success(function(data, status){
+      $log.log('ticker', data, status);
+    });
+  };
+
+  $scope.GetChart = function() {
+    $scope.imageUrl = bitnz.chart();
+    return $scope.imageUrl;
+  };
+
+  $scope.OrderBook = function(){
+    bitnz.orderbook().success(function(data) {
+      $log.log('orderbook', data);
+    });
+  };
+
+  $scope.Balance = function(){
+    bitnz.balance().success(function(data) {
+      $log.log('balance', data);
+    }).error(function(){
+      $log.log('error', arguments);
+    });
+  };
+
+  
+
+}]);
+```
+***
+### [index.html](https://gist.githubusercontent.com/master5o1/542f067143918c237834/raw/5158c5dd6e0ff1b0cc98390bcae99a1ee6f79e2a/index.html) -- text/html, 1.2KiB
+```html
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js"></script>
+        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script>
+        <script src="BitNZService.js"></script>
+        <script src="PlayApp.js"></script>
+
+    </head>
+    <body ng-app="Play">
+        <div ng-controller="Example">
+            <div>
+                <input ng-model="config.username" placeholder="Username" />
+                <input ng-model="config.key" placeholder="Key" />
+                <input ng-model="config.secret" placeholder="Secret" />
+                <button ng-click="Authorize()">Authorize</button>
+            </div>
+
+            <button ng-click="GetTicker()">Ticker</button>
+            <button ng-click="OrderBook()">OrderBook</button>
+            <button ng-click="Balance()">Balance</button>
+            
+
+            <pre style="margin-top: 50px; border: solid 1px; background: #f1f1f1; padding: 10px;">
+                Config: {{ config }}
+            </pre>
+
+            <img ng-src="{{ GetChart() }}" alt="trade chart" />
+        </div>
+    </body>
+</html>
+```
+

+ 209 - 0
content/posts/gist/2014-07-30/e5d2776d44f7ee31820a.md

@@ -0,0 +1,209 @@
+---
+title: "index.html"
+date: 2014-07-30T12:16:05Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/e5d2776d44f7ee31820a)
+
+
+
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [index.html](https://gist.githubusercontent.com/master5o1/e5d2776d44f7ee31820a/raw/544210b01298dd60e5a1c0f6efe89b99b8867db0/index.html) | text/html | 2.3KiB |
+| [pretty-bitnz.js](https://gist.githubusercontent.com/master5o1/e5d2776d44f7ee31820a/raw/d25de702b311eb7901cab11a42ddc8671eb47e9e/pretty-bitnz.js) | application/javascript | 2.8KiB |
+***
+
+### [index.html](https://gist.githubusercontent.com/master5o1/e5d2776d44f7ee31820a/raw/544210b01298dd60e5a1c0f6efe89b99b8867db0/index.html) -- text/html, 2.3KiB
+```html
+<!DOCTYPE html>
+<html>
+    <head>
+        <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha256.js"></script>
+        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.17/angular.min.js"></script>
+        <script src="libs/bitnz-angular/bitnz-angular.js"></script>
+        <script src="js/pretty-bitnz.js"></script>
+        <style>
+        </style>
+    </head>
+    <body ng-app="PrettyBitNZ">
+        <div style="border: solid 1px #000">
+            <div ng-controller="Ticker">
+                <button ng-click="Start()">Start</button> <button ng-click="Stop()">Stop</button>
+                {{ ticker }}
+            </div>
+        </div>
+        <div style="border: solid 1px #000;">
+            <form ng-controller="Configuration" ng-submit="Authorize()">
+                <input type="text" placeholder="username" ng-model="username" />
+                <input type="text" placeholder="key" ng-model="key" />
+                <input type="text" placeholder="secret" ng-model="secret" />
+                <input type="submit" value="Authorize" />
+            </form>
+        </div>
+        <div style="border: solid 1px #000">
+            <div ng-controller="Balance">
+                <button ng-click="Start()">Start</button> <button ng-click="Stop()">Stop</button>
+                {{ balance }}
+            </div>
+        </div>
+        <div style="border: solid 1px #000">
+            <div ng-controller="OrderBook">
+                <div>
+                    <button ng-click="Start()">Start</button> <button ng-click="Stop()">Stop</button>
+                </div>
+                <div style="width: 50%; float: left;">
+                    <strong>Bids</strong>
+                    <ol>
+                        <li ng-repeat="bid in orderbook.bids | priceasc | reverse">{{ bid[1] | number : 8 }} @ ${{ bid[0] | number : 8 }}</li>
+                    </ol>
+                </div>
+                <div style="width: 50%; float: right;">
+                    <strong>Asks</strong>
+                    <ol>
+                        <li ng-repeat="ask in orderbook.asks | priceasc">{{ ask[1] | number : 8 }} @ ${{ ask[0] | number : 8 }}</li>
+                    </ol>
+                </div>
+                <div style="clear: both;"></div>
+            </div>
+        </div>
+    </body>
+</html>
+```
+***
+### [pretty-bitnz.js](https://gist.githubusercontent.com/master5o1/e5d2776d44f7ee31820a/raw/d25de702b311eb7901cab11a42ddc8671eb47e9e/pretty-bitnz.js) -- application/javascript, 2.8KiB
+```javascript
+var app = angular.module('PrettyBitNZ', ['BitNZ']);
+
+app.filter('priceasc', function() {
+  return function(items) {
+    var list = items.slice();
+    list.sort(function(a, b) {
+      return a[0] - b[0];
+    });
+    return list;
+  };
+});
+
+app.filter('reverse', function() {
+  return function(items) {
+    return items.slice().reverse();
+  };
+});
+
+app.controller('Configuration', ['$scope', '$log', 'BitNZ', function($scope, $log, bitnz){
+  $scope.username = '';
+  $scope.key = '';
+  $scope.secret = '';
+
+  $scope.Authorize = function() {
+    bitnz.authorize($scope.username, $scope.key, $scope.secret);
+  };
+}]);
+
+app.controller('Ticker', ['$scope', '$interval', '$log', 'BitNZ', function($scope, $interval, $log, bitnz){
+  $scope.ticker = {};
+
+  var interval = null;
+
+  var fn = function(){
+    $log.info('run');
+    bitnz.ticker().success(function(data){
+      $log.log('ticker', data);
+      $scope.ticker = data;
+    }).error(function(data){
+      $log.error('ticker', data);
+      $scope.Stop();
+    });
+  };
+
+  $scope.Start = function() {
+    $log.info('ticker', 'start');
+    fn();
+    interval = $interval(fn, 60 * 1000);
+  };
+
+  $scope.Stop = function() {
+    $log.info('ticker', 'stop');
+    if (angular.isDefined(interval)) {
+      $interval.cancel(interval);
+      interval = undefined;
+    }
+  };
+
+}]);
+
+app.controller('OrderBook', ['$scope', '$interval', '$log', 'BitNZ', function($scope, $interval, $log, bitnz){
+  $scope.orderbook = {
+    bids: [],
+    asks: []
+  };
+
+  var interval = null;
+
+  var fn = function(){
+    $log.info('run');
+    bitnz.orderbook().success(function(data){
+      $log.log('orderbook', data);
+      $scope.orderbook = data;
+    }).error(function(data){
+      $log.error('orderbook', data);
+      $scope.Stop();
+    });
+  };
+
+  $scope.Start = function() {
+    $log.info('orderbook', 'start');
+    fn();
+    interval = $interval(fn, 60 * 1000);
+  };
+
+  $scope.Stop = function() {
+    $log.info('orderbook', 'stop');
+    if (angular.isDefined(interval)) {
+      $interval.cancel(interval);
+      interval = undefined;
+    }
+  };
+
+}]);
+
+app.controller('Balance', ['$scope', '$interval', '$log', 'BitNZ', function($scope, $interval, $log, bitnz){
+  $scope.balance = {};
+
+  var interval = null;
+
+  var fn = function(){
+    $log.info('run');
+    bitnz.balance().success(function(data){
+      if (data.result === false) {
+        $scope.Stop();
+        return;
+      }
+      $log.log('balance', data);
+      $scope.balance = data;
+    }).error(function(data){
+      $log.error('balance', data);
+      $scope.Stop();
+    });
+  };
+
+  $scope.Start = function() {
+    $log.info('balance', 'start');
+    fn();
+    interval = $interval(fn, 60 * 1000);
+  };
+
+  $scope.Stop = function() {
+    $log.info('balance', 'stop');
+    if (angular.isDefined(interval)) {
+      $interval.cancel(interval);
+      interval = undefined;
+    }
+  };
+
+}]);
+```
+

+ 16 - 0
content/posts/gist/2014-09-03/169489838b9e5ee0d100.md

@@ -0,0 +1,16 @@
+---
+title: "gistfile1.txt"
+date: 2014-09-03T01:33:51Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/169489838b9e5ee0d100)
+
+
+
+
+
+```text
+Verifying that +master5o1 is my Bitcoin username. You can send me #bitcoin here: https://onename.io/master5o1
+```
+

+ 436 - 0
content/posts/gist/2014-12-18/0ac511e0a3ec0cd5cf4a.md

@@ -0,0 +1,436 @@
+---
+title: "WebSocketRpc.js"
+date: 2014-12-18T04:29:14Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/0ac511e0a3ec0cd5cf4a)
+
+
+WebSocket RPC
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [WebSocketRpc.js](https://gist.githubusercontent.com/master5o1/0ac511e0a3ec0cd5cf4a/raw/242aff878b0c1736788e89c14ca67fec6a58cbb5/WebSocketRpc.js) | application/javascript | 7.4KiB |
+| [index.html](https://gist.githubusercontent.com/master5o1/0ac511e0a3ec0cd5cf4a/raw/c6d7194451487aa18a0163fcac7f420cf377cbc2/index.html) | text/html | 2.4KiB |
+***
+
+### [WebSocketRpc.js](https://gist.githubusercontent.com/master5o1/0ac511e0a3ec0cd5cf4a/raw/242aff878b0c1736788e89c14ca67fec6a58cbb5/WebSocketRpc.js) -- application/javascript, 7.4KiB
+```javascript
+function WebSocketRpc(url, batchOperationsDisabled) {
+  'use strict';
+  var self = this;
+  var socket = null;
+  var queue = [];
+  var history = {};
+  var methods = {};
+  var noop = function () {};
+  var noopFactory = function () {
+    return noop;
+  };
+
+  var eventHandlers = {
+    error: noop,
+    ready: noop,
+    close: noop,
+    notification: noop,
+    message: noop
+  };
+
+  var exceptions = {
+    ParseError: {
+      code: -32700,
+      message: 'Parse error'
+    },
+    MethodNotFound: {
+      code: -32601,
+      message: 'Method not found'
+    }
+  };
+
+  init();
+
+  function init() {
+    self.call = function () {
+      queue.push([].slice.call(arguments));
+      return self;
+    };
+    self.batch = function () {
+      if (batchOperationsDisabled) {
+        throw new Error('Batch Operations Disabled');
+      }
+      queue = queue.concat([].slice.call(arguments));
+      return self;
+    };
+
+    self.connect = connect;
+    self.expose = expose;
+    self.exceptions = exceptions;
+  }
+
+  function connect() {
+    socket = new WebSocket(url);
+    self.ws = socket;
+    socket.onopen = opened;
+    socket.onerror = error;
+    socket.onmessage = handler;
+    socket.onclose = onclose;
+    return self;
+  }
+
+  function opened(event) {
+    eventHandlers.ready.call(self, event);
+
+    if (batchOperationsDisabled) {
+      while (queue.length > 0) {
+        call.apply(self, queue.shift());
+      }
+    } else {
+      batch.apply(self, queue);
+    }
+
+    self.call = call;
+    self.batch = batch;
+    self.connect = noop;
+  }
+
+  function error(event) {
+    eventHandlers.error.call(self, event);
+  }
+
+  function handler(event) {
+    eventHandlers.message.call(self, event);
+    var data;
+    try {
+      data = JSON.parse(event.data);
+    } catch (e) {
+      console.error(e);
+      var request = formatResponse(exceptions.ParseError, null, {
+        id: null
+      });
+      socket.send(JSON.stringify(request));
+    }
+    if (!data) {
+      return;
+    }
+    if (Object.prototype.toString.call(data) === '[object Array]') {
+      new Batched(data, event).handle();
+      return;
+    }
+    new Single(data, event).handle();
+  }
+
+  function onclose(event) {
+    eventHandlers.close.call(self, event);
+  }
+
+  function Batched(responses, event) {
+    var _self = this;
+    var batchRequest = [];
+    var batchNofications = [];
+    _self.handle = handle;
+
+    function trySend() {
+      var combined = batchRequest.length + batchNofications.length;
+      if (combined >= responses.length) {
+        socket.send(JSON.stringify(batchRequest));
+        return;
+      }
+    }
+
+    function next(res) {
+      return function (error, result) {
+        var request = formatResponse(error, result, res);
+        batchRequest.push(request);
+        trySend();
+      };
+    }
+
+    function notify(res) {
+      return function (error, result) {
+        batchNofications.push(res);
+      };
+    }
+
+    function handle() {
+      responses.forEach(function (response) {
+        new Single(response, event, next, notify).handle();
+      });
+      return _self;
+    }
+
+    return _self;
+  }
+
+  function Single(response, event, _next, _nextNoop) {
+    var _self = this;
+    _nextNoop = _nextNoop || noopFactory;
+    _self.next = next;
+    _self.handle = handle;
+    _self.method = method;
+    _self.notification = notification;
+    _self.results = results;
+
+    function next(res) {
+      return function (error, result) {
+        var request = formatResponse(error, result, res);
+        socket.send(JSON.stringify(request));
+      };
+    }
+
+    function handle() {
+      if (response.method !== undefined && response.params !== undefined) {
+        return !!method(response, event);
+      }
+      if (response.id === null) {
+        return !!notification(response, event);
+      }
+      results(response, event);
+      return _self;
+    }
+
+    function method(response, event) {
+      var cb = methods[response.method] || rpcException(exceptions.MethodNotFound);
+      var n = _next || next;
+      if (response.id === null) {
+        n = _nextNoop || noopFactory;
+      }
+      cb.call(self, response.params, n(response), response, response.id === null);
+      return _self;
+    }
+
+    function notification(response, event) {
+      response.id = response.error === undefined ? response.id : response.error.id;
+      response.id = response.id || null;
+      if (response.id === null) {
+        console.log('notification:', response);
+        eventHandlers.notification.call(self, response.error, response.result, response, event);
+        return _self;
+      }
+      handle(response, event);
+      return _self;
+    }
+
+    function results(response, event) {
+      var item = history[response.id] || {};
+      item.response = response;
+      item.callback.call(self, item.response.error, item.response.result, item.response, item.request, event);
+      return _self;
+    }
+    return _self;
+  }
+
+  function formatResponse(error, result, response) {
+    var request = {
+      jsonrpc: '2.0',
+      id: response.id || null
+    };
+    if ( !! error) {
+      request.error = error;
+    }
+    if ( !! result) {
+      request.result = result;
+    }
+    return request;
+  }
+
+  function onErrorCallback(error) {
+    return function (params, callback, response, isNotification) {
+      callback(error);
+      var cb = onError || noop;
+      cb.call(self, error);
+    };
+  }
+
+  function rpcException(error) {
+    return function (params, callback, response, isNotification) {
+      callback(error);
+    };
+  }
+
+  function send(id) {
+    var request = collateRequest(id);
+    socket.send(JSON.stringify(request));
+  }
+
+  function collateRequest(id) {
+    var ids = id;
+    if (typeof id === 'string') {
+      return prepareRequest(id);
+    }
+    return ids.map(prepareRequest);
+  }
+
+  function prepareRequest(id) {
+    var item = history[id];
+    if (typeof item.callback !== 'function') {
+      item.request.id = null;
+    }
+    return item.request;
+  }
+
+  function identity(size, v) {
+    v = new Array(size || 20).join('.').split('').map(function () {
+      return Math.round(Math.random() * 100);
+    }).join('');
+    return (1 * v).toString(36);
+  }
+
+  function createRequest(method, parameters, callback, id) {
+    id = id || identity();
+    var request = {
+      jsonrpc: '2.0',
+      id: id || null,
+      method: method,
+      params: parameters
+    };
+    history[id] = {
+      method: method,
+      request: request,
+      callback: callback,
+      response: null
+    };
+    return id;
+  }
+
+  function call(method, parameters, callback, id) {
+    id = createRequest(method, parameters, callback, id);
+    send(id);
+    return self;
+  }
+
+  function batch(requests) {
+    if (batchOperationsDisabled) {
+      throw new Error('Batch Operations Disabled');
+    }
+    requests = [].slice.call(arguments);
+    if (requests.length === 1) {
+      call.apply(self, requests[0]);
+      return;
+    }
+    var ids = requests.map(function (request) {
+      return createRequest.apply(self, request);
+    });
+    send(ids);
+    return self;
+  }
+
+  function expose(method, fn) {
+    if (typeof fn !== 'function') {
+      Object.keys(fn).forEach(function (key) {
+        methods[method + '.' + key] = fn[key];
+      }, methods);
+    }
+    methods[method] = fn;
+    return self;
+  }
+
+  function on(eventName, handler) {
+    eventHandlers[eventName] = handler;
+    return self;
+  }
+
+  function off(eventName) {
+    eventHandlers[eventName] = noop;
+    return self;
+  }
+
+  function close() {
+    if (socket !== null) {
+      socket.close();
+    }
+  }
+
+  self.close = close;
+  self.on = on;
+  self.off = off;
+  self.ws = socket;
+
+  return self;
+}
+```
+***
+### [index.html](https://gist.githubusercontent.com/master5o1/0ac511e0a3ec0cd5cf4a/raw/c6d7194451487aa18a0163fcac7f420cf377cbc2/index.html) -- text/html, 2.4KiB
+```html
+<html>
+  <head>
+    <script src="WebSocketRpc.js"></script>
+    <script>
+
+    // Setup RPC
+    var rpc = new WebSocketRpc('ws://echo.websocket.org'/*, true */); // pass true to disable sending batched calls.
+    
+    // Want to do stuff on open, error and close.
+    rpc.on('ready', function(event){ console.log('socket is ready'); })
+       .on('error', function(event){ console.log('oh my an error occurred', event); })
+       .on('close', function(event){ console.log('socket is closed'); })
+       
+    // We'll use this for handling JSON-RPC 2.0 notification result/error messages.
+    rpc.on('notification', function(error, results, response, event){
+      if (error) {
+        console.error('what, an error notification?', error);
+        return;
+      }
+      console.log('oh good, a notification', results);
+    })
+
+    // Let's set up a method that the server can call for the client to do.
+    rpc.expose('add', function(params, callback) {
+      console.log('exposed add:', params);
+      var result = params[0] + params[1];
+      callback(null, result);
+    });
+
+    // Let's set up another one, which we'll use as a notification.
+    rpc.expose('notification', function(params, callback){
+      console.log('exposed notification:', params);
+      callback();
+    });
+
+    // Can also set up a namedspaced object of methods.
+    rpc.expose('math', {
+      add: function(params, callback) {
+        callback(null, params[0] + params[1]);
+      },
+      subtract: function(params, callback) {
+        callback(null, params[0] - params[1]);
+      },
+      multiply: function(params, callback) {
+        callback(null, params[0] * params[1]);
+      }
+    });
+
+    // Call a method on the server.
+    rpc.call('add', [5, 10], function(error, result, response, request, event){
+      console.log(arguments);
+    });
+
+    // Send the notification to the server.
+    rpc.call('notification', 'Still Alive');
+
+    // Call a namespaced method.
+    rpc.call('math.multiply', [21, 34], function(error, results){
+      console.log('math.multiply', results);
+    });
+
+    rpc.batch(['math.subtract', [5, 3], function(error, result) {
+      console.log('subtract', result);
+    }], ['math.divide', [5, 3], function(error, result) {
+      if (error) {
+        console.error('divide', error);
+        return;
+      }
+      console.log('divide', result);
+    }]);
+
+    rpc.connect();
+
+    </script>
+  </head>
+  <body>
+    Look in the JS console.
+  </body>
+</html>
+```
+

+ 185 - 0
content/posts/gist/2015-02-28/1e8f24628ab13282145a.md

@@ -0,0 +1,185 @@
+---
+title: "index.html"
+date: 2015-02-28T10:18:44Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/1e8f24628ab13282145a)
+
+
+Simpler Name Generator Thing
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [index.html](https://gist.githubusercontent.com/master5o1/1e8f24628ab13282145a/raw/8b137e14ee76a08417e76655dd57b72fb2065201/index.html) | text/html | 746.0B |
+| [script.js](https://gist.githubusercontent.com/master5o1/1e8f24628ab13282145a/raw/bf25b704bb18cbf6048d2300086e71d984f7428a/script.js) | application/javascript | 3.7KiB |
+***
+
+### [index.html](https://gist.githubusercontent.com/master5o1/1e8f24628ab13282145a/raw/8b137e14ee76a08417e76655dd57b72fb2065201/index.html) -- text/html, 746.0B
+```html
+<html>
+    
+    <head></head>
+    
+    <body>
+        <strong>Markov Team Name Generator</strong><br />
+        <button id="get-markov-name">Get Name</button><br />
+        <strong>Generated Name:</strong>
+        <span id="generated-name">click Get Name to generate a name</span><br />
+        <textarea style="min-width:200px; min-height: 400px;" id="previous-names"></textarea><br />
+        <span>Source names based on people in the <a href="http://en.wikipedia.org/wiki/New_Zealand_national_cricket_team#Current_squad">Black Caps</a>, the New Zealand national cricket team<br />
+        <a href="https://gist.github.com/master5o1/1e8f24628ab13282145a">gist source</a> on GitHub.
+        <script src="script.js"></script>
+    </body>
+
+</html>
+```
+***
+### [script.js](https://gist.githubusercontent.com/master5o1/1e8f24628ab13282145a/raw/bf25b704bb18cbf6048d2300086e71d984f7428a/script.js) -- application/javascript, 3.7KiB
+```javascript
+document.getElementById('get-markov-name').onclick = team;
+
+function team() {
+    var players = [
+        ['Brendon', 'McCullum'],
+        ['Kane', 'Williamson'],
+        ['Ross', 'Taylor'],
+        ['Martin', 'Guptill'],
+        ['Hamish', 'Rutherford'],
+        ['Dean', 'Brownlie'],
+        ['Colin', 'Munro'],
+        ['Tom', 'Latham'],
+        ['BJ', 'Watling'],
+        ['Luke', 'Ronchi'],
+        ['Corey', 'Anderson'],
+        ['Grant', 'Elliott'],
+        ['Nathan', 'McCullum'],
+        ['Anton', 'Devcich'],
+        ['Jimmy', 'Neesham'],
+        ['Daniel', 'Vettori'],
+        ['Pace', 'Bowlers'],
+        ['Trent', 'Boult'],
+        ['Doug', 'Bracewell'],
+        ['Mitchell', 'McClenaghan'],
+        ['Kyle', 'Mills'],
+        ['Tim', 'Southee'],
+        ['Neil', 'Wagner'],
+        ['Hamish', 'Bennett'],
+        ['Andrew', 'Ellis'],
+        ['Matt', 'Henry'],
+        ['Adam', 'Milne'],
+        ['Ish', 'Sodhi'],
+        ['Mark', 'Craig']
+    ];
+
+    var firstNames = players.map(function (player) {
+        return player[0];
+    });
+
+    var lastNames = players.map(function (player) {
+        return player[1];
+    });
+    
+    var firstName = processList(firstNames, Infinity, true);
+    var lastName = processList(lastNames, Infinity, true);
+    var fullName = firstName + ' ' + lastName;
+
+    var html = document.getElementById('previous-names').innerHTML;
+    document.getElementById('previous-names').innerHTML = fullName + '\r\n' + html;
+    document.getElementById('generated-name').innerHTML = fullName;
+}
+
+function processList(namesList, useAverageNameLength, useRandomFirstLetters) {
+    var firstTwoLetters = mode(namesList.map(function (name) {
+        return name.substring(0, 2);
+    }));
+    
+    if (useRandomFirstLetters) {
+        firstTwoLetters = pickRandomly(namesList.map(function (name) {
+            return name.substring(0, 2);
+        }));   
+    }
+
+    var avgNameLength = avg(namesList.map(function (name) {
+        return name.length;
+    }));
+
+    var markov = processWords(namesList);
+
+    if (useAverageNameLength === true) {
+        return buildString(markov, firstTwoLetters, avgNameLength);
+    }
+
+    return buildString(markov, firstTwoLetters, useAverageNameLength);
+}
+
+function processWords(words) {
+    var dict = {};
+    for (var i = 0; i < words.length; i++) {
+        dict = generateMarkov(words[i], dict);
+    }
+    return dict;
+}
+
+function generateMarkov(letters, dict) {
+    var i, key, letter, first, second, third;
+
+    i = 0;
+    first = letters[i++];
+    second = letters[i++];
+    while (i < letters.length) {
+        third = letters[i++];
+        key = first + second;
+        dict[key] = dict[key] || [];
+        dict[key].push(third);
+        first = second;
+        second = third;
+    }
+
+    return dict;
+}
+
+function buildString(dict, start, maxLength) {
+    var dictKeys = Object.keys(dict);
+    var key = start;
+    var str = start;
+    while (typeof dict[key] !== 'undefined' && str.length < maxLength) {
+        var value = dict[key];
+        var third = pickRandomly(value);
+        str = str + third;
+        key = key.split('')[1] + third;
+    }
+    return str;
+}
+
+function mode(list) {
+    var frequency, items;
+
+    frequency = {};
+    list.forEach(function (item) {
+        this[item] = this[item] || 0;
+        this[item] = this[item] + 1;
+    }, frequency);
+    items = Object.keys(frequency);
+    items.sort(function (a, b) {
+        return frequency[b] - frequency[a];
+    });
+
+    return items[0];
+}
+
+function pickRandomly(list) {
+    var index = Math.round(Math.random() * list.length) % list.length;
+    return list[index];
+}
+
+function avg(list) {
+    var sum = list.reduce(function (p, c) {
+        return p + c;
+    }, 0);
+    var total = list.length;
+    return Math.round(sum / total);
+}
+```
+

+ 215 - 0
content/posts/gist/2015-02-28/ae3fe23d8b6e0e5a36d1.md

@@ -0,0 +1,215 @@
+---
+title: "index.html"
+date: 2015-02-28T09:58:05Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/ae3fe23d8b6e0e5a36d1)
+
+
+Name Generator
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [index.html](https://gist.githubusercontent.com/master5o1/ae3fe23d8b6e0e5a36d1/raw/3d0c9a13b24e0b8fe365ff7884c51b18116b8449/index.html) | text/html | 1.2KiB |
+| [script.js](https://gist.githubusercontent.com/master5o1/ae3fe23d8b6e0e5a36d1/raw/c271ba3182622ca42d4a6770faea8996a19d4996/script.js) | application/javascript | 4.2KiB |
+***
+
+### [index.html](https://gist.githubusercontent.com/master5o1/ae3fe23d8b6e0e5a36d1/raw/3d0c9a13b24e0b8fe365ff7884c51b18116b8449/index.html) -- text/html, 1.2KiB
+```html
+<html>
+    
+    <head></head>
+    
+    <body>
+<strong>Markov Team Name Generator</strong>
+        <br />
+        <button id="get-markov-name">Get Name</button>
+        <p>First table shows names generated by creating a first name starting with the most common first two letters, and a last name starting with the most common first two letters.</p>
+        <table border=1>
+            <thead>
+                <th>Max name length 15 characters</th>
+                <th>Using Average Name Length</th>
+                <th>No Max Length</th>
+            </thead>
+            <tbody id="output"></tbody>
+        </table>
+        <p>Second table creates names where the first name starts with a random pair of first letters and same case for the last name.</p>
+        <table border=1>
+            <thead>
+                <th>Max name length 15 characters</th>
+                <th>Using Average Name Length</th>
+                <th>No Max Length</th>
+            </thead>
+            <tbody id="output-arbitrary"></tbody>
+        </table>
+        <a href="https://gist.github.com/master5o1/ae3fe23d8b6e0e5a36d1">gist source</a> on github
+        <script src="script.js"></script>
+    </body>
+
+</html>
+```
+***
+### [script.js](https://gist.githubusercontent.com/master5o1/ae3fe23d8b6e0e5a36d1/raw/c271ba3182622ca42d4a6770faea8996a19d4996/script.js) -- application/javascript, 4.2KiB
+```javascript
+document.getElementById('get-markov-name').onclick = team;
+
+function team() {
+    var players = [
+        ['Brendon', 'McCullum'],
+        ['Kane', 'Williamson'],
+        ['Ross', 'Taylor'],
+        ['Martin', 'Guptill'],
+        ['Hamish', 'Rutherford'],
+        ['Dean', 'Brownlie'],
+        ['Colin', 'Munro'],
+        ['Tom', 'Latham'],
+        ['BJ', 'Watling'],
+        ['Luke', 'Ronchi'],
+        ['Corey', 'Anderson'],
+        ['Grant', 'Elliott'],
+        ['Nathan', 'McCullum'],
+        ['Anton', 'Devcich'],
+        ['Jimmy', 'Neesham'],
+        ['Daniel', 'Vettori'],
+        ['Pace', 'Bowlers'],
+        ['Trent', 'Boult'],
+        ['Doug', 'Bracewell'],
+        ['Mitchell', 'McClenaghan'],
+        ['Kyle', 'Mills'],
+        ['Tim', 'Southee'],
+        ['Neil', 'Wagner'],
+        ['Hamish', 'Bennett'],
+        ['Andrew', 'Ellis'],
+        ['Matt', 'Henry'],
+        ['Adam', 'Milne'],
+        ['Ish', 'Sodhi'],
+        ['Mark', 'Craig']
+    ];
+
+    var firstNames = players.map(function (player) {
+        return player[0];
+    });
+
+    var lastNames = players.map(function (player) {
+        return player[1];
+    });
+    
+    var html = '';
+    
+    
+    html = '<tr>';
+    html = addHtml(html, firstNames, lastNames, 15);
+    html = addHtml(html, firstNames, lastNames, true);
+    html = addHtml(html, firstNames, lastNames, Infinity);
+    html += '</tr>';
+    document.getElementById('output').innerHTML += html;
+    
+    html = '<tr>';
+    html = addHtml(html, firstNames, lastNames, 15, true);
+    html = addHtml(html, firstNames, lastNames, true, true);
+    html = addHtml(html, firstNames, lastNames, Infinity, true);
+    html += '</tr>';
+    document.getElementById('output-arbitrary').innerHTML += html;
+}
+
+function addHtml(html, firstNames, lastNames, maxLength, useRandomFirstLetters) {
+    firstName = processList(firstNames, maxLength, useRandomFirstLetters);
+    lastName = processList(lastNames, maxLength, useRandomFirstLetters);
+    return html + '<td>' + firstName + ' ' + lastName + '</td>';
+}
+
+function processList(namesList, useAverageNameLength, useRandomFirstLetters) {
+    var firstTwoLetters = mode(namesList.map(function (name) {
+        return name.substring(0, 2);
+    }));
+    
+    if (useRandomFirstLetters) {
+        firstTwoLetters = pickRandomly(namesList.map(function (name) {
+            return name.substring(0, 2);
+        }));   
+    }
+
+    var avgNameLength = avg(namesList.map(function (name) {
+        return name.length;
+    }));
+
+    var markov = processWords(namesList);
+
+    if (useAverageNameLength === true) {
+        return buildString(markov, firstTwoLetters, avgNameLength);
+    }
+
+    return buildString(markov, firstTwoLetters, useAverageNameLength);
+}
+
+function processWords(words) {
+    var dict = {};
+    for (var i = 0; i < words.length; i++) {
+        dict = generateMarkov(words[i], dict);
+    }
+    return dict;
+}
+
+function generateMarkov(letters, dict) {
+    var i, key, letter, first, second, third;
+
+    i = 0;
+    first = letters[i++];
+    second = letters[i++];
+    while (i < letters.length) {
+        third = letters[i++];
+        key = first + second;
+        dict[key] = dict[key] || [];
+        dict[key].push(third);
+        first = second;
+        second = third;
+    }
+
+    return dict;
+}
+
+function buildString(dict, start, maxLength) {
+    var dictKeys = Object.keys(dict);
+    var key = start;
+    var str = start;
+    while (typeof dict[key] !== 'undefined' && str.length < maxLength) {
+        var value = dict[key];
+        var third = pickRandomly(value);
+        str = str + third;
+        key = key.split('')[1] + third;
+    }
+    return str;
+}
+
+function mode(list) {
+    var frequency, items;
+
+    frequency = {};
+    list.forEach(function (item) {
+        this[item] = this[item] || 0;
+        this[item] = this[item] + 1;
+    }, frequency);
+    items = Object.keys(frequency);
+    items.sort(function (a, b) {
+        return frequency[b] - frequency[a];
+    });
+
+    return items[0];
+}
+
+function pickRandomly(list) {
+    var index = Math.round(Math.random() * list.length) % list.length;
+    return list[index];
+}
+
+function avg(list) {
+    var sum = list.reduce(function (p, c) {
+        return p + c;
+    }, 0);
+    var total = list.length;
+    return Math.round(sum / total);
+}
+```
+

+ 33 - 0
content/posts/gist/2015-03-26/0199179c7f57ea7a379a.md

@@ -0,0 +1,33 @@
+---
+title: "konami.js"
+date: 2015-03-26T03:29:02Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/0199179c7f57ea7a379a)
+
+
+
+
+
+```javascript
+konami(function(){
+  console.log('KONAMI!!!');
+});
+
+function konami(fn, match) {
+  var konamiCode = '3838404037393739666513';
+  var sequence = '';
+  match = match || konamiCode;
+  window.addEventListener('keyup', function(event){
+    sequence += event.keyCode;
+    if (match === sequence) {
+      fn();
+    }
+    if (match.indexOf(sequence) === -1) {
+      sequence = '';
+    }
+  }, false); 
+}
+```
+

+ 39 - 0
content/posts/gist/2015-04-22/23dc705d3a181f532484.md

@@ -0,0 +1,39 @@
+---
+title: "not-ie.js"
+date: 2015-04-22T05:19:17Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/23dc705d3a181f532484)
+
+
+Small is or is not internet explorer. Provides .ie or .is-ie and .not-ie css classes.
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [not-ie.js](https://gist.githubusercontent.com/master5o1/23dc705d3a181f532484/raw/ccfc6ce0e4801dd4893b4b22f092b89d092e84ee/not-ie.js) | application/javascript | 440.0B |
+| [not-ie.min.js](https://gist.githubusercontent.com/master5o1/23dc705d3a181f532484/raw/ce1bf33634ef7b8c46226f7864284ea023ce78c2/not-ie.min.js) | application/javascript | 368.0B |
+***
+
+### [not-ie.js](https://gist.githubusercontent.com/master5o1/23dc705d3a181f532484/raw/ccfc6ce0e4801dd4893b4b22f092b89d092e84ee/not-ie.js) -- application/javascript, 440.0B
+```javascript
+(function(n, o, t, i, e){
+	n.isIE = t;
+	if (t) {
+		o.styleSheets[0].addRule('.ie, .is-ie', 'display: initial');
+		o.styleSheets[0].addRule('.not-ie', 'display: none');
+		return;
+	}
+	i = o.createElement('style');
+	i.innerHTML = '.ie,.is-ie { display: none; } .not-ie: { display: initial; }'
+	e = document.getElementsByTagName('script')[0];
+	e.parentNode.insertBefore(i, e);
+})(window, document, /*@cc_on!@*/false || !!document.documentMode);
+```
+***
+### [not-ie.min.js](https://gist.githubusercontent.com/master5o1/23dc705d3a181f532484/raw/ce1bf33634ef7b8c46226f7864284ea023ce78c2/not-ie.min.js) -- application/javascript, 368.0B
+```javascript
+(function(d,a,e,b,c){(d.isIE=e)?(a.styleSheets[0].addRule(".ie, .is-ie","display: initial"),a.styleSheets[0].addRule(".not-ie","display: none")):(b=a.createElement("style"),b.innerHTML=".ie,.is-ie { display: none; } .not-ie: { display: initial; }",c=document.getElementsByTagName("script")[0],c.parentNode.insertBefore(b,c))})(window,document,!!document.documentMode);
+```
+

+ 31 - 0
content/posts/gist/2015-04-22/d75343d1a8f7761212f6.md

@@ -0,0 +1,31 @@
+---
+title: "hangman.js"
+date: 2015-04-22T23:14:47Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/d75343d1a8f7761212f6)
+
+
+
+
+
+```javascript
+function hangman(word) {
+    var reference = word.replace(/[a-zA-Z]/g,'-');
+    function reveal(letter) {
+        reference = reference.split('').map(function(v, i){
+            return word[i] === letter ? letter : v;
+        }).join('');
+        return reference;
+    };
+    return {
+        reveal: reveal
+    };
+}
+
+var game = hangman('carrot');
+console.log(game.reveal('r'));
+console.log(game.reveal('a'));
+```
+

+ 46 - 0
content/posts/gist/2015-07-13/2f8bc9aeabf8045e34c0.md

@@ -0,0 +1,46 @@
+---
+title: "MockAjax.js"
+date: 2015-07-13T23:48:29Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/2f8bc9aeabf8045e34c0)
+
+
+silly little thing.
+
+
+```javascript
+function MockAjax() {
+	var self = this;
+	var responses = {
+		'http://api.example.com/cart/add.json?a=5&b=3': {
+			"data": 8
+		}
+	};
+
+	function request(url, success, failure) {
+		window.setTimeout(function () {
+			if (responses[url] === undefined) {
+				failure();
+				return;
+			}
+			success(responses[url]);
+		}, Math.random() * 1000);
+	}
+
+	self.mock = function(url, response) {
+		responses[url] = response;
+	};
+	self.get = function(url, success, failure) {
+		request(url, success, failure);
+	};
+	
+	self.post = function(url, success, failure) {
+		request(url, success, failure);
+	};
+
+	return self;
+}
+```
+

+ 38 - 0
content/posts/gist/2015-08-06/7783eac88f2fc8d914a7.md

@@ -0,0 +1,38 @@
+---
+title: "radionz-rss-feeds.html"
+date: 2015-08-06T09:05:39Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/7783eac88f2fc8d914a7)
+
+
+
+
+
+```html
+<a href="http://www.radionz.co.nz/podcasts/atthemovies.rss">http://www.radionz.co.nz/podcasts/atthemovies.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/aucklandstories.rss">http://www.radionz.co.nz/podcasts/aucklandstories.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/bestoftheweek.rss">http://www.radionz.co.nz/podcasts/bestoftheweek.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/businessnews.rss">http://www.radionz.co.nz/podcasts/businessnews.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/checkpoint.rss">http://www.radionz.co.nz/podcasts/checkpoint.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/downthelist.rss">http://www.radionz.co.nz/podcasts/downthelist.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/focusonpolitics.rss">http://www.radionz.co.nz/podcasts/focusonpolitics.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/greatencounters.rss">http://www.radionz.co.nz/podcasts/greatencounters.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/inparliament.rss">http://www.radionz.co.nz/podcasts/inparliament.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/insight.rss">http://www.radionz.co.nz/podcasts/insight.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/introducing.rss">http://www.radionz.co.nz/podcasts/introducing.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/afternoons.rss">http://www.radionz.co.nz/podcasts/afternoons.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/lateedition.rss">http://www.radionz.co.nz/podcasts/lateedition.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/mediawatch.rss">http://www.radionz.co.nz/podcasts/mediawatch.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/morningreport.rss">http://www.radionz.co.nz/podcasts/morningreport.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/nights.rss">http://www.radionz.co.nz/podcasts/nights.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/ninetonoon.rss">http://www.radionz.co.nz/podcasts/ninetonoon.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/ourchangingworld.rss">http://www.radionz.co.nz/podcasts/ourchangingworld.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/saturday.rss">http://www.radionz.co.nz/podcasts/saturday.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/thepanel.rss">http://www.radionz.co.nz/podcasts/thepanel.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/theweekinreview.rss">http://www.radionz.co.nz/podcasts/theweekinreview.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/thiswayup.rss">http://www.radionz.co.nz/podcasts/thiswayup.rss</a>
+<br /> <a href="http://www.radionz.co.nz/podcasts/parliament.rss">http://www.radionz.co.nz/podcasts/parliament.rss</a>
+```
+

+ 103 - 0
content/posts/gist/2015-08-19/4cf9bf1096c5d113a01a.md

@@ -0,0 +1,103 @@
+---
+title: "lolcryption.py"
+date: 2015-08-19T09:24:48Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/4cf9bf1096c5d113a01a)
+
+
+
+
+
+```python
+"""
+lolcryption.py
+Translates text into LOLcrypted ciphertext. <http://lolcryption.master5o1.com/>
+Created By:
+    - Jason Schwarzenberger <https://github.com/master5o1>
+License:
+    MIT
+"""
+
+from cloudbot import hook
+import math
+
+@hook.command()
+def enlolcrypt(text):
+	""" enlolcrypt <text> -- enLOLcrypts <text> in <ciphertext>. """
+	return tr(text, "aeioubcdfghjklmnpqrstvwxyz", "iouaenpqrstvwxyzbcdfghjklm")
+
+@hook.command()
+def delolcrypt(text):
+	""" delolcrypt <ciphertext> -- deLOLcrypts <ciphertext> in <text>. """
+	return tr(text, "iouaenpqrstvwxyzbcdfghjklm", "aeioubcdfghjklmnpqrstvwxyz")
+
+@hook.command()
+def detheucon(text):
+    """ detheucon <text> -- unscrambles Theucon scrambled <text>. """
+    return theucon_decrypt(text)
+    
+@hook.command()
+def entheucon(text):
+    """ entheucon <text> -- scrambles <text> using Theucon algorithm. """
+    return theucon_encrypt(text)
+
+def theucon_encrypt(text):
+    output = ""
+    remaining = text
+    while len(remaining) > 0:
+        primeIndexed = ""
+        nonPrimeIndexed = ""
+        for i in range(0, len(remaining)):
+            if i == 0 or is_prime(i):
+                primeIndexed = primeIndexed + remaining[i]
+            else:
+                nonPrimeIndexed = nonPrimeIndexed + remaining[i]
+        output = output + primeIndexed
+        remaining = nonPrimeIndexed
+    return output
+
+def theucon_decrypt(text):
+    output = make_empty_list(len(text), '')
+    remaining = text
+    while len(remaining) > 0:
+        primes = [0] + primes_until(len(remaining))
+        currentOutput = make_empty_list(len(remaining), '')
+        current = remaining[0:len(primes)]
+        remaining = remaining[len(primes):]
+        for i in range(0, len(primes)):
+            currentOutput[primes[i]] = current[i]
+        if len(output) == 0:
+            output = currentOutput
+        else:
+            for i in range(0, len(output)):
+                if output[i] == '':
+                    output[i] = currentOutput[0]
+                    currentOutput = currentOutput[1:]
+    return str.join("", output)
+        
+def is_prime(n):
+    if n < 2 or n % 2 == 0 and n > 2: 
+        return False
+    return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
+
+
+def primes_until(n):
+    list = []
+    for x in range(1, n):
+        if is_prime(x):
+            list.append(x)
+    return list
+    
+def make_empty_list(n, sep=""):
+    list = []
+    for x in range(0, n):
+        list.append(sep)
+    return list
+
+def tr(text, inAlphabet, outAlphabet):
+	text = text.translate(str.maketrans(inAlphabet, outAlphabet))
+	return text.translate(str.maketrans(inAlphabet.upper(), outAlphabet.upper()))
+```
+

+ 67 - 0
content/posts/gist/2016-03-04/0edc8df5ed5916434da2.md

@@ -0,0 +1,67 @@
+---
+title: "pgp_public.asc"
+date: 2016-03-04T07:57:41Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/0edc8df5ed5916434da2)
+
+
+
+
+
+```public key
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+mQINBFbZPwEBEACsF8oNkQ/LSe4bS7bqjeTzfV+c3F+QFMDq5c/Z40YLlg4dILEz
+CxnfAGj5+F8Gxele/WKicf8YRhsMTXbarFuL5PKibiQPFAE2Jo06TbIRHqc1GW1C
+xDplF0sww7Kl/D1ly++xp7MQV4bJZz1U+mUxylPLNpM9Xd6WuSv0xN8dN4cALVnB
+vu/G/6+qrsJ/rLsPqdPSPttET5g5p7dRaXpKY8RlRFh+RBsZ0f4+7x9pCkvJrgEZ
+NcTzjn/r/r7Vk0GGrp8PxNrOTTXelljkMxK60KZvTSL5+ksdX0d1GJ8Nxm9Ah5LY
+XmMjv09XD/5YFG6RkE9itPIwfk7+aJ4T6hAgrJBAUa4kytkTgJwAUkarn77hfHad
+rFK7hlxRBmR5ntYNmr0QkoQ1buHSJ2szr72uXSfoobP3Onig0Z0G04fkTU0tFBVy
+30hfSTnJ6aGfuJrhG/7SsC59EIO5DMpbo/idfcuMYpzWr9ERCLx7mozLFhZY9s6d
+WzlsiE9tvxgJCLitNBpV3OgSMSpcu5gf+X/VyRuXWsc9qnFnzcwTbFost7mVMmNL
+9/QPGEVcnEV6adMavL1ds1DQzdzs8X93k0nuQewdcwnC9iG0FqVDEK4d3m45+ltr
+jfEHPVgjIWCVnKin/XZpJJxHNpoZmnbXus/k2BhJAOx71jmmagGo4cDUNQARAQAB
+tCtKYXNvbiBTY2h3YXJ6ZW5iZXJnZXIgPGphc29uQG1hc3RlcjVvMS5jb20+iQI4
+BBMBAgAiBQJW2T8BAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBetMMH
+7jF7rjZoD/0UZgMU7tAnLbLe9VBtgxVXC9RYcUt/Ijqinsooyc9lHlbpADZYmRZV
+wcGU4q0V433kYbZhx8Dhl3tpz5a3D3Dc74YUKdLrKSuEXwnftrV3GV3QAVfPeYEP
+xyGPW07y7b1YoeHUfYbz0l1lOy0GYLxcX6yMYih5sbgYHuF9clDxD47R6tQTMogg
+tYq/Utr3wZpJfs1viIAZtC+u1qQrwWDykR4TRatg7JqQv1lxIcTKlLuVliO04DMG
+unzSUwEfuLI4/5ssLbdf/hZhndL1NgD8OUXKN3kG71k6J6KVWlab9SoQ+Yupm1UC
+jfcLRPSxdMUNNWKv8zKFswdUwfBB4NhrEHDwzOb8DqIw3JBbNIkrIa0XqRYxnrEo
+JJGk8WTjE0Vq/XU+SDXhFkvBhBL7izRGQBXhiCwJYsVctVBf8uFCGUPCHheDA1p3
+M+3LZg8LkqXJA6Mx4Kjg8mLA0vLAOsY7uFHhSB41xw+dtBk7MhEy892085PK4F5x
++PIG4w5UUN598bzshOwEDbtX9Cfqkfm5BCFjufc1+4MyR5aHT1HGPdF6CSdPSJ95
+BxZVER8oCbv0Hf2EkajFgmHPc58hDBSgxxAzI7rPHEu2PEfBUcU+gapjRyipSQxw
+VtYZiS64s1bspMdz200w+UFrWHatBgCRt0xAUXIqWLLWVqwqYezuSbkCDQRW2T8B
+ARAAxtPH7/bHertfUlBQzIinu4boP0x3ShL9yqvxTiGRqpGHPYaSWBvHNjRkuxrn
+7xGKwlVFyV42MmSFuYyC+N9c31heq5E1aOF179YbLQyfhYgnt/CH6PduU8RUj4zf
+7yB6dsm7xf/oeHdNA4Yx8oZ4+lx5dla6OW4q5udWmnxLYFxu23o2E0hTblAs3md+
+aDj5rkWRQ3amTCeODIRgAvY3V6L7NAcDrN0hOhwhzvnppE66KvJA5gBVem7aac9K
+XT6pnEF8/YpcQsdqDH/guzREkFbkMy7YxfeD6biE6dRfpvzzFUQZ282VVrEWVgUK
+7Ask48SoS2tL+3XHyTL0n5wuc2iANEtxNpR48DcSGxVNHvOsF4wEDSeJbRVkDcIx
+O37KLSgY4iau2u/CqHB3EIxzVL4ou3z/Stuf8mImQmDhhd7Q7wa3z2dZHwX736FS
+7N0EQhLTHTYym1RtTJL5ZZVQqrann4OfOwpD8RY4TZU29NtUEcm4Wgm+ktG00Djw
+07sMb5EfBVga0IMzJSQTnpc1rSlDPf+8K7dZEMogH+ioePG7NaKIyRFk8Vns5uEh
++4Zh0s7pMzoJ4+asK2rTy0PaXAp5d2QU3clybnlECwfKpFJQYKYf0TPKrVP1HMRL
+lY9N1TrkKWFnWwQKbaJnM2d5wlazrd2ejJ0bA1xnFP5xqyMAEQEAAYkCHwQYAQIA
+CQUCVtk/AQIbDAAKCRBetMMH7jF7rg1WD/4/m4SHWToQF+AJp4QEQZbcfFDsXtft
+onqw6pjblMz42p4G21yMwMpJndLsNFdYlLadP4mCK1tp7I8uIXcmc9EbA3k+rLu8
+6LfAElNak4YKgXD7/J7AGeN/lMXP2R49xNcn+JEN4xhvpgYyU9Fr67oPEQUvEdHm
+9VQ3Ya2iIsPRJQ+PPTFYJMXA+igPG4LU5W79Dxn2hAF7+4EVjefa6kazCqU0+Oa6
+YaTzqER/q9zmf7NQPrQpa/kA1Zfn794SFWHVHEwYxxF0HuyE5vuCCpKTVWzko+/w
+qjdwJu5zB546jmbrHv6YmJxw/jS/K93r7vwp6eIjmjLgOxmDswQMU2+2oWlge7Nv
+7/O8KpnBKXrBF/AGPq7G5/LIvA1A7Ui7KFjfbBZ/jLJm86u308eFAGTH9AY15Twp
+9hCREdQyWGQhhBHKlOlSX6/UgDg2mssQKGClHQUW59Lcu5A3tr0huobNSVrV7xOq
+oncvcmlZ79Z+Nmu/QB9aZbbQiBAgEbLbFyv2ITrAy26jycP5PNFm9shR7c+/wzWZ
+NX1B1OC20LFsogWEAX9Ss7ZQy2bhgqP/++lQTt+ZKs17nY63teJ0AhlDcY9UC4sP
+LffkGN/JUU4Xotl7mALnzZsJaEPa61zCgOGPcqaWAjUVr0QxRhQ1c+0iL2o7i9lL
+wwROoQ9/0RsxTQ==
+=Atnx
+-----END PGP PUBLIC KEY BLOCK-----
+```
+

+ 175 - 0
content/posts/gist/2016-03-23/7e547987c77cef5aa9fa.md

@@ -0,0 +1,175 @@
+---
+title: "angular-websocket-rpc.js"
+date: 2016-03-23T22:13:29Z
+tags: ["gist"]
+draft: false
+---
+[gist link](https://gist.github.com/7e547987c77cef5aa9fa)
+
+
+angular websockets json-rpc2 service that uses [angular-websockets](https://github.com/AngularClass/angular-websocket). JSFiddle example: https://jsfiddle.net/master5o1/bxvauLcw/
+
+
+| Attachment | Type | Size |
+| - | - | - |
+| [angular-websocket-rpc.js](https://gist.githubusercontent.com/master5o1/7e547987c77cef5aa9fa/raw/11cbc817d106d55789f8a1b58d95723a7fff68f4/angular-websocket-rpc.js) | application/javascript | 3.1KiB |
+| [guid.js](https://gist.githubusercontent.com/master5o1/7e547987c77cef5aa9fa/raw/70f5de52653ab5f964c97143f20f67b6d6a86dc0/guid.js) | application/javascript | 548.0B |
+***
+
+### [angular-websocket-rpc.js](https://gist.githubusercontent.com/master5o1/7e547987c77cef5aa9fa/raw/11cbc817d106d55789f8a1b58d95723a7fff68f4/angular-websocket-rpc.js) -- application/javascript, 3.1KiB
+```javascript
+angular.module('ngWebsocketRpc', ['ngWebSocket', 'guid'])
+  .factory('$rpc', ['$websocket', '$q', 'guid', function($websocket, $q, guid) {
+    var seconds = 1000;
+    var history = {};
+    var methods = {};
+    var $ws;
+
+    var handlers = {
+      onOpen: angular.noop,
+      onClose: angular.noop,
+      onError: angular.noop
+    };
+
+    var rpcErrors = {
+      ParseError: RpcError(-32700, 'Parse error'),
+      InvalidRequest: RpcError(-32600, 'Invalid Request'),
+      MethodNotFound: RpcError(-32601, 'Method not found'),
+      InvalidParams: RpcError(-32602, 'Invalid params'),
+      InternalError: RpcError(-32603, 'Internal error'),
+      ServerError: RpcError(-32000, 'Server Error'),
+    };
+
+    function open(url) {
+      $ws = $websocket(url);
+      $ws.onMessage(messageRouter);
+    }
+
+    function close(force) {
+      return $ws.close(force);
+    }
+
+    function messageRouter(event, message) {
+      message = JSON.parse(event.data);
+      if (!!message.method) {
+        handlerMethodCall(event, message);
+        return;
+      }
+      handleCallResponse(event, message);
+    }
+
+    function handleCallResponse(event, message){
+      var call = history[message.id];
+      if (!!message.result) {
+        call.deferred.resolve(message.result, message, event);
+        return;
+      }
+      call.deferred.reject(message.error, message, event);
+    }
+
+    function handlerMethodCall(event, message) {
+      var response = {
+        "jsonrpc": "2.0",
+        "id": message.id
+      };
+      var params = message.params;
+      var fn = methods[message.method];
+
+      if (typeof fn === 'function'){
+        response = angular.extend(response, fn(params));
+      } else {
+        response = angular.extend(response, {
+          error: rpcErrors.MethodNotFound
+        });
+      }
+
+      var promise = $ws.send(JSON.stringify(response));
+    }
+
+    function callMethod(method, parameters) {
+      var id = guid();
+      var data = {
+        "jsonrpc": "2.0",
+        "method": method,
+        "params": parameters,
+        "id": id
+      };
+      var deferred = $q.defer();
+      var send = $ws.send(JSON.stringify(data));
+
+      history[id] = {
+        call: data,
+        messages: [],
+        send: send,
+        deferred: deferred
+      };
+      // cancel if somehow it doesn't make it to the websocket.
+      send.then(angular.noop, deferred.reject);
+      return deferred.promise;
+    }
+
+    function exposeMethod(method, handler){
+      methods[method] = handler;
+    }
+
+    function RpcError(code, message) {
+      return {
+        error: {
+          code: code,
+          message: message
+        }
+      };
+    }
+