Skip to content

Instantly share code, notes, and snippets.

@chrisquinnr
Created April 6, 2016 08:03
Show Gist options
  • Save chrisquinnr/ecd5f80a8e4a1eeafa961362b6d4c3f5 to your computer and use it in GitHub Desktop.
Save chrisquinnr/ecd5f80a8e4a1eeafa961362b6d4c3f5 to your computer and use it in GitHub Desktop.
Engine behind xkcd 1663
!function (t) {
function e(i) {
if (n[i])return n[i].exports;
var o = n[i] = {exports: {}, id: i, loaded: !1};
return t[i].call(o.exports, o, o.exports, e), o.loaded = !0, o.exports
}
var n = {};
return e.m = t, e.c = n, e.p = "", e(0)
}([function (t, e, n) {
n(55), n(53), n(52), n(51), n(54), n(50), n(109), n(103);
var i = n(45), o = document.getElementsByTagName("script"), r = o[o.length - 1];
window.garden = new i({
name: "garden",
el: document.getElementById("comic"),
width: 740,
height: 462,
title: r.getAttribute("data-title"),
endpoint: r.getAttribute("data-endpoint"),
imgPrefix: r.getAttribute("data-image-endpoint"),
spread: {reload: 60},
debug: "?debug" === location.search
}).run(), window.addEventListener("keydown", function (t) {
8 === t.which && t.preventDefault()
}, !1)
}, function (t, e, n) {
var i = n(40)("wks"), o = n(29), r = n(2).Symbol, s = "function" == typeof r;
t.exports = function (t) {
return i[t] || (i[t] = s && r[t] || (s ? r : o)("Symbol." + t))
}
}, function (t, e) {
var n = t.exports = "undefined" != typeof window && window.Math == Math ? window : "undefined" != typeof self && self.Math == Math ? self : Function("return this")();
"number" == typeof __g && (__g = n)
}, function (t, e) {
var n = t.exports = {version: "2.2.1"};
"number" == typeof __e && (__e = n)
}, function (t, e, n) {
var i = n(10);
t.exports = function (t) {
if (!i(t))throw TypeError(t + " is not an object!");
return t
}
}, function (t, e, n) {
var i = n(2), o = n(3), r = n(9), s = n(13), a = n(6), c = "prototype", u = function (t, e, n) {
var h, l, d, A, f = t & u.F, p = t & u.G, g = t & u.S, v = t & u.P, m = t & u.B, y = p ? i : g ? i[e] || (i[e] = {}) : (i[e] || {})[c], b = p ? o : o[e] || (o[e] = {}), w = b[c] || (b[c] = {});
p && (n = e);
for (h in n)l = !f && y && void 0 !== y[h], d = (l ? y : n)[h], A = m && l ? a(d, i) : v && "function" == typeof d ? a(Function.call, d) : d, y && s(y, h, d, t & u.U), b[h] != d && r(b, h, A), v && w[h] != d && (w[h] = d)
};
i.core = o, u.F = 1, u.G = 2, u.S = 4, u.P = 8, u.B = 16, u.W = 32, u.U = 64, u.R = 128, t.exports = u
}, function (t, e, n) {
var i = n(17);
t.exports = function (t, e, n) {
if (i(t), void 0 === e)return t;
switch (n) {
case 1:
return function (n) {
return t.call(e, n)
};
case 2:
return function (n, i) {
return t.call(e, n, i)
};
case 3:
return function (n, i, o) {
return t.call(e, n, i, o)
}
}
return function () {
return t.apply(e, arguments)
}
}
}, function (t, e, n) {
t.exports = !n(14)(function () {
return 7 != Object.defineProperty({}, "a", {
get: function () {
return 7
}
}).a
})
}, function (t, e) {
var n = {}.hasOwnProperty;
t.exports = function (t, e) {
return n.call(t, e)
}
}, function (t, e, n) {
var i = n(15), o = n(23);
t.exports = n(7) ? function (t, e, n) {
return i.f(t, e, o(1, n))
} : function (t, e, n) {
return t[e] = n, t
}
}, function (t, e) {
t.exports = function (t) {
return "object" == typeof t ? null !== t : "function" == typeof t
}
}, function (t, e) {
var n = {}.toString;
t.exports = function (t) {
return n.call(t).slice(8, -1)
}
}, function (t, e) {
t.exports = {}
}, function (t, e, n) {
var i = n(2), o = n(9), r = n(8), s = n(29)("src"), a = "toString", c = Function[a], u = ("" + c).split(a);
n(3).inspectSource = function (t) {
return c.call(t)
}, (t.exports = function (t, e, n, a) {
var c = "function" == typeof n;
c && (r(n, "name") || o(n, "name", e)), t[e] !== n && (c && (r(n, s) || o(n, s, t[e] ? "" + t[e] : u.join(String(e)))), t === i ? t[e] = n : a ? t[e] ? t[e] = n : o(t, e, n) : (delete t[e], o(t, e, n)))
})(Function.prototype, a, function () {
return "function" == typeof this && this[s] || c.call(this)
})
}, function (t, e) {
t.exports = function (t) {
try {
return !!t()
} catch (e) {
return !0
}
}
}, function (t, e, n) {
var i = n(4), o = n(35), r = n(43), s = Object.defineProperty;
e.f = n(7) ? Object.defineProperty : function (t, e, n) {
if (i(t), e = r(e, !0), i(n), o)try {
return s(t, e, n)
} catch (a) {
}
if ("get" in n || "set" in n)throw TypeError("Accessors not supported!");
return "value" in n && (t[e] = n.value), t
}
}, function (t, e, n) {
var i = n(22), o = n(20);
t.exports = function (t) {
return i(o(t))
}
}, function (t, e) {
t.exports = function (t) {
if ("function" != typeof t)throw TypeError(t + " is not a function!");
return t
}
}, function (t, e, n) {
var i = n(6), o = n(22), r = n(28), s = n(27), a = n(58);
t.exports = function (t, e) {
var n = 1 == t, c = 2 == t, u = 3 == t, h = 4 == t, l = 6 == t, d = 5 == t || l, A = e || a;
return function (e, a, f) {
for (var p, g, v = r(e), m = o(v), y = i(a, f, 3), b = s(m.length), w = 0, x = n ? A(e, b) : c ? A(e, 0) : void 0; b > w; w++)if ((d || w in m) && (p = m[w], g = y(p, w, v), t))if (n)x[w] = g; else if (g)switch (t) {
case 3:
return !0;
case 5:
return p;
case 6:
return w;
case 2:
x.push(p)
} else if (h)return !1;
return l ? -1 : u || h ? h : x
}
}
}, function (t, e, n) {
var i = n(11), o = n(1)("toStringTag"), r = "Arguments" == i(function () {
return arguments
}()), s = function (t, e) {
try {
return t[e]
} catch (n) {
}
};
t.exports = function (t) {
var e, n, a;
return void 0 === t ? "Undefined" : null === t ? "Null" : "string" == typeof(n = s(e = Object(t), o)) ? n : r ? i(e) : "Object" == (a = i(e)) && "function" == typeof e.callee ? "Arguments" : a
}
}, function (t, e) {
t.exports = function (t) {
if (void 0 == t)throw TypeError("Can't call method on " + t);
return t
}
}, function (t, e, n) {
var i = n(10), o = n(2).document, r = i(o) && i(o.createElement);
t.exports = function (t) {
return r ? o.createElement(t) : {}
}
}, function (t, e, n) {
var i = n(11);
t.exports = Object("z").propertyIsEnumerable(0) ? Object : function (t) {
return "String" == i(t) ? t.split("") : Object(t)
}
}, function (t, e) {
t.exports = function (t, e) {
return {enumerable: !(1 & t), configurable: !(2 & t), writable: !(4 & t), value: e}
}
}, function (t, e, n) {
var i = n(15).f, o = n(8), r = n(1)("toStringTag");
t.exports = function (t, e, n) {
t && !o(t = n ? t : t.prototype, r) && i(t, r, {configurable: !0, value: e})
}
}, function (t, e, n) {
var i = n(40)("keys"), o = n(29);
t.exports = function (t) {
return i[t] || (i[t] = o(t))
}
}, function (t, e) {
var n = Math.ceil, i = Math.floor;
t.exports = function (t) {
return isNaN(t = +t) ? 0 : (t > 0 ? i : n)(t)
}
}, function (t, e, n) {
var i = n(26), o = Math.min;
t.exports = function (t) {
return t > 0 ? o(i(t), 9007199254740991) : 0
}
}, function (t, e, n) {
var i = n(20);
t.exports = function (t) {
return Object(i(t))
}
}, function (t, e) {
var n = 0, i = Math.random();
t.exports = function (t) {
return "Symbol(".concat(void 0 === t ? "" : t, ")_", (++n + i).toString(36))
}
}, function (t, e) {
t.exports = function n(t, e) {
function i() {
for (var i = 0; i < t.children.length; i++)n(t.children[i], e)
}
t && e(t.node, i)
}
}, function (t, e) {
function n(t, e, n) {
return n > e ? e > t ? e : t > n ? n : t : n > t ? n : t > e ? e : t
}
t.exports = n
}, function (t, e, n) {
var i = n(1)("unscopables"), o = Array.prototype;
void 0 == o[i] && n(9)(o, i, {}), t.exports = function (t) {
o[i][t] = !0
}
}, function (t, e) {
t.exports = "constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")
}, function (t, e, n) {
t.exports = n(2).document && document.documentElement
}, function (t, e, n) {
t.exports = !n(7) && !n(14)(function () {
return 7 != Object.defineProperty(n(21)("div"), "a", {
get: function () {
return 7
}
}).a
})
}, function (t, e, n) {
"use strict";
var i = n(37), o = n(5), r = n(13), s = n(9), a = n(8), c = n(12), u = n(64), h = n(24), l = n(73), d = n(1)("iterator"), A = !([].keys && "next" in [].keys()), f = "@@iterator", p = "keys", g = "values", v = function () {
return this
};
t.exports = function (t, e, n, m, y, b, w) {
u(n, e, m);
var x, E, C, D = function (t) {
if (!A && t in O)return O[t];
switch (t) {
case p:
return function () {
return new n(this, t)
};
case g:
return function () {
return new n(this, t)
}
}
return function () {
return new n(this, t)
}
}, M = e + " Iterator", S = y == g, R = !1, O = t.prototype, k = O[d] || O[f] || y && O[y], N = k || D(y), T = y ? S ? D("entries") : N : void 0, L = "Array" == e ? O.entries || k : k;
if (L && (C = l(L.call(new t)), C !== Object.prototype && (h(C, M, !0), i || a(C, d) || s(C, d, v))), S && k && k.name !== g && (R = !0, N = function () {
return k.call(this)
}), i && !w || !A && !R && O[d] || s(O, d, N), c[e] = N, c[M] = v, y)if (x = {
values: S ? N : D(g),
keys: b ? N : D(p),
entries: T
}, w)for (E in x)E in O || r(O, E, x[E]); else o(o.P + o.F * (A || R), e, x);
return x
}
}, function (t, e) {
t.exports = !1
}, function (t, e, n) {
var i = n(74), o = n(33);
t.exports = Object.keys || function (t) {
return i(t, o)
}
}, function (t, e) {
e.f = {}.propertyIsEnumerable
}, function (t, e, n) {
var i = n(2), o = "__core-js_shared__", r = i[o] || (i[o] = {});
t.exports = function (t) {
return r[t] || (r[t] = {})
}
}, function (t, e, n) {
var i = n(14);
t.exports = function (t, e) {
return !!t && i(function () {
e ? t.call(null, function () {
}, 1) : t.call(null)
})
}
}, function (t, e, n) {
var i, o, r, s = n(6), a = n(60), c = n(34), u = n(21), h = n(2), l = h.process, d = h.setImmediate, A = h.clearImmediate, f = h.MessageChannel, p = 0, g = {}, v = "onreadystatechange", m = function () {
var t = +this;
if (g.hasOwnProperty(t)) {
var e = g[t];
delete g[t], e()
}
}, y = function (t) {
m.call(t.data)
};
d && A || (d = function (t) {
for (var e = [], n = 1; arguments.length > n;)e.push(arguments[n++]);
return g[++p] = function () {
a("function" == typeof t ? t : Function(t), e)
}, i(p), p
}, A = function (t) {
delete g[t]
}, "process" == n(11)(l) ? i = function (t) {
l.nextTick(s(m, t, 1))
} : f ? (o = new f, r = o.port2, o.port1.onmessage = y, i = s(r.postMessage, r, 1)) : h.addEventListener && "function" == typeof postMessage && !h.importScripts ? (i = function (t) {
h.postMessage(t + "", "*")
}, h.addEventListener("message", y, !1)) : i = v in u("script") ? function (t) {
c.appendChild(u("script"))[v] = function () {
c.removeChild(this), m.call(t)
}
} : function (t) {
setTimeout(s(m, t, 1), 0)
}), t.exports = {set: d, clear: A}
}, function (t, e, n) {
var i = n(10);
t.exports = function (t, e) {
if (!i(t))return t;
var n, o;
if (e && "function" == typeof(n = t.toString) && !i(o = n.call(t)))return o;
if ("function" == typeof(n = t.valueOf) && !i(o = n.call(t)))return o;
if (!e && "function" == typeof(n = t.toString) && !i(o = n.call(t)))return o;
throw TypeError("Can't convert object to primitive value")
}
}, function (t, e, n) {
function i(t) {
return t === p || t === g
}
function o(t) {
return y.test(t)
}
var r = n(97), s = 0, a = 1, c = 2, u = 3, h = 4, l = 5, d = 6, A = 7, f = 8, p = 9, g = 10, v = 11, m = 12;
t.exports = function (t, e) {
function n(t) {
return "function" == typeof t ? t : "string" == typeof t ? t : t && "object" == typeof t ? t : y("", t)
}
t = r(t), e || (e = {});
var y = e.concat || function (t, e) {
return String(t) + String(e)
};
return function (e) {
function r(t) {
var e = [];
b === A && (b = h);
for (var n = 0; n < t.length; n++) {
var o = t.charAt(n);
b === a && "<" === o ? (w.length && e.push([a, w]), w = "", b = c) : ">" !== o || i(b) ? b === a ? w += o : b === c && /\s/.test(o) ? (e.push([c, w]), w = "", b = h) : b === c ? w += o : b === h && /[\w-]/.test(o) ? (b = l, w = o) : b === h && /\s/.test(o) ? (w.length && e.push([l, w]), e.push([m])) : b === l && /\s/.test(o) ? (e.push([l, w]), w = "", b = d) : b === l && "=" === o ? (e.push([l, w], [v]), w = "", b = A) : b === l ? w += o : b !== d && b !== h || "=" !== o ? b !== d && b !== h || /\s/.test(o) ? b === A && '"' === o ? b = g : b === A && "'" === o ? b = p : b === g && '"' === o ? (e.push([f, w], [m]), w = "", b = h) : b === p && "'" === o ? (e.push([f, w], [m]), w = "", b = h) : b !== A || /\s/.test(o) ? b === f && /\s/.test(o) ? (e.push([m], [f, w]), w = "", b = h) : b !== f && b !== p && b !== g || (w += o) : (b = f, n--) : (e.push([m]), /[\w-]/.test(o) ? (w += o, b = l) : b = h) : (e.push([v]), b = A) : (b === c ? e.push([c, w]) : b === l ? e.push([l, w]) : b === f && w.length && e.push([f, w]), e.push([u]), w = "", b = a)
}
return b === a && w.length ? (e.push([a, w]), w = "") : b === f && w.length ? (e.push([f, w]), w = "") : b === g && w.length ? (e.push([f, w]), w = "") : b === p && w.length ? (e.push([f, w]), w = "") : b === l && (e.push([l, w]), w = ""), e
}
for (var b = a, w = "", x = arguments.length, E = [], C = 0; C < e.length; C++)if (x - 1 > C) {
var D = arguments[C + 1], M = r(e[C]), S = b;
S === g && (S = f), S === p && (S = f), S === A && (S = f), S === h && (S = l), M.push([s, S, D]), E.push.apply(E, M)
} else E.push.apply(E, r(e[C]));
for (var R = [null, {}, []], O = [[R, -1]], C = 0; C < E.length; C++) {
var k = O[O.length - 1][0], M = E[C], N = M[0];
if (N === c && /^\//.test(M[1])) {
var T = O[O.length - 1][1];
O.length > 1 && (O.pop(), O[O.length - 1][0][2][T] = t(k[0], k[1], k[2].length ? k[2] : void 0))
} else if (N === c) {
var L = [M[1], {}, []];
k[2].push(L), O.push([L, k[2].length - 1])
} else if (N === l || N === s && M[1] === l) {
for (var I, U = ""; C < E.length; C++)if (E[C][0] === l)U = y(U, E[C][1]); else {
if (E[C][0] !== s || E[C][1] !== l)break;
if ("object" != typeof E[C][2] || U)U = y(U, E[C][2]); else for (I in E[C][2])E[C][2].hasOwnProperty(I) && !k[1][I] && (k[1][I] = E[C][2][I])
}
E[C][0] === v && C++;
for (var B = C; C < E.length; C++)if (E[C][0] === f || E[C][0] === l)k[1][U] ? k[1][U] = y(k[1][U], E[C][1]) : k[1][U] = n(E[C][1]); else {
if (E[C][0] !== s || E[C][1] !== f && E[C][1] !== l) {
!U.length || k[1][U] || C !== B || E[C][0] !== u && E[C][0] !== m || (k[1][U] = U.toLowerCase());
break
}
k[1][U] ? k[1][U] = y(k[1][U], E[C][2]) : k[1][U] = n(E[C][2])
}
} else if (N === l)k[1][M[1]] = !0; else if (N === s && M[1] === l)k[1][M[2]] = !0; else if (N === u) {
if (o(k[0]) && O.length) {
var T = O[O.length - 1][1];
O.pop(), O[O.length - 1][0][2][T] = t(k[0], k[1], k[2].length ? k[2] : void 0)
}
} else if (N === s && M[1] === a)void 0 === M[2] || null === M[2] ? M[2] = "" : M[2] || (M[2] = y("", M[2])), Array.isArray(M[2][0]) ? k[2].push.apply(k[2], M[2]) : k[2].push(M[2]); else if (N === a)k[2].push(M[1]); else if (N !== v && N !== m)throw new Error("unhandled: " + N)
}
if (R[2].length > 1 && /^\s*$/.test(R[2][0]) && R[2].shift(), R[2].length > 2 || 2 === R[2].length && /\S/.test(R[2][1]))throw new Error("multiple root elements must be wrapped in an enclosing tag");
return Array.isArray(R[2][0]) && "string" == typeof R[2][0][0] && Array.isArray(R[2][0][2]) && (R[2][0] = t(R[2][0][0], R[2][0][1], R[2][0][2])), R[2][0]
}
};
var y = (Object.prototype.hasOwnProperty, RegExp("^(" + ["area", "base", "basefont", "bgsound", "br", "col", "command", "embed", "frame", "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source", "track", "wbr", "animate", "animateTransform", "circle", "cursor", "desc", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "font-face-format", "font-face-name", "font-face-uri", "glyph", "glyphRef", "hkern", "image", "line", "missing-glyph", "mpath", "path", "polygon", "polyline", "rect", "set", "stop", "tref", "use", "view", "vkern"].join("|") + ")(?:[.#][a-zA-Z0-9-ï¿¿_:-]+)*$"))
}, function (t, e, n) {
n(99);
var i = n(47), o = n(30), r = n(48), s = function (t) {
this.opts = t, this.data = null, this.gardenId = null, this.gardenKey = null, this.dirtyLights = {}, this.inFlightRequests = 0
};
s.prototype = {
record: function (t, e) {
(new Image).src = "http://xkcd.com/events.gif?re=" + t + "&ev=" + e
}, log: function () {
this.opts.debug && console.log.apply(console, arguments)
}, _url: function () {
var t = this.opts.endpoint + "run";
return this.gardenId && (t += "/" + this.gardenId), t
}, _connect: function () {
var t = this._url();
this.source = new EventSource(t), this.log("connecting to event source:", t), this.source.addEventListener("open", this.onConnect.bind(this), !1), this.source.addEventListener("error", this.onConnectionError.bind(this), !1), this.source.addEventListener("linden-key", this.onLindenKey.bind(this), !1), this.source.addEventListener("linden", this.onLindenUpdate.bind(this), !1), this.source.addEventListener("reload", this.onReload.bind(this), !1)
}, run: function () {
try {
this.opts.endpoint && (location.hash && (this.gardenId = location.hash.substr(1), this.gardenKey = localStorage["key-" + this.gardenId]), this._connect()), this.linden = new i({
el: this.opts.el,
width: this.opts.width,
height: this.opts.height,
title: this.opts.title,
urlPrefix: this.opts.imgPrefix,
loading: !0,
readOnly: !this.gardenKey,
debug: this.opts.debug,
onLightChanging: this.handleLightChanging.bind(this),
onSetLight: this.handleSetLight.bind(this),
onRemoveLight: this.handleRemoveLight.bind(this),
onPruneNode: this.handlePruneNode.bind(this)
}), this.opts.data && this.linden.update(this.opts.data), r(this.linden)
} catch (t) {
throw this.record(this.opts.name, "js_error"), t
}
return this
}, onConnect: function () {
this.record(this.opts.name, "connect_start"), this.linden.renderUI()
}, onConnectionError: function (t) {
this.log("connection error", t), this.record(this.opts.name, "connect_error"), this.linden.opts.loading = !0, this.linden.resetTree(), this.linden.renderUI(), this.source.url !== this._url() && (this.source.close(), this._connect())
}, onLindenKey: function (t) {
this.log("linden key from EventSource", t);
var e = JSON.parse(t.data);
this.gardenId = location.hash = e.garden, this.gardenKey = localStorage["key-" + e.garden] = e.key, this.linden.opts.readOnly = !1, this.linden.renderUI()
}, _acceptUpdate: function () {
if (this.inFlightRequests > 0)return this.log("rejecting update, inflight:", this.inFlightRequests), !1;
for (var t in this.dirtyLights)if (this.dirtyLights.hasOwnProperty(t) && this.dirtyLights[t] === !0)return this.log("rejecting update, dirty light:", t), !1;
return !0
}, _update: function (t) {
this._acceptUpdate() && (this.data = t, this.linden.update(t))
}, onLindenUpdate: function (t) {
this.log("linden from EventSource", t), this._update(JSON.parse(t.data))
}, onReload: function () {
var t = Math.round(Math.random() * this.opts.spread.reload);
this.log("reloading in", t + 5, "seconds"), setTimeout(function () {
this.record(this.opts.name, "reloading"), setTimeout(function () {
location.reload()
}, 5e3)
}, 1e3 * t)
}, request: function (t, e) {
var n = function () {
this.inFlightRequests--, this.log("inflight--", this.inFlightRequests)
}.bind(this), i = {method: "POST"};
Object.assign(i, e), i.body = JSON.stringify(e.body), this.log("request", t, i);
var o = fetch(t, i);
return o.then(n, n), this.inFlightRequests++, this.log("inflight++", this.inFlightRequests), o
}, handleLightChanging: function (t) {
this.dirtyLights[t] = !0
}, handleSetLight: function (t, e) {
this.log("set light:", t, e), this.request(this.opts.endpoint + "edit", {
body: Object.assign({
tag: "EditLight",
garden: this.data.garden,
editKey: this.gardenKey,
light: t
}, e)
}).then(function (t) {
return t.json()
}).then(function (t) {
this._update(Object.assign({}, this.data, {lights: t}))
}.bind(this)), delete this.dirtyLights[t]
}, _sendRemove: function (t) {
this.request(this.opts.endpoint + "edit", {
body: {
tag: "Del",
garden: this.data.garden,
editKey: this.gardenKey,
node: t
}
})
}, handleRemoveLight: function (t) {
this.log("remove light:", t);
var e = this.data.lights.filter(function (e) {
return e.id !== t
});
this._update(Object.assign({}, this.data, {lights: e})), this._sendRemove(t)
}, handlePruneNode: function (t) {
this.log("prune node:", t);
var e = {children: []}, n = e;
o(this.data.tree, function (e, i) {
var o = n;
n = {node: e, children: []}, e.id !== t && o.children.push(n), i(), n = o
}), this._update(Object.assign({}, this.data, {tree: e.children[0]})), this._sendRemove(t)
}
}, t.exports = s
}, function (t, e) {
function n() {
this.imgs = {}, this.callbacks = {}
}
n.prototype = {
get: function (t, e) {
var n = this.imgs[t];
void 0 === n ? (this.imgs[t] = !0, this.callbacks[t] = [e], n = new Image, n.onload = this._onDone.bind(this, t, n, n), n.onerror = this._onDone.bind(this, t, n, !1), n.crossOrigin = "anonymous", n.src = t) : n === !0 ? this.callbacks[t].push(e) : e && e(t, n)
}, _onDone: function (t, e, n) {
this.imgs[t] = n;
for (var i = 0; i < this.callbacks[t].length; i++) {
var o = this.callbacks[t][i];
o && o(t, n)
}
delete this.callbacks[t]
}, getAll: function (t, e) {
function n(t, n) {
o[t] = n, i--, 0 === i && e(o)
}
if (!t.length)return void e([]);
for (var i = t.length, o = {}, r = 0; r < t.length; r++)this.get(t[r], n)
}
}, t.exports = n
}, function (t, e, n) {
function i(t, e) {
return Object.freeze(Object.defineProperties(t, {raw: {value: Object.freeze(e)}}))
}
function o(t) {
return Math.sin(t * O)
}
function r(t) {
return Math.cos(t * O)
}
function s(t, e) {
return (t % e + e) % e
}
function a(t, e, n, i, a, c, u) {
var h, l, d, A, f = s(t, 360);
90 >= f ? (h = i, l = u, d = c, A = a) : 180 >= f ? (h = c, l = a, d = i, A = u) : 270 >= f ? (h = c, l = u, d = i, A = a) : (h = i, l = u, d = c, A = a), h -= e, l -= n, d -= e, A -= n;
var p = {
x1: e + h * r(f) - l * o(f),
y1: n + h * o(f) + l * r(f),
x2: e + d * r(f) - A * o(f),
y2: n + d * o(f) + A * r(f)
};
if (p.x2 < p.x1) {
var g = p.x2;
p.x2 = p.x1, p.x1 = g
}
if (p.y2 < p.y1) {
var v = p.y2;
p.y2 = p.y1, p.y1 = v
}
return p
}
function c(t, e, n, i) {
return "rgba(" + 100 * t + "%, " + 100 * e + "%, " + 100 * n + "%, " + i + ")"
}
function u(t) {
return .32 > t ? [1, .5 + .5 * t / .32, .5] : .64 > t ? [1, 1, .5 + .5 * (t - .32) / .32] : [.75 + .25 * (1 - t) / .36, .75 + .25 * (1 - t) / .36, 1]
}
function h(t, e, n) {
var i = {x2: 0, y2: 0, scale: 1, angle: 0};
M(t, function (t, s) {
var a = e[t.id], c = t.cache;
c || (c = t.cache = {}), c.scale = i.scale * t.scale, c.angle = i.angle + a.angle;
var u = t.attach[0] - t.root[0], h = t.attach[1] - t.root[1];
c.x1 = i.x2, c.y1 = i.y2, c.x2 = c.x1 + c.scale * (u * r(c.angle) + h * o(c.angle)), c.y2 = c.y1 + c.scale * (-u * o(c.angle) + h * r(c.angle));
var l = i;
i = c, n(t, s), i = l
})
}
function l(t) {
var e = t.cache, n = e.x1 - t.root[0], i = e.y1 - t.root[1];
return a(-e.angle, n + t.root[0], i + t.root[1], n, i, n + e.scale * e.width, i + e.scale * e.height)
}
function d(t, e, n, i) {
function s(t, n) {
return e[t.id][n]
}
var a = i.width, d = i.height, A = i.debug, f = i.urlPrefix, p = "", g = i.imgCache, v = i.el.getContext("2d"), m = Number(i.el.getAttribute("data-density"));
m > 1 && (p = "2x-");
var y = [];
M(t, function (t, e) {
t.img && y.push(f + p + t.img), e()
}), g.getAll(y, function (g) {
function y(t) {
for (var e = 0; e < n.length; e++) {
var i = n[e];
x.save(), x.beginPath(), x.moveTo(i.pos[0], i.pos[1]);
var s = i.pos[0] + E * r(i.pointAngle - i.beamAngle / 2), a = i.pos[1] + E * o(i.pointAngle - i.beamAngle / 2);
x.lineTo(s, a), x.arc(i.pos[0], i.pos[1], E, (i.pointAngle - i.beamAngle / 2) * O, (i.pointAngle + i.beamAngle / 2) * O), x.lineTo(i.pos[0], i.pos[1]), t(i), x.restore()
}
}
v.save(), v.scale(m, -m), v.translate(0, -d), v.clearRect(0, 0, a, d);
var b;
h(t, e, function (t, n) {
var i = t.cache;
if (v.save(), v.rotate(s(t, "angle") * -O), v.scale(t.scale, t.scale), e._selected && (t.id === e._selected.id && (v.globalAlpha = .5), t.id === e._selected.circled && (b = t)), t.img) {
var o = f + p + t.img, r = g[o];
r && (v.save(), v.scale(1 / m, -1 / m), v.translate(0, -r.height), v.drawImage(r, -t.root[0] * m, t.root[1] * m), v.restore(), i.width = r.width / m, i.height = r.height / m)
}
v.translate(t.attach[0] - t.root[0], t.attach[1] - t.root[1]), n(), v.restore()
});
var w = document.createElement("canvas");
w.width = i.el.width, w.height = i.el.height;
var x = w.getContext("2d");
x.scale(m, m);
var E = Math.sqrt(Math.pow(a, 2) + Math.pow(d, 2));
if (y(function (t) {
var e = x.createRadialGradient(t.pos[0], t.pos[1], 0, t.pos[0], t.pos[1], E), n = u(t.temp);
e.addColorStop(0, c(n[0], n[1], n[2], 1)), e.addColorStop(1, c(n[0], n[1], n[2], 0)), x.fillStyle = e, x.globalCompositeOperation = "lighten", x.fill()
}), y(function (t) {
x.globalAlpha = .4, x.strokeStyle = "black", x.stroke()
}), v.save(), v.scale(1 / m, 1 / m), v.globalCompositeOperation = "source-atop", v.globalAlpha = .65, v.drawImage(w, 0, 0), v.globalAlpha = .25, v.globalCompositeOperation = "destination-over", v.drawImage(w, 0, 0), v.restore(), b) {
b.cache;
v.save(), v.beginPath();
var C = l(b), D = C.x1 + (C.x2 - C.x1) / 2, S = C.y1 + (C.y2 - C.y1) / 2, k = Math.sqrt(Math.pow(C.x2 - C.x1, 2) + Math.pow(C.y2 - C.y1, 2));
v.arc(D, S, k / 2 + 6, 0, R), v.strokeStyle = "red", v.lineWidth = 2, v.globalAlpha = .9, v.stroke(), v.restore()
}
A && M(t, function (t, e) {
v.save();
var n = t.cache;
if (v.beginPath(), v.globalAlpha = .75, v.moveTo(n.x1, n.y1), v.lineTo(n.x2, n.y2), v.strokeStyle = t.proxyFor ? "lightgreen" : "magenta", v.lineWidth = 1, v.stroke(), e(), v.restore(), n.width) {
var i = l(t);
v.beginPath(), v.rect(i.x1, i.y1, i.x2 - i.x1, i.y2 - i.y1), v.strokeStyle = "red", v.stroke()
}
}), v.restore(), i.onFinish && i.onFinish()
})
}
function A(t) {
this.el = t.el, this.opts = t, this.imgCache = new D, this._queued = !1, this._rendering = !1, this._afterNextRender = null, this.resetTree(), this.renderUI()
}
var f = i(["<div\n className=", "\n style=", "\n onMouseDown=", "\n />"], ["<div\n className=", "\n style=", "\n onMouseDown=", "\n />"]), p = i(["\n <div>\n <div style=", '>\n <Handle\n className="rotate"\n disabled=', "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n <div style=", '>\n <Handle\n className="color"\n style=', "\n disabled=", "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n </div>\n "], ["\n <div>\n <div style=", '>\n <Handle\n className="rotate"\n disabled=', "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n <div style=", '>\n <Handle\n className="color"\n style=', "\n disabled=", "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n </div>\n "]), g = i(["\n <div\n className=", "\n style=", "\n data-light-id=", '\n >\n <div>\n <Handle\n className="position"\n disabled=', "\n onGrab=", "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n ", "\n </div>\n "], ["\n <div\n className=", "\n style=", "\n data-light-id=", '\n >\n <div>\n <Handle\n className="position"\n disabled=', "\n onGrab=", "\n onDrag=", "\n onRelease=", "\n ></Handle>\n </div>\n ", "\n </div>\n "]), v = i(['\n <div className="tools">\n <button\n className="add-light"\n disabled=', '\n title="Create new light"\n onClick=', '\n >+</button>\n <button\n className="remove"\n disabled=', '\n title="Remove selected (delete key)"\n onClick=', "\n >x</button>\n </div>\n "], ['\n <div className="tools">\n <button\n className="add-light"\n disabled=', '\n title="Create new light"\n onClick=', '\n >+</button>\n <button\n className="remove"\n disabled=', '\n title="Remove selected (delete key)"\n onClick=', "\n >x</button>\n </div>\n "]), m = i(["\n <div\n onMouseDown=", "\n onKeyDown=", "\n style=", "\n className=", "\n title=", '\n tabIndex="1"\n >\n ', "\n ", '\n <div className="content">\n <canvas\n data-density=', "\n width=", "\n height=", "\n style=", "\n onMouseDown=", "\n ></canvas>\n ", "\n </div>\n </div>\n "], ["\n <div\n onMouseDown=", "\n onKeyDown=", "\n style=", "\n className=", "\n title=", '\n tabIndex="1"\n >\n ', "\n ", '\n <div className="content">\n <canvas\n data-density=', "\n width=", "\n height=", "\n style=", "\n onMouseDown=", "\n ></canvas>\n ", "\n </div>\n </div>\n "]), y = i(['<div><div className="spinner"></div><div className="spinner-text">loading</div>'], ['<div><div className="spinner"></div><div className="spinner-text">loading</div>']), b = i(["<Light\n id=", "\n disabled=", "\n selected=", "\n x=", "\n y=", "\n temp=", "\n pointAngle=", "\n beamAngle=", "\n onInteract=", "\n onMove=", "\n onRotate=", "\n onChangeColor=", "\n onSave=", "\n />"], ["<Light\n id=", "\n disabled=", "\n selected=", "\n x=", "\n y=", "\n temp=", "\n pointAngle=", "\n beamAngle=", "\n onInteract=", "\n onMove=", "\n onRotate=", "\n onChangeColor=", "\n onSave=", "\n />"]), w = n(94), x = n(49), E = n(31), C = n(100), D = n(46), M = n(30), S = Math.PI / 2, R = 2 * Math.PI, O = S / 90;
w.component("Handle", {
componentDidMount: function () {
this._handleDragMove = this.handleDragMove.bind(this), this._handleDragUp = this.handleDragUp.bind(this), this.getDOMNode().firstChild.addEventListener("touchstart", this.handleDragDown.bind(this))
}, _stopListening: function () {
window.removeEventListener("mousemove", this._handleDragMove, !1), window.removeEventListener("mouseup", this._handleDragUp, !1), window.removeEventListener("touchmove", this._handleDragMove, !1), window.removeEventListener("touchend", this._handleDragUp, !1)
}, componentWillUnmount: function () {
this._stopListening()
}, _normalizeEvent: function (t) {
t.touches && t.touches[0] && (t.clientX = t.touches[0].clientX, t.clientY = t.touches[0].clientY)
}, handleDragDown: function (t) {
this.props.disabled || (document.documentElement.style.cursor = "move", window.addEventListener("mousemove", this._handleDragMove, !1), window.addEventListener("mouseup", this._handleDragUp, !1), window.addEventListener("touchmove", this._handleDragMove, !1), window.addEventListener("touchend", this._handleDragUp, !1), this.props.onGrab && (this._normalizeEvent(t), this.props.onGrab(t)), t.preventDefault())
}, handleDragUp: function (t) {
document.documentElement.style.cursor = null, this._stopListening(), this.props.onRelease && (this._normalizeEvent(t), this.props.onRelease(t)), t.preventDefault()
}, handleDragMove: function (t) {
this.props.onDrag && (this._normalizeEvent(t), this.props.onDrag(t)), t.preventDefault()
}, render: function () {
return w(f, x("handle", this.props.className), this.props.style || "", this.handleDragDown.bind(this))
}
}), w.component("Light", {
handleRotate: function (t) {
var e = this.getDOMNode().firstChild.getBoundingClientRect(), n = t.clientX - e.left, i = t.clientY - e.top, o = s(-Math.atan2(i, n) / O, 360), r = Math.sqrt(Math.pow(n, 2) + Math.pow(i, 2));
this.props.onRotate(o, E(0, 95 - 3 * (r - 42), 95))
}, handleRotateColor: function (t) {
var e = this.getDOMNode().firstChild.getBoundingClientRect(), n = t.clientX - e.left, i = t.clientY - e.top, o = E(90, s(-Math.atan2(i, n) / O - this.props.pointAngle, 360), 270) - 90;
this.props.onChangeColor(o / 180)
}, render: function () {
var t = C({
left: this.props.x + "px",
top: this.props.y + "px",
transform: "rotate(" + (-this.props.pointAngle - 90) + "deg)"
}), e = "";
if (this.props.selected) {
var n = 42 + E(0, (95 - this.props.beamAngle) / 3, 95), i = C({
position: "absolute",
top: n + "px"
}), s = 180 * this.props.temp, a = u(this.props.temp), h = C({
position: "absolute",
left: 39 * r(-s) + "px",
top: 39 * o(-s) + "px"
}), l = C({backgroundColor: c(a[0], a[1], a[2], 1)});
e = w(p, i, this.props.disabled, this.handleRotate.bind(this), this.props.onSave, h, l, this.props.disabled, this.handleRotateColor.bind(this), this.props.onSave)
}
return w(g, x("light", this.props.selected && "selected"), t, this.props.id, this.props.disabled, this.props.onInteract, this.props.onMove, this.props.onSave, e)
}
}), A.prototype = {
STIFFNESS: .25, FRICTION: .1, MAX_LIGHTS: 3, FPS: 15, resetTree: function () {
this.l = null, this.lights = [], this.state = {_selected: null}
}, renderUI: function () {
var t = "";
this.opts.readOnly || this.opts.loading || (t = w(v, this.lights.length === this.MAX_LIGHTS, this.handleCreateLight.bind(this), !this.state._selected, this.handleRemoveSelection.bind(this)));
var e = C({
width: this.opts.width + "px",
height: this.opts.height + "px"
}), n = window.devicePixelRatio > 1 ? 2 : 1, i = C({
transformOrigin: "0 0",
transform: "scale(" + 1 / n + ", " + 1 / n + ")"
}), o = x("frame", this.opts.loading && "loading");
w.render(w(m, this.handleMouseDown.bind(this), this.handleKeyDown.bind(this), e, o, this.opts.title, t, this.opts.loading ? w(y) : "", n, this.opts.width * n, this.opts.height * n, i, this.handleCanvasMouseDown.bind(this), this.lights.map(function (t) {
var e = Boolean(this.state._selected && "light" === this.state._selected.kind && this.state._selected.id === t.id);
return w(b, t.id, this.opts.readOnly, e, t.pos[0], this.opts.height - t.pos[1], t.temp, t.pointAngle, t.beamAngle, this.handleLightInteract.bind(this, t.id), this.handleLightMove.bind(this, t.id), this.handleLightRotate.bind(this, t.id), this.handleLightChangeColor.bind(this, t.id), this.saveLight.bind(this, t.id))
}.bind(this))), this.el)
}, update: function (t) {
this.l = t.tree;
var e = 0, n = {};
M(this.l, function (t, i) {
e++;
var o = t.img || "proxy";
n[o] = n[o] || {count: 0}, n[o].count++;
var r = this.state[t.id];
r || (r = this.state[t.id] = {angle: t.angle, av: 0}), r.node = t, i()
}.bind(this)), this.lights = t.lights || [];
var i = Date.now();
this._afterNextRender = function () {
if (this.opts.loading = !1, this.renderUI(), this._afterNextRender = null, this.opts.debug) {
var o = Date.now() - i;
console.debug("updated. rendered", e, "nodes in", o, "ms", "| supply:", t.supply), console.table(n)
}
}.bind(this), this.renderCanvas()
}, addWind: function (t, e, n) {
M(this.l, function (i, r) {
if (!i.rigid && i.cache) {
var s = this.state[i.id], a = o(t - i.cache.angle), c = 1 - n + Math.random() * n;
s.av += i.waviness * c * (1 / Math.sqrt(i.cache.scale)) * a * e
}
r()
}.bind(this)), this.queueStep()
}, queueStep: function () {
this._queued || (setTimeout(this.step.bind(this), 1e3 / this.FPS), this._queued = Date.now())
}, step: function () {
this.opts.beforeStep && this.opts.beforeStep(), M(this.l, function (t, e) {
var n = this.state[t.id];
n.av += (1 - t.waviness) * t.scale * this.STIFFNESS * (t.angle - n.angle), n.av += -n.av * this.FRICTION, n.angle += n.av, e()
}.bind(this)), this.renderCanvas(), this._queued = !1, this.queueStep()
}, renderCanvas: function () {
!this._rendering && this.l && (this._rendering = !0, d(this.l, this.state, this.lights, {
width: this.opts.width,
height: this.opts.height,
el: this.el.querySelector("canvas"),
urlPrefix: this.opts.urlPrefix,
imgCache: this.imgCache,
debug: this.opts.debug,
onFinish: function () {
this._afterNextRender && this._afterNextRender(), this._rendering = !1
}.bind(this)
}))
}, handleMouseDown: function () {
this.el.querySelector(".frame").focus()
}, _deselect: function () {
this.state._selected = null, this.renderCanvas(), this.renderUI()
}, handleCanvasMouseDown: function (t) {
if (!this.opts.readOnly) {
this._deselect();
var e = this.el.getBoundingClientRect(), n = t.clientX - e.left, i = this.opts.height - (t.clientY - e.top), o = null, r = Number.MAX_VALUE;
if (M(this.l, function (t, e) {
var s = t.cache;
if (s && s.width && !t.immutable) {
var a = l(t);
if (a.x1 <= n && a.x2 >= n && a.y1 <= i && a.y2 >= i) {
var c = (a.x2 - a.x1) * (a.y2 - a.y1);
r > c && (o = t, r = c)
}
}
e()
}), o) {
var s = o.proxyFor || o.id;
this.state._selected = {kind: "node", id: s, circled: o.id}
}
this.renderCanvas(), this.renderUI()
}
}, handleKeyDown: function (t) {
46 !== t.which && 8 !== t.which || (this.handleRemoveSelection(), t.preventDefault())
}, handleLightInteract: function (t) {
this.opts.readOnly || (this.state._selected = {kind: "light", id: t}, this.renderCanvas(), this.renderUI())
}, handleLightMove: function (t, e) {
var n = this.el.getBoundingClientRect(), i = E(0, e.clientX - n.left, this.opts.width), o = E(0, this.opts.height - (e.clientY - n.top), this.opts.height);
this.setLight(t, {pos: [i, o]})
}, handleLightRotate: function (t, e, n) {
this.setLight(t, {pointAngle: e, beamAngle: n})
}, handleLightChangeColor: function (t, e) {
this.setLight(t, {temp: e})
}, setLight: function (t, e) {
this.opts.onLightChanging(t);
var n = this.lights.findIndex(function (e) {
return e.id === t
});
-1 !== n && (Object.assign(this.lights[n], e), this.renderCanvas(), this.renderUI())
}, saveLight: function (t) {
var e = this.lights.findIndex(function (e) {
return e.id === t
});
-1 !== e && this.opts.onSetLight(t, this.lights[e])
}, handleCreateLight: function () {
var t = this.opts.width * Math.random(), e = (this.opts.height + this.opts.height * Math.random()) / 2, n = this.opts.width / 2, i = 0;
this.opts.onSetLight(null, {
pos: [t, e],
pointAngle: Math.atan2(i - e, n - t) / O,
beamAngle: 45 + 45 * Math.random(),
temp: .5
})
}, handleRemoveSelection: function () {
this.state._selected && ("node" === this.state._selected.kind ? this.opts.onPruneNode(this.state._selected.id) : "light" === this.state._selected.kind && this.opts.onRemoveLight(this.state._selected.id), this._deselect())
}
}, t.exports = A
}, function (t, e, n) {
var i = n(31);
t.exports = function (t) {
function e() {
var e = 2 * (Math.random() - .5);
Math.random() > .9 && (n += Math.random() - .5), o = i(60, o + 2 * (Math.random() - .5), 120), n *= .995, t.addWind(o, .025 * e + .25 * n, .5)
}
var n = 0, o = 90;
t.opts.beforeStep = e, e()
}
}, function (t, e, n) {
var i, o;
/*!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment