diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json
index c161ab9e..9bc51314 100644
--- a/.obsidian/community-plugins.json
+++ b/.obsidian/community-plugins.json
@@ -22,5 +22,7 @@
"obsidian-itinerary",
"customjs",
"obsidian42-brat",
- "code-block-copy"
+ "code-block-copy",
+ "obsidian-crypto-lookup",
+ "obsidian-lineup-builder"
]
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-crypto-lookup/main.js b/.obsidian/plugins/obsidian-crypto-lookup/main.js
new file mode 100644
index 00000000..db3a9b13
--- /dev/null
+++ b/.obsidian/plugins/obsidian-crypto-lookup/main.js
@@ -0,0 +1,895 @@
+/*
+THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
+if you want to view the source visit the plugins github repository
+*/
+
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
+var __commonJS = (cb, mod) => function __require() {
+ return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
+};
+var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __reExport = (target, module2, desc) => {
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
+ for (let key of __getOwnPropNames(module2))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
+ }
+ return target;
+};
+var __toModule = (module2) => {
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
+};
+var __async = (__this, __arguments, generator) => {
+ return new Promise((resolve, reject) => {
+ var fulfilled = (value) => {
+ try {
+ step(generator.next(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var rejected = (value) => {
+ try {
+ step(generator.throw(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+ step((generator = generator.apply(__this, __arguments)).next());
+ });
+};
+
+// node_modules/numeral/numeral.js
+var require_numeral = __commonJS({
+ "node_modules/numeral/numeral.js"(exports, module2) {
+ (function(global, factory) {
+ if (typeof define === "function" && define.amd) {
+ define(factory);
+ } else if (typeof module2 === "object" && module2.exports) {
+ module2.exports = factory();
+ } else {
+ global.numeral = factory();
+ }
+ })(exports, function() {
+ var numeral2, _, VERSION = "2.0.6", formats = {}, locales = {}, defaults = {
+ currentLocale: "en",
+ zeroFormat: null,
+ nullFormat: null,
+ defaultFormat: "0,0",
+ scalePercentBy100: true
+ }, options = {
+ currentLocale: defaults.currentLocale,
+ zeroFormat: defaults.zeroFormat,
+ nullFormat: defaults.nullFormat,
+ defaultFormat: defaults.defaultFormat,
+ scalePercentBy100: defaults.scalePercentBy100
+ };
+ function Numeral(input, number) {
+ this._input = input;
+ this._value = number;
+ }
+ numeral2 = function(input) {
+ var value, kind, unformatFunction, regexp;
+ if (numeral2.isNumeral(input)) {
+ value = input.value();
+ } else if (input === 0 || typeof input === "undefined") {
+ value = 0;
+ } else if (input === null || _.isNaN(input)) {
+ value = null;
+ } else if (typeof input === "string") {
+ if (options.zeroFormat && input === options.zeroFormat) {
+ value = 0;
+ } else if (options.nullFormat && input === options.nullFormat || !input.replace(/[^0-9]+/g, "").length) {
+ value = null;
+ } else {
+ for (kind in formats) {
+ regexp = typeof formats[kind].regexps.unformat === "function" ? formats[kind].regexps.unformat() : formats[kind].regexps.unformat;
+ if (regexp && input.match(regexp)) {
+ unformatFunction = formats[kind].unformat;
+ break;
+ }
+ }
+ unformatFunction = unformatFunction || numeral2._.stringToNumber;
+ value = unformatFunction(input);
+ }
+ } else {
+ value = Number(input) || null;
+ }
+ return new Numeral(input, value);
+ };
+ numeral2.version = VERSION;
+ numeral2.isNumeral = function(obj) {
+ return obj instanceof Numeral;
+ };
+ numeral2._ = _ = {
+ numberToFormat: function(value, format, roundingFunction) {
+ var locale = locales[numeral2.options.currentLocale], negP = false, optDec = false, leadingCount = 0, abbr = "", trillion = 1e12, billion = 1e9, million = 1e6, thousand = 1e3, decimal = "", neg = false, abbrForce, abs, min, max, power, int, precision, signed, thousands, output;
+ value = value || 0;
+ abs = Math.abs(value);
+ if (numeral2._.includes(format, "(")) {
+ negP = true;
+ format = format.replace(/[\(|\)]/g, "");
+ } else if (numeral2._.includes(format, "+") || numeral2._.includes(format, "-")) {
+ signed = numeral2._.includes(format, "+") ? format.indexOf("+") : value < 0 ? format.indexOf("-") : -1;
+ format = format.replace(/[\+|\-]/g, "");
+ }
+ if (numeral2._.includes(format, "a")) {
+ abbrForce = format.match(/a(k|m|b|t)?/);
+ abbrForce = abbrForce ? abbrForce[1] : false;
+ if (numeral2._.includes(format, " a")) {
+ abbr = " ";
+ }
+ format = format.replace(new RegExp(abbr + "a[kmbt]?"), "");
+ if (abs >= trillion && !abbrForce || abbrForce === "t") {
+ abbr += locale.abbreviations.trillion;
+ value = value / trillion;
+ } else if (abs < trillion && abs >= billion && !abbrForce || abbrForce === "b") {
+ abbr += locale.abbreviations.billion;
+ value = value / billion;
+ } else if (abs < billion && abs >= million && !abbrForce || abbrForce === "m") {
+ abbr += locale.abbreviations.million;
+ value = value / million;
+ } else if (abs < million && abs >= thousand && !abbrForce || abbrForce === "k") {
+ abbr += locale.abbreviations.thousand;
+ value = value / thousand;
+ }
+ }
+ if (numeral2._.includes(format, "[.]")) {
+ optDec = true;
+ format = format.replace("[.]", ".");
+ }
+ int = value.toString().split(".")[0];
+ precision = format.split(".")[1];
+ thousands = format.indexOf(",");
+ leadingCount = (format.split(".")[0].split(",")[0].match(/0/g) || []).length;
+ if (precision) {
+ if (numeral2._.includes(precision, "[")) {
+ precision = precision.replace("]", "");
+ precision = precision.split("[");
+ decimal = numeral2._.toFixed(value, precision[0].length + precision[1].length, roundingFunction, precision[1].length);
+ } else {
+ decimal = numeral2._.toFixed(value, precision.length, roundingFunction);
+ }
+ int = decimal.split(".")[0];
+ if (numeral2._.includes(decimal, ".")) {
+ decimal = locale.delimiters.decimal + decimal.split(".")[1];
+ } else {
+ decimal = "";
+ }
+ if (optDec && Number(decimal.slice(1)) === 0) {
+ decimal = "";
+ }
+ } else {
+ int = numeral2._.toFixed(value, 0, roundingFunction);
+ }
+ if (abbr && !abbrForce && Number(int) >= 1e3 && abbr !== locale.abbreviations.trillion) {
+ int = String(Number(int) / 1e3);
+ switch (abbr) {
+ case locale.abbreviations.thousand:
+ abbr = locale.abbreviations.million;
+ break;
+ case locale.abbreviations.million:
+ abbr = locale.abbreviations.billion;
+ break;
+ case locale.abbreviations.billion:
+ abbr = locale.abbreviations.trillion;
+ break;
+ }
+ }
+ if (numeral2._.includes(int, "-")) {
+ int = int.slice(1);
+ neg = true;
+ }
+ if (int.length < leadingCount) {
+ for (var i = leadingCount - int.length; i > 0; i--) {
+ int = "0" + int;
+ }
+ }
+ if (thousands > -1) {
+ int = int.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1" + locale.delimiters.thousands);
+ }
+ if (format.indexOf(".") === 0) {
+ int = "";
+ }
+ output = int + decimal + (abbr ? abbr : "");
+ if (negP) {
+ output = (negP && neg ? "(" : "") + output + (negP && neg ? ")" : "");
+ } else {
+ if (signed >= 0) {
+ output = signed === 0 ? (neg ? "-" : "+") + output : output + (neg ? "-" : "+");
+ } else if (neg) {
+ output = "-" + output;
+ }
+ }
+ return output;
+ },
+ stringToNumber: function(string) {
+ var locale = locales[options.currentLocale], stringOriginal = string, abbreviations = {
+ thousand: 3,
+ million: 6,
+ billion: 9,
+ trillion: 12
+ }, abbreviation, value, i, regexp;
+ if (options.zeroFormat && string === options.zeroFormat) {
+ value = 0;
+ } else if (options.nullFormat && string === options.nullFormat || !string.replace(/[^0-9]+/g, "").length) {
+ value = null;
+ } else {
+ value = 1;
+ if (locale.delimiters.decimal !== ".") {
+ string = string.replace(/\./g, "").replace(locale.delimiters.decimal, ".");
+ }
+ for (abbreviation in abbreviations) {
+ regexp = new RegExp("[^a-zA-Z]" + locale.abbreviations[abbreviation] + "(?:\\)|(\\" + locale.currency.symbol + ")?(?:\\))?)?$");
+ if (stringOriginal.match(regexp)) {
+ value *= Math.pow(10, abbreviations[abbreviation]);
+ break;
+ }
+ }
+ value *= (string.split("-").length + Math.min(string.split("(").length - 1, string.split(")").length - 1)) % 2 ? 1 : -1;
+ string = string.replace(/[^0-9\.]+/g, "");
+ value *= Number(string);
+ }
+ return value;
+ },
+ isNaN: function(value) {
+ return typeof value === "number" && isNaN(value);
+ },
+ includes: function(string, search) {
+ return string.indexOf(search) !== -1;
+ },
+ insert: function(string, subString, start) {
+ return string.slice(0, start) + subString + string.slice(start);
+ },
+ reduce: function(array, callback) {
+ if (this === null) {
+ throw new TypeError("Array.prototype.reduce called on null or undefined");
+ }
+ if (typeof callback !== "function") {
+ throw new TypeError(callback + " is not a function");
+ }
+ var t = Object(array), len = t.length >>> 0, k = 0, value;
+ if (arguments.length === 3) {
+ value = arguments[2];
+ } else {
+ while (k < len && !(k in t)) {
+ k++;
+ }
+ if (k >= len) {
+ throw new TypeError("Reduce of empty array with no initial value");
+ }
+ value = t[k++];
+ }
+ for (; k < len; k++) {
+ if (k in t) {
+ value = callback(value, t[k], k, t);
+ }
+ }
+ return value;
+ },
+ multiplier: function(x) {
+ var parts = x.toString().split(".");
+ return parts.length < 2 ? 1 : Math.pow(10, parts[1].length);
+ },
+ correctionFactor: function() {
+ var args = Array.prototype.slice.call(arguments);
+ return args.reduce(function(accum, next) {
+ var mn = _.multiplier(next);
+ return accum > mn ? accum : mn;
+ }, 1);
+ },
+ toFixed: function(value, maxDecimals, roundingFunction, optionals) {
+ var splitValue = value.toString().split("."), minDecimals = maxDecimals - (optionals || 0), boundedPrecision, optionalsRegExp, power, output;
+ if (splitValue.length === 2) {
+ boundedPrecision = Math.min(Math.max(splitValue[1].length, minDecimals), maxDecimals);
+ } else {
+ boundedPrecision = minDecimals;
+ }
+ power = Math.pow(10, boundedPrecision);
+ output = (roundingFunction(value + "e+" + boundedPrecision) / power).toFixed(boundedPrecision);
+ if (optionals > maxDecimals - boundedPrecision) {
+ optionalsRegExp = new RegExp("\\.?0{1," + (optionals - (maxDecimals - boundedPrecision)) + "}$");
+ output = output.replace(optionalsRegExp, "");
+ }
+ return output;
+ }
+ };
+ numeral2.options = options;
+ numeral2.formats = formats;
+ numeral2.locales = locales;
+ numeral2.locale = function(key) {
+ if (key) {
+ options.currentLocale = key.toLowerCase();
+ }
+ return options.currentLocale;
+ };
+ numeral2.localeData = function(key) {
+ if (!key) {
+ return locales[options.currentLocale];
+ }
+ key = key.toLowerCase();
+ if (!locales[key]) {
+ throw new Error("Unknown locale : " + key);
+ }
+ return locales[key];
+ };
+ numeral2.reset = function() {
+ for (var property in defaults) {
+ options[property] = defaults[property];
+ }
+ };
+ numeral2.zeroFormat = function(format) {
+ options.zeroFormat = typeof format === "string" ? format : null;
+ };
+ numeral2.nullFormat = function(format) {
+ options.nullFormat = typeof format === "string" ? format : null;
+ };
+ numeral2.defaultFormat = function(format) {
+ options.defaultFormat = typeof format === "string" ? format : "0.0";
+ };
+ numeral2.register = function(type, name, format) {
+ name = name.toLowerCase();
+ if (this[type + "s"][name]) {
+ throw new TypeError(name + " " + type + " already registered.");
+ }
+ this[type + "s"][name] = format;
+ return format;
+ };
+ numeral2.validate = function(val, culture) {
+ var _decimalSep, _thousandSep, _currSymbol, _valArray, _abbrObj, _thousandRegEx, localeData, temp;
+ if (typeof val !== "string") {
+ val += "";
+ if (console.warn) {
+ console.warn("Numeral.js: Value is not string. It has been co-erced to: ", val);
+ }
+ }
+ val = val.trim();
+ if (!!val.match(/^\d+$/)) {
+ return true;
+ }
+ if (val === "") {
+ return false;
+ }
+ try {
+ localeData = numeral2.localeData(culture);
+ } catch (e) {
+ localeData = numeral2.localeData(numeral2.locale());
+ }
+ _currSymbol = localeData.currency.symbol;
+ _abbrObj = localeData.abbreviations;
+ _decimalSep = localeData.delimiters.decimal;
+ if (localeData.delimiters.thousands === ".") {
+ _thousandSep = "\\.";
+ } else {
+ _thousandSep = localeData.delimiters.thousands;
+ }
+ temp = val.match(/^[^\d]+/);
+ if (temp !== null) {
+ val = val.substr(1);
+ if (temp[0] !== _currSymbol) {
+ return false;
+ }
+ }
+ temp = val.match(/[^\d]+$/);
+ if (temp !== null) {
+ val = val.slice(0, -1);
+ if (temp[0] !== _abbrObj.thousand && temp[0] !== _abbrObj.million && temp[0] !== _abbrObj.billion && temp[0] !== _abbrObj.trillion) {
+ return false;
+ }
+ }
+ _thousandRegEx = new RegExp(_thousandSep + "{2}");
+ if (!val.match(/[^\d.,]/g)) {
+ _valArray = val.split(_decimalSep);
+ if (_valArray.length > 2) {
+ return false;
+ } else {
+ if (_valArray.length < 2) {
+ return !!_valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx);
+ } else {
+ if (_valArray[0].length === 1) {
+ return !!_valArray[0].match(/^\d+$/) && !_valArray[0].match(_thousandRegEx) && !!_valArray[1].match(/^\d+$/);
+ } else {
+ return !!_valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx) && !!_valArray[1].match(/^\d+$/);
+ }
+ }
+ }
+ }
+ return false;
+ };
+ numeral2.fn = Numeral.prototype = {
+ clone: function() {
+ return numeral2(this);
+ },
+ format: function(inputString, roundingFunction) {
+ var value = this._value, format = inputString || options.defaultFormat, kind, output, formatFunction;
+ roundingFunction = roundingFunction || Math.round;
+ if (value === 0 && options.zeroFormat !== null) {
+ output = options.zeroFormat;
+ } else if (value === null && options.nullFormat !== null) {
+ output = options.nullFormat;
+ } else {
+ for (kind in formats) {
+ if (format.match(formats[kind].regexps.format)) {
+ formatFunction = formats[kind].format;
+ break;
+ }
+ }
+ formatFunction = formatFunction || numeral2._.numberToFormat;
+ output = formatFunction(value, format, roundingFunction);
+ }
+ return output;
+ },
+ value: function() {
+ return this._value;
+ },
+ input: function() {
+ return this._input;
+ },
+ set: function(value) {
+ this._value = Number(value);
+ return this;
+ },
+ add: function(value) {
+ var corrFactor = _.correctionFactor.call(null, this._value, value);
+ function cback(accum, curr, currI, O) {
+ return accum + Math.round(corrFactor * curr);
+ }
+ this._value = _.reduce([this._value, value], cback, 0) / corrFactor;
+ return this;
+ },
+ subtract: function(value) {
+ var corrFactor = _.correctionFactor.call(null, this._value, value);
+ function cback(accum, curr, currI, O) {
+ return accum - Math.round(corrFactor * curr);
+ }
+ this._value = _.reduce([value], cback, Math.round(this._value * corrFactor)) / corrFactor;
+ return this;
+ },
+ multiply: function(value) {
+ function cback(accum, curr, currI, O) {
+ var corrFactor = _.correctionFactor(accum, curr);
+ return Math.round(accum * corrFactor) * Math.round(curr * corrFactor) / Math.round(corrFactor * corrFactor);
+ }
+ this._value = _.reduce([this._value, value], cback, 1);
+ return this;
+ },
+ divide: function(value) {
+ function cback(accum, curr, currI, O) {
+ var corrFactor = _.correctionFactor(accum, curr);
+ return Math.round(accum * corrFactor) / Math.round(curr * corrFactor);
+ }
+ this._value = _.reduce([this._value, value], cback);
+ return this;
+ },
+ difference: function(value) {
+ return Math.abs(numeral2(this._value).subtract(value).value());
+ }
+ };
+ numeral2.register("locale", "en", {
+ delimiters: {
+ thousands: ",",
+ decimal: "."
+ },
+ abbreviations: {
+ thousand: "k",
+ million: "m",
+ billion: "b",
+ trillion: "t"
+ },
+ ordinal: function(number) {
+ var b = number % 10;
+ return ~~(number % 100 / 10) === 1 ? "th" : b === 1 ? "st" : b === 2 ? "nd" : b === 3 ? "rd" : "th";
+ },
+ currency: {
+ symbol: "$"
+ }
+ });
+ (function() {
+ numeral2.register("format", "bps", {
+ regexps: {
+ format: /(BPS)/,
+ unformat: /(BPS)/
+ },
+ format: function(value, format, roundingFunction) {
+ var space = numeral2._.includes(format, " BPS") ? " " : "", output;
+ value = value * 1e4;
+ format = format.replace(/\s?BPS/, "");
+ output = numeral2._.numberToFormat(value, format, roundingFunction);
+ if (numeral2._.includes(output, ")")) {
+ output = output.split("");
+ output.splice(-1, 0, space + "BPS");
+ output = output.join("");
+ } else {
+ output = output + space + "BPS";
+ }
+ return output;
+ },
+ unformat: function(string) {
+ return +(numeral2._.stringToNumber(string) * 1e-4).toFixed(15);
+ }
+ });
+ })();
+ (function() {
+ var decimal = {
+ base: 1e3,
+ suffixes: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
+ }, binary = {
+ base: 1024,
+ suffixes: ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]
+ };
+ var allSuffixes = decimal.suffixes.concat(binary.suffixes.filter(function(item) {
+ return decimal.suffixes.indexOf(item) < 0;
+ }));
+ var unformatRegex = allSuffixes.join("|");
+ unformatRegex = "(" + unformatRegex.replace("B", "B(?!PS)") + ")";
+ numeral2.register("format", "bytes", {
+ regexps: {
+ format: /([0\s]i?b)/,
+ unformat: new RegExp(unformatRegex)
+ },
+ format: function(value, format, roundingFunction) {
+ var output, bytes = numeral2._.includes(format, "ib") ? binary : decimal, suffix = numeral2._.includes(format, " b") || numeral2._.includes(format, " ib") ? " " : "", power, min, max;
+ format = format.replace(/\s?i?b/, "");
+ for (power = 0; power <= bytes.suffixes.length; power++) {
+ min = Math.pow(bytes.base, power);
+ max = Math.pow(bytes.base, power + 1);
+ if (value === null || value === 0 || value >= min && value < max) {
+ suffix += bytes.suffixes[power];
+ if (min > 0) {
+ value = value / min;
+ }
+ break;
+ }
+ }
+ output = numeral2._.numberToFormat(value, format, roundingFunction);
+ return output + suffix;
+ },
+ unformat: function(string) {
+ var value = numeral2._.stringToNumber(string), power, bytesMultiplier;
+ if (value) {
+ for (power = decimal.suffixes.length - 1; power >= 0; power--) {
+ if (numeral2._.includes(string, decimal.suffixes[power])) {
+ bytesMultiplier = Math.pow(decimal.base, power);
+ break;
+ }
+ if (numeral2._.includes(string, binary.suffixes[power])) {
+ bytesMultiplier = Math.pow(binary.base, power);
+ break;
+ }
+ }
+ value *= bytesMultiplier || 1;
+ }
+ return value;
+ }
+ });
+ })();
+ (function() {
+ numeral2.register("format", "currency", {
+ regexps: {
+ format: /(\$)/
+ },
+ format: function(value, format, roundingFunction) {
+ var locale = numeral2.locales[numeral2.options.currentLocale], symbols = {
+ before: format.match(/^([\+|\-|\(|\s|\$]*)/)[0],
+ after: format.match(/([\+|\-|\)|\s|\$]*)$/)[0]
+ }, output, symbol, i;
+ format = format.replace(/\s?\$\s?/, "");
+ output = numeral2._.numberToFormat(value, format, roundingFunction);
+ if (value >= 0) {
+ symbols.before = symbols.before.replace(/[\-\(]/, "");
+ symbols.after = symbols.after.replace(/[\-\)]/, "");
+ } else if (value < 0 && (!numeral2._.includes(symbols.before, "-") && !numeral2._.includes(symbols.before, "("))) {
+ symbols.before = "-" + symbols.before;
+ }
+ for (i = 0; i < symbols.before.length; i++) {
+ symbol = symbols.before[i];
+ switch (symbol) {
+ case "$":
+ output = numeral2._.insert(output, locale.currency.symbol, i);
+ break;
+ case " ":
+ output = numeral2._.insert(output, " ", i + locale.currency.symbol.length - 1);
+ break;
+ }
+ }
+ for (i = symbols.after.length - 1; i >= 0; i--) {
+ symbol = symbols.after[i];
+ switch (symbol) {
+ case "$":
+ output = i === symbols.after.length - 1 ? output + locale.currency.symbol : numeral2._.insert(output, locale.currency.symbol, -(symbols.after.length - (1 + i)));
+ break;
+ case " ":
+ output = i === symbols.after.length - 1 ? output + " " : numeral2._.insert(output, " ", -(symbols.after.length - (1 + i) + locale.currency.symbol.length - 1));
+ break;
+ }
+ }
+ return output;
+ }
+ });
+ })();
+ (function() {
+ numeral2.register("format", "exponential", {
+ regexps: {
+ format: /(e\+|e-)/,
+ unformat: /(e\+|e-)/
+ },
+ format: function(value, format, roundingFunction) {
+ var output, exponential = typeof value === "number" && !numeral2._.isNaN(value) ? value.toExponential() : "0e+0", parts = exponential.split("e");
+ format = format.replace(/e[\+|\-]{1}0/, "");
+ output = numeral2._.numberToFormat(Number(parts[0]), format, roundingFunction);
+ return output + "e" + parts[1];
+ },
+ unformat: function(string) {
+ var parts = numeral2._.includes(string, "e+") ? string.split("e+") : string.split("e-"), value = Number(parts[0]), power = Number(parts[1]);
+ power = numeral2._.includes(string, "e-") ? power *= -1 : power;
+ function cback(accum, curr, currI, O) {
+ var corrFactor = numeral2._.correctionFactor(accum, curr), num = accum * corrFactor * (curr * corrFactor) / (corrFactor * corrFactor);
+ return num;
+ }
+ return numeral2._.reduce([value, Math.pow(10, power)], cback, 1);
+ }
+ });
+ })();
+ (function() {
+ numeral2.register("format", "ordinal", {
+ regexps: {
+ format: /(o)/
+ },
+ format: function(value, format, roundingFunction) {
+ var locale = numeral2.locales[numeral2.options.currentLocale], output, ordinal = numeral2._.includes(format, " o") ? " " : "";
+ format = format.replace(/\s?o/, "");
+ ordinal += locale.ordinal(value);
+ output = numeral2._.numberToFormat(value, format, roundingFunction);
+ return output + ordinal;
+ }
+ });
+ })();
+ (function() {
+ numeral2.register("format", "percentage", {
+ regexps: {
+ format: /(%)/,
+ unformat: /(%)/
+ },
+ format: function(value, format, roundingFunction) {
+ var space = numeral2._.includes(format, " %") ? " " : "", output;
+ if (numeral2.options.scalePercentBy100) {
+ value = value * 100;
+ }
+ format = format.replace(/\s?\%/, "");
+ output = numeral2._.numberToFormat(value, format, roundingFunction);
+ if (numeral2._.includes(output, ")")) {
+ output = output.split("");
+ output.splice(-1, 0, space + "%");
+ output = output.join("");
+ } else {
+ output = output + space + "%";
+ }
+ return output;
+ },
+ unformat: function(string) {
+ var number = numeral2._.stringToNumber(string);
+ if (numeral2.options.scalePercentBy100) {
+ return number * 0.01;
+ }
+ return number;
+ }
+ });
+ })();
+ (function() {
+ numeral2.register("format", "time", {
+ regexps: {
+ format: /(:)/,
+ unformat: /(:)/
+ },
+ format: function(value, format, roundingFunction) {
+ var hours = Math.floor(value / 60 / 60), minutes = Math.floor((value - hours * 60 * 60) / 60), seconds = Math.round(value - hours * 60 * 60 - minutes * 60);
+ return hours + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds < 10 ? "0" + seconds : seconds);
+ },
+ unformat: function(string) {
+ var timeArray = string.split(":"), seconds = 0;
+ if (timeArray.length === 3) {
+ seconds = seconds + Number(timeArray[0]) * 60 * 60;
+ seconds = seconds + Number(timeArray[1]) * 60;
+ seconds = seconds + Number(timeArray[2]);
+ } else if (timeArray.length === 2) {
+ seconds = seconds + Number(timeArray[0]) * 60;
+ seconds = seconds + Number(timeArray[1]);
+ }
+ return Number(seconds);
+ }
+ });
+ })();
+ return numeral2;
+ });
+ }
+});
+
+// main.ts
+__export(exports, {
+ CRYPTONATOR_API: () => CRYPTONATOR_API,
+ default: () => CryptoLookup
+});
+var import_obsidian2 = __toModule(require("obsidian"));
+var import_numeral = __toModule(require_numeral());
+
+// crypto-modal.ts
+var import_obsidian = __toModule(require("obsidian"));
+var CryptoModal = class extends import_obsidian.Modal {
+ constructor(app, defaultTarget, onSubmit) {
+ super(app);
+ this.target = defaultTarget;
+ this.onSubmit = onSubmit;
+ }
+ onOpen() {
+ const { contentEl } = this;
+ contentEl.createEl("h1", { text: "Select crypto base and target" });
+ new import_obsidian.Setting(contentEl).setName("Base").addText((text) => text.setValue(this.base).onChange((value) => {
+ this.base = value;
+ }));
+ new import_obsidian.Setting(contentEl).setName("Target").addText((text) => text.setValue(this.target).onChange((value) => {
+ this.target = value;
+ }));
+ new import_obsidian.Setting(contentEl).addButton((btn) => btn.setButtonText("Lookup").setCta().onClick(() => {
+ this.close();
+ this.onSubmit(this.base, this.target);
+ }));
+ }
+ onClose() {
+ let { contentEl } = this;
+ contentEl.empty();
+ }
+};
+
+// main.ts
+var CRYPTONATOR_API = "https://api.cryptonator.com/api";
+var DEFAULT_SETTINGS = {
+ defaultBase: "BTC",
+ defaultTarget: "USD"
+};
+var CryptoLookup = class extends import_obsidian2.Plugin {
+ getCurrencyTicker(base, target) {
+ return __async(this, null, function* () {
+ const data = yield (0, import_obsidian2.request)({
+ url: `${CRYPTONATOR_API}/ticker/${base}-${target}`
+ });
+ return JSON.parse(data);
+ });
+ }
+ getCurrencyListAsJson() {
+ return __async(this, null, function* () {
+ return yield (0, import_obsidian2.request)({
+ url: `${CRYPTONATOR_API}/currencies`
+ });
+ });
+ }
+ onload() {
+ return __async(this, null, function* () {
+ yield this.loadSettings();
+ const adapter = this.app.vault.adapter;
+ const dir = this.manifest.dir;
+ yield (() => __async(this, null, function* () {
+ const path = (0, import_obsidian2.normalizePath)(`${dir}/currencies.json`);
+ if (yield adapter.exists(path)) {
+ const currencies = yield adapter.read(path);
+ this.currencies = JSON.parse(currencies).rows;
+ } else {
+ try {
+ const currencyText = yield this.getCurrencyListAsJson();
+ yield adapter.write(path, currencyText);
+ this.currencies = JSON.parse(currencyText).rows;
+ } catch (error) {
+ const text = "The JSON file could not be read.";
+ new import_obsidian2.Notice(text);
+ console.error(error);
+ }
+ }
+ }))();
+ this.addCommand({
+ id: "insert-default-crypto-ticker",
+ name: "Insert Default Crypto Ticker",
+ editorCallback: (editor) => __async(this, null, function* () {
+ if (!this.settings.defaultBase || !this.settings.defaultTarget) {
+ new import_obsidian2.Notice("Cannot use this command without default base and target in settings");
+ } else {
+ const base = this.settings.defaultBase;
+ const target = this.settings.defaultTarget;
+ const currencyTicker = yield this.getCurrencyTicker(base.toLocaleLowerCase(), target.toLocaleLowerCase());
+ const extendedCryptoTicker = `${base}:${target} price = ${(0, import_numeral.default)(currencyTicker.ticker.price).format("0,00.00")}`;
+ editor.replaceSelection(extendedCryptoTicker);
+ }
+ })
+ });
+ this.addCommand({
+ id: "insert-default-crypto-ticker-extended",
+ name: "Insert Default Crypto Ticker Extended",
+ editorCallback: (editor) => __async(this, null, function* () {
+ if (!this.settings.defaultBase || !this.settings.defaultTarget) {
+ new import_obsidian2.Notice("Cannot use this command without default base and target in settings");
+ } else {
+ const base = this.settings.defaultBase;
+ const target = this.settings.defaultTarget;
+ const currencyTicker = yield this.getCurrencyTicker(base.toLocaleLowerCase(), target.toLocaleLowerCase());
+ const formattedTimestamp = window.moment(currencyTicker.timestamp * 1e3).format("YYYY-MM-DDTHH:mm:ss");
+ const extendedCryptoTicker = `${base}:${target} price = ${(0, import_numeral.default)(currencyTicker.ticker.price).format("0,00.00")}, volume = ${(0, import_numeral.default)(currencyTicker.ticker.volume).format("0,00.00")}, change = ${(0, import_numeral.default)(currencyTicker.ticker.change).format("0,00.00")} on ${formattedTimestamp}`;
+ editor.replaceSelection(extendedCryptoTicker);
+ }
+ })
+ });
+ this.addCommand({
+ id: "insert-selected-crypto-ticker",
+ name: "Insert Selected Crypto Ticker",
+ editorCallback: (editor) => __async(this, null, function* () {
+ const onSubmit = (base, target) => __async(this, null, function* () {
+ const currencyTicker = yield this.getCurrencyTicker(base.toLocaleLowerCase(), target.toLocaleLowerCase());
+ const extendedCryptoTicker = `${base}:${target} price = ${(0, import_numeral.default)(currencyTicker.ticker.price).format("0,00.00")}`;
+ editor.replaceSelection(extendedCryptoTicker);
+ });
+ new CryptoModal(this.app, "USD", onSubmit).open();
+ })
+ });
+ this.addCommand({
+ id: "insert-selected-crypto-ticker-extended",
+ name: "Insert Selected Crypto Ticker Extended",
+ editorCallback: (editor) => __async(this, null, function* () {
+ const onSubmit = (base, target) => __async(this, null, function* () {
+ const currencyTicker = yield this.getCurrencyTicker(base.toLocaleLowerCase(), target.toLocaleLowerCase());
+ const formattedTimestamp = window.moment(currencyTicker.timestamp * 1e3).format("YYYY-MM-DDTHH:mm:ss");
+ const extendedCryptoTicker = `${base}:${target} price = ${(0, import_numeral.default)(currencyTicker.ticker.price).format("0,00.00")}, volume = ${(0, import_numeral.default)(currencyTicker.ticker.volume).format("0,00.00")}, change = ${(0, import_numeral.default)(currencyTicker.ticker.change).format("0,00.00")} on ${formattedTimestamp}`;
+ editor.replaceSelection(extendedCryptoTicker);
+ });
+ new CryptoModal(this.app, "USD", onSubmit).open();
+ })
+ });
+ this.addSettingTab(new CryptoLookupSettingTab(this.app, this));
+ });
+ }
+ onunload() {
+ }
+ loadSettings() {
+ return __async(this, null, function* () {
+ this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
+ });
+ }
+ saveSettings() {
+ return __async(this, null, function* () {
+ yield this.saveData(this.settings);
+ });
+ }
+};
+var CryptoLookupSettingTab = class extends import_obsidian2.PluginSettingTab {
+ constructor(app, plugin) {
+ super(app, plugin);
+ this.plugin = plugin;
+ }
+ display() {
+ let { containerEl } = this;
+ containerEl.empty();
+ containerEl.createEl("h2", { text: "Crypto Lookup Defaults" });
+ new import_obsidian2.Setting(containerEl).setName("Base Currency").setDesc("Default currency we want the price of").addText((text) => text.setPlaceholder("BTC").setValue(this.plugin.settings.defaultBase).onChange((value) => __async(this, null, function* () {
+ this.plugin.settings.defaultBase = value;
+ yield this.plugin.saveSettings();
+ })));
+ new import_obsidian2.Setting(containerEl).setName("Target Currency").setDesc("Default target currency to convert base currency into").addText((text) => text.setPlaceholder("USD").setValue(this.plugin.settings.defaultTarget).onChange((value) => __async(this, null, function* () {
+ this.plugin.settings.defaultTarget = value;
+ yield this.plugin.saveSettings();
+ })));
+ }
+};
+/*! @preserve
+ * numeral.js
+ * version : 2.0.6
+ * author : Adam Draper
+ * license : MIT
+ * http://adamwdraper.github.com/Numeral-js/
+ */
diff --git a/.obsidian/plugins/obsidian-crypto-lookup/manifest.json b/.obsidian/plugins/obsidian-crypto-lookup/manifest.json
new file mode 100644
index 00000000..1a5c754a
--- /dev/null
+++ b/.obsidian/plugins/obsidian-crypto-lookup/manifest.json
@@ -0,0 +1 @@
+{"id":"obsidian-crypto-lookup","name":"Crypto Lookup","version":"0.0.2","minAppVersion":"0.12.0","description":"A plugin for Obsidian which uses the Cryptonator API to pull back prices for crypto in a target currency","author":"Andrew Lombardi","authorUrl":"https://mysticcoders.com","isDesktopOnly":false}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-crypto-lookup/styles.css b/.obsidian/plugins/obsidian-crypto-lookup/styles.css
new file mode 100644
index 00000000..2ed200b6
--- /dev/null
+++ b/.obsidian/plugins/obsidian-crypto-lookup/styles.css
@@ -0,0 +1,4 @@
+/* Sets all the text color to red! */
+/*body {*/
+/* color: red;*/
+/*}*/
diff --git a/.obsidian/plugins/obsidian-lineup-builder/main.js b/.obsidian/plugins/obsidian-lineup-builder/main.js
new file mode 100644
index 00000000..c0544ded
--- /dev/null
+++ b/.obsidian/plugins/obsidian-lineup-builder/main.js
@@ -0,0 +1,314 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
+var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __reExport = (target, module2, desc) => {
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
+ for (let key of __getOwnPropNames(module2))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
+ }
+ return target;
+};
+var __toModule = (module2) => {
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
+};
+var __async = (__this, __arguments, generator) => {
+ return new Promise((resolve, reject) => {
+ var fulfilled = (value) => {
+ try {
+ step(generator.next(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var rejected = (value) => {
+ try {
+ step(generator.throw(value));
+ } catch (e) {
+ reject(e);
+ }
+ };
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+ step((generator = generator.apply(__this, __arguments)).next());
+ });
+};
+
+// src/main.ts
+__export(exports, {
+ default: () => LineupBuilderPlugin
+});
+
+// src/config.ts
+var KEEPER_COLOUR = "#808080";
+var DEFENDER_COLOUR = "#2009ff";
+var MIDFIELDER_COLOUR = "#ff0";
+var FORWARD_COLOUR = "#f00";
+
+// src/position.ts
+var GK = {
+ x: 772,
+ y: 1670,
+ circleColour: KEEPER_COLOUR
+};
+var LB = {
+ x: 272,
+ y: 1347,
+ circleColour: DEFENDER_COLOUR
+};
+var CBL = {
+ x: 571,
+ y: 1447,
+ circleColour: DEFENDER_COLOUR
+};
+var CBR = {
+ x: 970,
+ y: 1447,
+ circleColour: DEFENDER_COLOUR
+};
+var RB = {
+ x: 1272,
+ y: 1347,
+ circleColour: DEFENDER_COLOUR
+};
+var LWB = {
+ x: 272,
+ y: 1247,
+ circleColour: DEFENDER_COLOUR
+};
+var LCB = {
+ x: 471,
+ y: 1447,
+ circleColour: DEFENDER_COLOUR
+};
+var CCB = {
+ x: 772,
+ y: 1420,
+ circleColour: DEFENDER_COLOUR
+};
+var RCB = {
+ x: 1070,
+ y: 1447,
+ circleColour: DEFENDER_COLOUR
+};
+var RWB = {
+ x: 1272,
+ y: 1247,
+ circleColour: DEFENDER_COLOUR
+};
+var CDM = {
+ x: 772,
+ y: 1083,
+ circleColour: MIDFIELDER_COLOUR
+};
+var LDM = {
+ x: 551.8,
+ y: 1083,
+ circleColour: MIDFIELDER_COLOUR
+};
+var RDM = {
+ x: 988.8,
+ y: 1083,
+ circleColour: MIDFIELDER_COLOUR
+};
+var CML = {
+ x: 571,
+ y: 976,
+ circleColour: MIDFIELDER_COLOUR
+};
+var CMR = {
+ x: 970,
+ y: 976,
+ circleColour: MIDFIELDER_COLOUR
+};
+var LCM = {
+ x: 417,
+ y: 883,
+ circleColour: MIDFIELDER_COLOUR
+};
+var RCM = {
+ x: 1152,
+ y: 883,
+ circleColour: MIDFIELDER_COLOUR
+};
+var CAM = {
+ x: 772,
+ y: 580.9,
+ circleColour: MIDFIELDER_COLOUR
+};
+var LAM = {
+ x: 319.1,
+ y: 580.9,
+ circleColour: MIDFIELDER_COLOUR
+};
+var RAM = {
+ x: 1211.8,
+ y: 580.9,
+ circleColour: MIDFIELDER_COLOUR
+};
+var LM = {
+ x: 328,
+ y: 775,
+ circleColour: MIDFIELDER_COLOUR
+};
+var RM = {
+ x: 1216,
+ y: 775,
+ circleColour: MIDFIELDER_COLOUR
+};
+var RW = {
+ x: 1258,
+ y: 363,
+ circleColour: FORWARD_COLOUR
+};
+var LW = {
+ x: 282,
+ y: 363,
+ circleColour: FORWARD_COLOUR
+};
+var LS = {
+ x: 588,
+ y: 260,
+ circleColour: FORWARD_COLOUR
+};
+var RS = {
+ x: 962,
+ y: 260,
+ circleColour: FORWARD_COLOUR
+};
+var ST = {
+ x: 772,
+ y: 193,
+ circleColour: FORWARD_COLOUR
+};
+
+// src/formation.ts
+var formations = [
+ {
+ name: "442",
+ positions: [GK, LB, CBL, CBR, RB, LM, CML, CMR, RM, LS, RS]
+ },
+ {
+ name: "433",
+ positions: [GK, LB, CBL, CBR, RB, LCM, CDM, RCM, LW, ST, RW]
+ },
+ {
+ name: "4231",
+ positions: [GK, LB, CBL, CBR, RB, LDM, RDM, LAM, CAM, RAM, ST]
+ },
+ {
+ name: "442-diamond",
+ positions: [GK, LB, CBL, CBR, RB, CDM, LM, RM, CAM, LS, RS]
+ },
+ {
+ name: "541",
+ positions: [GK, LWB, LCB, CCB, RCB, RWB, LM, CML, CMR, RM, ST]
+ },
+ {
+ name: "523",
+ positions: [GK, LWB, LCB, CCB, RCB, RWB, CML, CMR, LW, ST, RW]
+ },
+ {
+ name: "532",
+ positions: [GK, LWB, LCB, CCB, RCB, RWB, LCM, CDM, RCM, LS, RS]
+ },
+ {
+ name: "343",
+ positions: [GK, LCB, CCB, RCB, LM, CML, CMR, RM, LW, ST, RW]
+ },
+ {
+ name: "352",
+ positions: [GK, LCB, CCB, RCB, LM, LDM, RDM, RM, CAM, LS, RS]
+ }
+];
+
+// src/main.ts
+var import_obsidian = __toModule(require("obsidian"));
+
+// src/svg-builder.ts
+var LABEL_OFFSET_X = -69;
+var LABEL_OFFSET_Y = 140;
+function buildLabels(positions, players) {
+ let labels = [];
+ for (var i = 0; i < positions.length; i++) {
+ labels[i] = buildLabel(positions[i], players[i]);
+ }
+ return labels;
+}
+function buildCircles(positions) {
+ return positions.map((position) => buildCircle(position));
+}
+function buildLabel(position, playerName) {
+ return `${playerName}`;
+}
+function buildCircle(position) {
+ return ``;
+}
+function buildSvg(positions, players) {
+ return `
+ `;
+}
+
+// src/main.ts
+var LineupBuilderPlugin = class extends import_obsidian.Plugin {
+ onInit() {
+ }
+ onload() {
+ return __async(this, null, function* () {
+ this.registerMarkdownCodeBlockProcessor("lineup", this.draw_lineup());
+ });
+ }
+ draw_lineup() {
+ return (source, el, ctx) => {
+ const { formation, players } = LineupBuilderPlugin.parseCode(source);
+ const xmlns = "http://www.w3.org/2000/svg";
+ var boxWidth = 346;
+ var boxHeight = 480;
+ var block = document.createElementNS(xmlns, "svg");
+ block.setAttributeNS(null, "viewBox", "0 0 " + boxWidth + " " + boxHeight);
+ block.setAttributeNS(null, "width", String(boxWidth));
+ block.setAttributeNS(null, "height", String(boxHeight));
+ block.innerHTML = buildSvg(formation.positions, players);
+ el.appendChild(block);
+ };
+ }
+ static parseCode(input) {
+ const lines = input.split(/\r?\n/);
+ let formation = lines[0];
+ if (formation.startsWith("formation: ")) {
+ formation = formation.replace("formation: ", "");
+ }
+ let players = [];
+ let playersLine = lines[1];
+ if (playersLine.startsWith("players: ")) {
+ players = playersLine.replace("players: ", "").split(",");
+ }
+ return {
+ formation: formations.find((x) => x.name === formation),
+ players
+ };
+ }
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL2NvbmZpZy50cyIsICJzcmMvcG9zaXRpb24udHMiLCAic3JjL2Zvcm1hdGlvbi50cyIsICJzcmMvc3ZnLWJ1aWxkZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IGZvcm1hdGlvbnMgfSBmcm9tICdzcmMvZm9ybWF0aW9uJztcclxuaW1wb3J0IHsgTWFya2Rvd25Qb3N0UHJvY2Vzc29yQ29udGV4dCwgUGx1Z2luIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBQYXJzZWRDb2RlIH0gZnJvbSAnLi90cy9pbnRlcmZhY2VzJztcclxuaW1wb3J0IHsgYnVpbGRTdmcgfSBmcm9tICcuL3N2Zy1idWlsZGVyJztcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpbmV1cEJ1aWxkZXJQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cclxuICAgIG9uSW5pdCgpIHsgfVxyXG5cclxuICAgIGFzeW5jIG9ubG9hZCgpIHtcclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Db2RlQmxvY2tQcm9jZXNzb3IoXHJcbiAgICAgICAgICAgIFwibGluZXVwXCIsXHJcbiAgICAgICAgICAgIHRoaXMuZHJhd19saW5ldXAoKVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBkcmF3X2xpbmV1cCgpIHtcclxuICAgICAgICByZXR1cm4gKHNvdXJjZTogc3RyaW5nLCBlbDogSFRNTEVsZW1lbnQsIGN0eDogTWFya2Rvd25Qb3N0UHJvY2Vzc29yQ29udGV4dCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgY29uc3Qge2Zvcm1hdGlvbiwgcGxheWVyc30gPSBMaW5ldXBCdWlsZGVyUGx1Z2luLnBhcnNlQ29kZShzb3VyY2UpO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgeG1sbnMgPSBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCI7XHJcbiAgICAgICAgICAgIHZhciBib3hXaWR0aCA9IDM0NjtcclxuICAgICAgICAgICAgdmFyIGJveEhlaWdodCA9IDQ4MDtcclxuICAgICAgICAgICAgdmFyIGJsb2NrID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHhtbG5zLCBcInN2Z1wiKTtcclxuICAgICAgICAgICAgYmxvY2suc2V0QXR0cmlidXRlTlMoXHJcbiAgICAgICAgICAgICAgICBudWxsLFxyXG4gICAgICAgICAgICAgICAgXCJ2aWV3Qm94XCIsXHJcbiAgICAgICAgICAgICAgICBcIjAgMCBcIiArIGJveFdpZHRoICsgXCIgXCIgKyBib3hIZWlnaHRcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgYmxvY2suc2V0QXR0cmlidXRlTlMobnVsbCwgXCJ3aWR0aFwiLCBTdHJpbmcoYm94V2lkdGgpKTtcclxuICAgICAgICAgICAgYmxvY2suc2V0QXR0cmlidXRlTlMobnVsbCwgXCJoZWlnaHRcIiwgU3RyaW5nKGJveEhlaWdodCkpO1xyXG4gICAgICAgICAgICBibG9jay5pbm5lckhUTUwgPSBidWlsZFN2Zyhmb3JtYXRpb24ucG9zaXRpb25zLCBwbGF5ZXJzKTtcclxuICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoYmxvY2spO1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VDb2RlKGlucHV0OiBzdHJpbmcpOiBQYXJzZWRDb2RlIHtcclxuICAgICAgICBjb25zdCBsaW5lcyA9IGlucHV0LnNwbGl0KC9cXHI/XFxuLyk7XHJcbiAgICAgICAgbGV0IGZvcm1hdGlvbjogc3RyaW5nID0gbGluZXNbMF07XHJcbiAgICAgICAgaWYgKGZvcm1hdGlvbi5zdGFydHNXaXRoKFwiZm9ybWF0aW9uOiBcIikpIHtcclxuICAgICAgICAgICAgZm9ybWF0aW9uID0gZm9ybWF0aW9uLnJlcGxhY2UoXCJmb3JtYXRpb246IFwiLCBcIlwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBwbGF5ZXJzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgIGxldCBwbGF5ZXJzTGluZTogc3RyaW5nID0gbGluZXNbMV07XHJcbiAgICAgICAgaWYgKHBsYXllcnNMaW5lLnN0YXJ0c1dpdGgoXCJwbGF5ZXJzOiBcIikpIHtcclxuICAgICAgICAgICAgcGxheWVycyA9IHBsYXllcnNMaW5lLnJlcGxhY2UoXCJwbGF5ZXJzOiBcIiwgXCJcIikuc3BsaXQoJywnKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGZvcm1hdGlvbjogZm9ybWF0aW9ucy5maW5kKHggPT4geC5uYW1lID09PSBmb3JtYXRpb24pLFxyXG4gICAgICAgICAgICBwbGF5ZXJzXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG4iLCAiZXhwb3J0IGNvbnN0IEtFRVBFUl9DT0xPVVIgPSAnIzgwODA4MCc7XG5leHBvcnQgY29uc3QgREVGRU5ERVJfQ09MT1VSID0gJyMyMDA5ZmYnO1xuZXhwb3J0IGNvbnN0IE1JREZJRUxERVJfQ09MT1VSID0gJyNmZjAnO1xuZXhwb3J0IGNvbnN0IEZPUldBUkRfQ09MT1VSID0gJyNmMDAnOyIsICJpbXBvcnQgeyBERUZFTkRFUl9DT0xPVVIsIEZPUldBUkRfQ09MT1VSLCBLRUVQRVJfQ09MT1VSLCBNSURGSUVMREVSX0NPTE9VUiB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7UG9zaXRpb259IGZyb20gJy4vdHMvaW50ZXJmYWNlcyc7XG5cbi8vIFRoaXMgbW9kdWxlIGNvbnRhaW5zIHRoZSBkZWZpbml0aW9ucyBvZiBhbGwgcG9zaXRpb25zXG5cbi8vIEdLXG5leHBvcnQgY29uc3QgR0s6IFBvc2l0aW9uID0ge1xuICAgIHg6IDc3MixcbiAgICB5OiAxNjcwLFxuICAgIGNpcmNsZUNvbG91cjogS0VFUEVSX0NPTE9VUlxufVxuXG4vLyBERUZFTkRFUlNcblxuLy8gNEFUQiBEZWZlbmRlcnNcbmV4cG9ydCBjb25zdCBMQjogUG9zaXRpb24gPSB7XG4gICAgeDogMjcyLFxuICAgIHk6IDEzNDcsXG4gICAgY2lyY2xlQ29sb3VyOiBERUZFTkRFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBDQkw6IFBvc2l0aW9uID0ge1xuICAgIHg6IDU3MSxcbiAgICB5OiAxNDQ3LFxuICAgIGNpcmNsZUNvbG91cjogREVGRU5ERVJfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgQ0JSOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA5NzAsXG4gICAgeTogMTQ0NyxcbiAgICBjaXJjbGVDb2xvdXI6IERFRkVOREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IFJCOiBQb3NpdGlvbiA9IHtcbiAgICB4OiAxMjcyLFxuICAgIHk6IDEzNDcsXG4gICAgY2lyY2xlQ29sb3VyOiBERUZFTkRFUl9DT0xPVVJcbn1cblxuLy8gNUFUQiBEZWZlbmRlcnNcbmV4cG9ydCBjb25zdCBMV0I6IFBvc2l0aW9uID0ge1xuICAgIHg6IDI3MixcbiAgICB5OiAxMjQ3LFxuICAgIGNpcmNsZUNvbG91cjogREVGRU5ERVJfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgTENCOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA0NzEsXG4gICAgeTogMTQ0NyxcbiAgICBjaXJjbGVDb2xvdXI6IERFRkVOREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IENDQjogUG9zaXRpb24gPSB7XG4gICAgeDogNzcyLFxuICAgIHk6IDE0MjAsXG4gICAgY2lyY2xlQ29sb3VyOiBERUZFTkRFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBSQ0I6IFBvc2l0aW9uID0ge1xuICAgIHg6IDEwNzAsXG4gICAgeTogMTQ0NyxcbiAgICBjaXJjbGVDb2xvdXI6IERFRkVOREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IFJXQjogUG9zaXRpb24gPSB7XG4gICAgeDogMTI3MixcbiAgICB5OiAxMjQ3LFxuICAgIGNpcmNsZUNvbG91cjogREVGRU5ERVJfQ09MT1VSXG59XG5cbi8vIE1JREZJRUxERVJTXG5leHBvcnQgY29uc3QgQ0RNOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA3NzIsXG4gICAgeTogMTA4MyxcbiAgICBjaXJjbGVDb2xvdXI6IE1JREZJRUxERVJfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgTERNOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA1NTEuOCxcbiAgICB5OiAxMDgzLFxuICAgIGNpcmNsZUNvbG91cjogTUlERklFTERFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBSRE06IFBvc2l0aW9uID0ge1xuICAgIHg6IDk4OC44LFxuICAgIHk6IDEwODMsXG4gICAgY2lyY2xlQ29sb3VyOiBNSURGSUVMREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IENNTDogUG9zaXRpb24gPSB7XG4gICAgeDogNTcxLFxuICAgIHk6IDk3NixcbiAgICBjaXJjbGVDb2xvdXI6IE1JREZJRUxERVJfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgQ01SOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA5NzAsXG4gICAgeTogOTc2LFxuICAgIGNpcmNsZUNvbG91cjogTUlERklFTERFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBMQ006IFBvc2l0aW9uID0ge1xuICAgIHg6IDQxNyxcbiAgICB5OiA4ODMsXG4gICAgY2lyY2xlQ29sb3VyOiBNSURGSUVMREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IFJDTTogUG9zaXRpb24gPSB7XG4gICAgeDogMTE1MixcbiAgICB5OiA4ODMsXG4gICAgY2lyY2xlQ29sb3VyOiBNSURGSUVMREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IENBTTogUG9zaXRpb24gPSB7XG4gICAgeDogNzcyLFxuICAgIHk6IDU4MC45LFxuICAgIGNpcmNsZUNvbG91cjogTUlERklFTERFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBMQU06IFBvc2l0aW9uID0ge1xuICAgIHg6IDMxOS4xLFxuICAgIHk6IDU4MC45LFxuICAgIGNpcmNsZUNvbG91cjogTUlERklFTERFUl9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBSQU06IFBvc2l0aW9uID0ge1xuICAgIHg6IDEyMTEuOCxcbiAgICB5OiA1ODAuOSxcbiAgICBjaXJjbGVDb2xvdXI6IE1JREZJRUxERVJfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgTE06IFBvc2l0aW9uID0ge1xuICAgIHg6IDMyOCxcbiAgICB5OiA3NzUsXG4gICAgY2lyY2xlQ29sb3VyOiBNSURGSUVMREVSX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IFJNOiBQb3NpdGlvbiA9IHtcbiAgICB4OiAxMjE2LFxuICAgIHk6IDc3NSxcbiAgICBjaXJjbGVDb2xvdXI6IE1JREZJRUxERVJfQ09MT1VSXG59XG5cbi8vIEZPUldBUkRTXG5leHBvcnQgY29uc3QgUlc6IFBvc2l0aW9uID0ge1xuICAgIHg6IDEyNTgsXG4gICAgeTogMzYzLFxuICAgIGNpcmNsZUNvbG91cjogRk9SV0FSRF9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBMVzogUG9zaXRpb24gPSB7XG4gICAgeDogMjgyLFxuICAgIHk6IDM2MyxcbiAgICBjaXJjbGVDb2xvdXI6IEZPUldBUkRfQ09MT1VSXG59XG5leHBvcnQgY29uc3QgTFM6IFBvc2l0aW9uID0ge1xuICAgIHg6IDU4OCxcbiAgICB5OiAyNjAsXG4gICAgY2lyY2xlQ29sb3VyOiBGT1JXQVJEX0NPTE9VUlxufVxuZXhwb3J0IGNvbnN0IFJTOiBQb3NpdGlvbiA9IHtcbiAgICB4OiA5NjIsXG4gICAgeTogMjYwLFxuICAgIGNpcmNsZUNvbG91cjogRk9SV0FSRF9DT0xPVVJcbn1cbmV4cG9ydCBjb25zdCBTVDogUG9zaXRpb24gPSB7XG4gICAgeDogNzcyLFxuICAgIHk6IDE5MyxcbiAgICBjaXJjbGVDb2xvdXI6IEZPUldBUkRfQ09MT1VSXG59IiwgImltcG9ydCB7IEdLLCBMQiwgQ0JMLCBDQlIsIFJCLCBDRE0sIExDTSwgUkNNLCBMVywgUlcsIFNULCBMRE0sIFJETSwgTEFNLCBDQU0sIFJBTSwgTFMsIFJTLCBSTSwgTE0sIExXQiwgUldCLCBDQ0IsIExDQiwgUkNCLCBDTUwsIENNUiB9IGZyb20gXCIuL3Bvc2l0aW9uXCI7XG5pbXBvcnQgeyBGb3JtYXRpb24gfSBmcm9tIFwiLi90cy9pbnRlcmZhY2VzXCI7XG5cbmV4cG9ydCBjb25zdCBmb3JtYXRpb25zOiBGb3JtYXRpb25bXSA9IFtcbiAgICB7XG4gICAgICAgIG5hbWU6ICc0NDInLFxuICAgICAgICBwb3NpdGlvbnM6IFtHSywgTEIsIENCTCwgQ0JSLCBSQiwgTE0sIENNTCwgQ01SLCBSTSwgTFMsIFJTXVxuICAgIH0sXG4gICAge1xuICAgICAgICBuYW1lOiAnNDMzJyxcbiAgICAgICAgcG9zaXRpb25zOiBbR0ssIExCLCBDQkwsIENCUiwgUkIsIExDTSwgQ0RNLCBSQ00sIExXLCBTVCwgUlddXG4gICAgfSxcbiAgICB7XG4gICAgICAgIG5hbWU6ICc0MjMxJyxcbiAgICAgICAgcG9zaXRpb25zOiBbR0ssIExCLCBDQkwsIENCUiwgUkIsIExETSwgUkRNLCBMQU0sIENBTSwgUkFNLCBTVF1cbiAgICB9LFxuICAgIHtcbiAgICAgICAgbmFtZTogJzQ0Mi1kaWFtb25kJyxcbiAgICAgICAgcG9zaXRpb25zOiBbR0ssIExCLCBDQkwsIENCUiwgUkIsIENETSwgTE0sIFJNLCBDQU0sIExTLCBSU11cbiAgICB9LFxuICAgIHtcbiAgICAgICAgbmFtZTogJzU0MScsXG4gICAgICAgIHBvc2l0aW9uczogW0dLLCBMV0IsIExDQiwgQ0NCLCBSQ0IsIFJXQiwgTE0sIENNTCwgQ01SLCBSTSwgU1RdXG4gICAgfSxcbiAgICB7XG4gICAgICAgIG5hbWU6ICc1MjMnLFxuICAgICAgICBwb3NpdGlvbnM6IFtHSywgTFdCLCBMQ0IsIENDQiwgUkNCLCBSV0IsIENNTCwgQ01SLCBMVywgU1QsIFJXXVxuICAgIH0sXG4gICAge1xuICAgICAgICBuYW1lOiAnNTMyJyxcbiAgICAgICAgcG9zaXRpb25zOiBbR0ssIExXQiwgTENCLCBDQ0IsIFJDQiwgUldCLCBMQ00sIENETSwgUkNNLCBMUywgUlNdXG4gICAgfSxcbiAgICB7XG4gICAgICAgIG5hbWU6ICczNDMnLFxuICAgICAgICBwb3NpdGlvbnM6IFtHSywgTENCLCBDQ0IsIFJDQiwgTE0sIENNTCwgQ01SLCBSTSwgTFcsIFNULCBSV11cbiAgICB9LFxuICAgIHtcbiAgICAgICAgbmFtZTogJzM1MicsXG4gICAgICAgIHBvc2l0aW9uczogW0dLLCBMQ0IsIENDQiwgUkNCLCBMTSwgTERNLCBSRE0sIFJNLCBDQU0sIExTLCBSU11cbiAgICB9XG5dOyIsICJpbXBvcnQgeyBQb3NpdGlvbiB9IGZyb20gXCIuL3RzL2ludGVyZmFjZXNcIjtcblxuY29uc3QgTEFCRUxfT0ZGU0VUX1ggPSAtNjk7XG5jb25zdCBMQUJFTF9PRkZTRVRfWSA9IDE0MDtcblxuZnVuY3Rpb24gYnVpbGRMYWJlbHMocG9zaXRpb25zOiBQb3NpdGlvbltdLCBwbGF5ZXJzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBsZXQgbGFiZWxzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspe1xuICAgICAgICBsYWJlbHNbaV0gPSBidWlsZExhYmVsKHBvc2l0aW9uc1tpXSwgcGxheWVyc1tpXSk7XG4gICAgfVxuICAgIHJldHVybiBsYWJlbHM7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQ2lyY2xlcyhwb3NpdGlvbnM6IFBvc2l0aW9uW10pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHBvc2l0aW9ucy5tYXAoKHBvc2l0aW9uKSA9PiBidWlsZENpcmNsZShwb3NpdGlvbikpO1xufVxuXG5mdW5jdGlvbiBidWlsZExhYmVsKHBvc2l0aW9uOiBQb3NpdGlvbiwgcGxheWVyTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYDx0c3BhbiB4PVwiJHtwb3NpdGlvbi54ICsgTEFCRUxfT0ZGU0VUX1h9XCIgeT1cIiR7cG9zaXRpb24ueSArIExBQkVMX09GRlNFVF9ZfVwiPiR7cGxheWVyTmFtZX08L3RzcGFuPmA7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQ2lyY2xlKHBvc2l0aW9uOiBQb3NpdGlvbik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGA8dXNlIHhsaW5rOmhyZWY9XCIjcG9zXCIgeD1cIiR7cG9zaXRpb24ueH1cIiB5PVwiJHtwb3NpdGlvbi55fVwiIGZpbGw9XCIke3Bvc2l0aW9uLmNpcmNsZUNvbG91cn1cIi8+YFxufVxuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRTdmcocG9zaXRpb25zOiBQb3NpdGlvbltdLCBwbGF5ZXJzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgPHN2ZyB4bWxuczp4bGluaz1cImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiMTAwJVwiIHZpZXdCb3g9XCIwIDAgMTM4NCAxOTIwXCIgcHJlc2VydmVBc3BlY3RSYXRpbz1cInhNaW5ZTWluXCIgdmVyc2lvbj1cIjEuMVwiPlxuICAgICAgICA8cGF0aCBkPVwiTTQ0LjUsMzQuNWgxMzEydjE4NTZoLTEzMTJ6XCIgZmlsbD1cIiMzOTNcIi8+XG4gICAgICAgIDxwYXRoIGQ9XCJNNjksNTloMTI2NC41djE4MDguNWgtMTI2NC41ek02OSw5NjRoODIwLjZhMTk3LjEsMTk3LjEgMCAwIDEtMzk0LjIsMGExOTcuMSwxOTcuMSAwIDAgMSAzOTQuMiwwaDQ0NE01MTUsNTl2MTczaDM3My42di0xNzNNMzMxLDU5djM0N2g3NDB2LTM0N001MTUsMTg2OHYtMTczaDM3My42djE3M00zMzEsMTg2OHYtMzQ3aDc0MHYzNDdcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cIiNmZmZcIiBzdHJva2Utd2lkdGg9XCI0XCIvPlxuICAgICAgICA8ZGVmcz5cbiAgICAgICAgPHBhdGggZD1cIm0wLDBhNzIsNzIgMCAwIDEtMTQ0LDAgNzIsNzIgMCAxIDEgMTQ0LDB6XCIgaWQ9XCJwb3NcIi8+XG4gICAgICAgIDwvZGVmcz5cblxuICAgICAgICA8ZyBzdHJva2U9XCIjMDAwXCIgc3Ryb2tlLXdpZHRoPVwiNlwiPlxuICAgICAgICAgICAgJHtidWlsZENpcmNsZXMocG9zaXRpb25zKS5qb2luKCdcXG4nKX1cbiAgICAgICAgPC9nPlxuXG4gICAgICAgIDx0ZXh0IHN0eWxlPVwiZm9udC1zaXplOjU2cHg7dGV4dC1hbGlnbjpjZW50ZXI7bGluZS1oZWlnaHQ6MTI1JTt0ZXh0LWFuY2hvcjptaWRkbGU7ZmlsbDojMDAwMDAwO2ZvbnQtZmFtaWx5OkJpdHN0cmVhbSBWZXJhIFNhbnNcIiB4PVwiNzA5LjRcIiB5PVwiMTg3MS42XCIgbGluZXNwYWNpbmc9XCIxMjUlXCI+XG4gICAgICAgICAgICAke2J1aWxkTGFiZWxzKHBvc2l0aW9ucywgcGxheWVycykuam9pbignXFxuJyl9XG4gICAgICAgIDwvdGV4dD5cbiAgICAgICAgPC9zdmc+YFxufSJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTs7O0FDQU8sSUFBTSxnQkFBZ0I7QUFDdEIsSUFBTSxrQkFBa0I7QUFDeEIsSUFBTSxvQkFBb0I7QUFDMUIsSUFBTSxpQkFBaUI7OztBQ0d2QixJQUFNLEtBQWU7QUFBQSxFQUN4QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFNWCxJQUFNLEtBQWU7QUFBQSxFQUN4QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FBRVgsSUFBTSxNQUFnQjtBQUFBLEVBQ3pCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUVYLElBQU0sS0FBZTtBQUFBLEVBQ3hCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUlYLElBQU0sTUFBZ0I7QUFBQSxFQUN6QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FBRVgsSUFBTSxNQUFnQjtBQUFBLEVBQ3pCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUVYLElBQU0sTUFBZ0I7QUFBQSxFQUN6QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FBSVgsSUFBTSxNQUFnQjtBQUFBLEVBQ3pCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUVYLElBQU0sTUFBZ0I7QUFBQSxFQUN6QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FBRVgsSUFBTSxNQUFnQjtBQUFBLEVBQ3pCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUVYLElBQU0sTUFBZ0I7QUFBQSxFQUN6QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FBRVgsSUFBTSxNQUFnQjtBQUFBLEVBQ3pCLEdBQUc7QUFBQSxFQUNILEdBQUc7QUFBQSxFQUNILGNBQWM7QUFBQTtBQUVYLElBQU0sTUFBZ0I7QUFBQSxFQUN6QixHQUFHO0FBQUEsRUFDSCxHQUFHO0FBQUEsRUFDSCxjQUFjO0FBQUE7QUFFWCxJQUFNLE1BQWdCO0FBQUEsRUFDekIsR0FBRztBQUFBLEVBQ0gsR0FBRztBQUFBLEVBQ0gsY0FBYztBQUFBO0FB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
diff --git a/.obsidian/plugins/obsidian-lineup-builder/manifest.json b/.obsidian/plugins/obsidian-lineup-builder/manifest.json
new file mode 100644
index 00000000..e53a0525
--- /dev/null
+++ b/.obsidian/plugins/obsidian-lineup-builder/manifest.json
@@ -0,0 +1 @@
+{"id":"obsidian-lineup-builder","name":"Lineup Builder","version":"1.0.0","minAppVersion":"0.12.0","description":"Build football lineups in Obsidian.","author":"James Fallon","authorUrl":"https://github.com/James-Fallon","isDesktopOnly":false}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian42-brat/data.json b/.obsidian/plugins/obsidian42-brat/data.json
index 82eaa9f9..61981d2a 100644
--- a/.obsidian/plugins/obsidian42-brat/data.json
+++ b/.obsidian/plugins/obsidian42-brat/data.json
@@ -1,5 +1,7 @@
{
"pluginList": [
+ "James-Fallon/obsidian-lineup-builder",
+ "kinabalu/obsidian-crypto-lookup",
"joethei/obsidian-rss"
],
"updateAtStartup": false
diff --git a/.obsidian/workspace b/.obsidian/workspace
index 3dfbf0e9..8688b307 100644
--- a/.obsidian/workspace
+++ b/.obsidian/workspace
@@ -9,7 +9,7 @@
"state": {
"type": "markdown",
"state": {
- "file": "01.01 Life Orga/Finances.md",
+ "file": "03.03 Food & Wine/!!Wine.md",
"mode": "preview"
}
}
@@ -68,7 +68,7 @@
"state": {
"type": "backlink",
"state": {
- "file": "01.01 Life Orga/Finances.md",
+ "file": "03.03 Food & Wine/!!Wine.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@@ -107,15 +107,15 @@
},
"active": "c252d60ecbda6bb3",
"lastOpenFiles": [
- "01.01 Life Orga/Finances.md",
- "06.02 Investments/Crypto Tasks.md",
- "01.01 Life Orga/IT & Computer.md",
- "05.02 Networks/VPS Console Dialogue.md",
+ "03.03 Food & Wine/!!Wine.md",
+ "03.03 Food & Wine/!!Coffee.md",
+ "03.03 Food & Wine/Maison Olivier Chanzy Chassagne-Montrachet 1er Cru.md",
+ "03.03 Food & Wine/Brazil Assodantas.md",
+ "03.03 Food & Wine/!!Wine 1.md",
+ "00.01 Admin/Templates/Template Wine 1.md",
+ "05.02 Networks/Server VPN.md",
"05.02 Networks/Server Cloud.md",
- "05.01 Computer setup/Applications.md",
- "05.02 Networks/mfxm Website Scope.md",
- "05.02 Networks/Server Tools.md",
- "01.01 Life Orga/Personal projects.md",
- "01.01 Life Orga/Lifestyle.md"
+ "00.01 Admin/Test sheet.md",
+ "01.01 Life Orga/Finances.md"
]
}
\ No newline at end of file
diff --git a/00.01 Admin/Templates/Template Coffee.md b/00.01 Admin/Templates/Template Coffee.md
new file mode 100644
index 00000000..c8dca817
--- /dev/null
+++ b/00.01 Admin/Templates/Template Coffee.md
@@ -0,0 +1,77 @@
+---
+
+Tag: ["Crisp", "Powerful", "Apricot", "Peach", "Mango", "Oak"]
+Date: <% tp.date.now("YYYY-MM-DD") %>
+DocType: "Coffee"
+Hierarchy: "NonRoot"
+TimeStamp:
+location:
+CollapseMetaTable: Yes
+Source:
+cssclass: recipeTable
+Coffee:
+ Brand:
+ Type:
+ Roast:
+ Strength:
+ Country:
+
+---
+
+parent::
+
+---
+
+
+
+```button
+name Save
+type command
+action Save current file
+id Save
+```
+^button-<% tp.file.title %>NSave
+
+# <% tp.file.title %>
+
+
+
+```ad-abstract
+title: Summary
+collapse: open
+Description
+```
+
+
+
+```toc
+style: number
+```
+
+
+
+---
+
+
+
+### Summary
+
+
+
+| |
+|-|-
+| **Coffee type**: | `$=dv.current().Coffee.Type`
+| **Strength**: | `$=dv.current().Coffee.Strength`
+| **Country**: | `$=dv.current().Coffee.Country`
+| **Roast**: | `$=dv.current().Coffee.Roast`
+| **Brand**: | `$=dv.current().Coffee.Brand`
+
+
+
+---
+
+
+
+### Notes
+
+
\ No newline at end of file
diff --git a/00.01 Admin/Test sheet.md b/00.01 Admin/Test sheet.md
index ae467136..6be3f812 100644
--- a/00.01 Admin/Test sheet.md
+++ b/00.01 Admin/Test sheet.md
@@ -9,6 +9,11 @@ ChildrenType: ["Note", "Task", "Recipe"]
+```lineup
+formation: 433
+players: Donnarumma,Bernat,Marquinhos,Kimpembe,Hakimi,Villeneuve,Verratti,St Hilaire,MBappe,Solanet,Messi
+```
+
```dataviewjs
const {shoppingFunc} = customJS
shoppingFunc.getItems2Change({app: app, dv: dv, luxon: luxon, that:this, theme: "to0"})
diff --git a/00.01 Admin/dv-views/GlobalFunc.js b/00.01 Admin/dv-views/GlobalFunc.js
index 5e60c7c4..2284c2af 100644
--- a/00.01 Admin/dv-views/GlobalFunc.js
+++ b/00.01 Admin/dv-views/GlobalFunc.js
@@ -302,6 +302,16 @@ class globalFunc {
break;
+ case 'Coffee':
+
+ switch(TableT) {
+ default:
+ TempData = ["Name", "Coffee type", "Strength", "Country", "Roast", "Notes", "Brand"]
+ break;
+ }
+
+ break;
+
}
return TempData
@@ -394,7 +404,17 @@ class globalFunc {
TempData = [p.file.link, this.GetPoint(p, DataT, "type"), this.GetPoint(p, DataT, "vintage"), this.toEmoji(this.GetPoint(p, DataT, "country")), this.GetPoint(p, DataT, "subregion"), this.GetPoint(p, DataT, "appellation")]
break;
case 'extended':
- TempData = [p.file.link, this.GetPoint(p, DataT, "type"), this.GetPoint(p, DataT, "vintage"), this.toEmoji(this.GetPoint(p, DataT, "country")), this.GetPoint(p, DataT, "region"), this.GetPoint(p, DataT, "subregion"), this.GetPoint(p, DataT, "appellation"), this.GetPoint(p, DataT, "vineyard"), this.GetPoint(p, DataT, "variety"), this.GetPoint(p, DataT, "producer")]
+ TempData = [p.file.link, this.GetPoint(p, DataT, "type"), this.GetPoint(p, DataT, "vintage"), this.toEmoji(this.GetPoint(p, DataT, "country")), this.GetPoint(p, DataT, "region"), this.GetPoint(p, DataT, "subregion"), this.GetPoint(p, DataT, "appellation"), this.GetPoint(p, DataT, "vineyard"), this.GetPoint(p, DataT, "varietal"), this.GetPoint(p, DataT, "producer")]
+ break;
+ }
+
+ break;
+
+ case 'Coffee':
+
+ switch(TableT) {
+ default:
+ TempData = [p.file.link, this.GetPoint(p, DataT, "type"), this.GetPoint(p, DataT, "strength"), this.toEmoji(this.GetPoint(p, DataT, "country")), this.GetPoint(p, DataT, "roast"), this.GetPoint(p, "main", "tag"), this.GetPoint(p, DataT, "brand")]
break;
}
@@ -492,6 +512,9 @@ class globalFunc {
case 'Nordics':
tempresult = "πΈπͺ"
break;
+ case 'Brazil':
+ tempresult = "π§π·"
+ break;
case 'Pub':
tempresult = "πΊ"
break;
@@ -527,6 +550,7 @@ class globalFunc {
case 'prodtype':
case 'disktype':
case 'winetype':
+ case 'coffeetype':
result = this.GetPoint(pobj, DocType, "type")
break;
case 'style':
@@ -643,6 +667,15 @@ class globalFunc {
case 'designation':
result = this.GetPoint(pobj, DocType, "designation")
break;
+ case 'brand':
+ result = this.GetPoint(pobj, DocType, "brand")
+ break;
+ case 'roast':
+ result = this.GetPoint(pobj, DocType, "roast")
+ break;
+ case 'strength':
+ result = this.GetPoint(pobj, DocType, "strength")
+ break;
}
return result
}
@@ -950,6 +983,28 @@ class globalFunc {
}
break;
+
+ case 'Coffee':
+
+ switch(dPoint) {
+ case 'brand':
+ result = pobj.Coffee.Brand
+ break;
+ case 'roast':
+ result = pobj.Coffee.Roast
+ break;
+ case 'country':
+ result = pobj.Coffee.Country
+ break;
+ case 'type':
+ result = pobj.Coffee.Type
+ break;
+ case 'strength':
+ result = pobj.Coffee.Strength
+ break;
+ }
+
+ break;
}
return result
diff --git a/00.01 Admin/dv-views/print_coffeesearch.js b/00.01 Admin/dv-views/print_coffeesearch.js
new file mode 100644
index 00000000..5f74736f
--- /dev/null
+++ b/00.01 Admin/dv-views/print_coffeesearch.js
@@ -0,0 +1,4 @@
+const {globalFunc} = customJS
+let {dateadded, coffeetype, brand, roast, strength, theme, country} = input;
+
+dv.el('t', "π search terms: \nβ’ " + globalFunc.buildToPrint([dateadded, coffeetype, brand, roast, strength, theme, country], ["note written", "type of coffee", "brand", "roast", "strength", "notes", "country"], "\nβ’ "));
diff --git a/00.01 Admin/dv-views/query_coffee.js b/00.01 Admin/dv-views/query_coffee.js
new file mode 100644
index 00000000..729af10f
--- /dev/null
+++ b/00.01 Admin/dv-views/query_coffee.js
@@ -0,0 +1,6 @@
+let {dateadded, coffeetype, brand, roast, strength, theme, country} = input;
+const {globalFunc} = customJS
+const DataType = 'Coffee'
+//let templacetype = globalFunc.Get1stArg(placetype)
+
+return globalFunc.getTable(dv, DataType, ["note written", "type of coffee", "brand", "roast", "strength", "notes", "country"], [dateadded, coffeetype, brand, roast, strength, theme, country], 0)
diff --git a/03.03 Food & Wine/!!Coffee.md b/03.03 Food & Wine/!!Coffee.md
new file mode 100644
index 00000000..9b68263f
--- /dev/null
+++ b/03.03 Food & Wine/!!Coffee.md
@@ -0,0 +1,167 @@
+---
+
+QPDate:
+QPcoffeetype: Arabica
+QProast:
+QPstrengtg:
+QPbrand:
+QPtheme:
+QPcountry:
+cssclass: recipeTable
+Alias: ["Coffee"]
+Tag: ["Morning"]
+Date: 2021-10-26
+DocType: "Personal"
+ChildrenType: ["Product", "Coffee"]
+Hierarchy: "Root"
+location:
+CollapseMetaTable: Yes
+
+---
+
+Parent:: [[Lifestyle]]
+
+---
+
+ ^Top
+
+
+
+```button
+name Create Note
+type append template
+action NewFile
+id CreateNote
+```
+^button-CoffeeNewNote
+
+
+
+```button
+name Save
+type command
+action Save current file
+id Save
+```
+^button-CoffeeSave
+
+
+
+# Folder map
+
+
+
+```ad-abstract
+title: Summary
+collapse: open
+This note enables to navigate in the Coffee section and find any Note in this Vault by Note or Tag
+```
+
+
+
+```toc
+style: number
+```
+
+
+
+---
+
+
+
+### Search
+[[#^Top|TOP]]
+
+
+```button
+name Search Coffees
+type command
+action MetaEdit: Run MetaEdit
+id EditMetaData
+```
+
+
+
+```dataviewjs
+dv.view("00.01 Admin/dv-views/print_coffeesearch", {dateadded: dv.current().QPDate, coffeetype: dv.current().QPcoffeetype, roast: dv.current().QProast, brand: dv.current().QPbrand, strength: dv.current().QPstrength, theme: dv.current().QPtheme, country: dv.current().QPcountry})
+```
+
+
+
+```dataviewjs
+dv.view("00.01 Admin/dv-views/query_coffee", {dateadded: dv.current().QPDate, type: dv.current().QPcoffeetype, roast: dv.current().QProast, brand: dv.current().QPbrand, strength: dv.current().QPstrength, theme: dv.current().QPtheme, country: dv.current().QPcountry})
+```
+
+
+
+---
+
+
+
+### Navigation
+
+
+
+#### By type
+[[#^Top|TOP]]
+##### Arabica
+
+
+
+```dataviewjs
+dv.view("00.01 Admin/dv-views/query_coffee", {type: "Arabica"})
+```
+
+
+
+---
+
+
+
+#### By Geography
+[[#^Top|TOP]]
+##### Brazil
+
+
+
+```dataviewjs
+dv.view("00.01 Admin/dv-views/query_coffee", {country: "Brazil"})
+```
+
+
+
+---
+
+
+
+### Tag Navigation
+[[#^Top|TOP]]
+
+
+```dataview
+ Table without id tags as "Tags" From "03.03 Food & Wine"
+ Where DocType = "Coffee"
+ Flatten file.tags as tags
+ Group by tags
+```
+
+
+
+---
+
+
+
+### High Level tasks
+[[#^Top|TOP]]
+
+
+```tasks
+not done
+path includes 03.03
+sort by due
+hide backlink
+hide task count
+```
+
+
+
\ No newline at end of file
diff --git a/03.03 Food & Wine/Brazil Assodantas.md b/03.03 Food & Wine/Brazil Assodantas.md
new file mode 100644
index 00000000..cae66e71
--- /dev/null
+++ b/03.03 Food & Wine/Brazil Assodantas.md
@@ -0,0 +1,77 @@
+---
+
+Tag: ["Nutty", "Cocoa", "Hazelnut", "Fruity"]
+Date: 2021-10-31
+DocType: "Coffee"
+Hierarchy: "NonRoot"
+TimeStamp:
+location:
+CollapseMetaTable: Yes
+Source:
+cssclass: recipeTable
+Coffee:
+ Brand: "Waitrose"
+ Type: "Arabica"
+ Roast: "Medium-dark"
+ Strength: 4
+ Country: Brazil
+
+---
+
+parent:: [[!!Coffee|Coffee]]
+
+---
+
+
+
+```button
+name Save
+type command
+action Save current file
+id Save
+```
+^button-BrazilAssodantasNSave
+
+# Brazil Assodantas
+
+
+
+```ad-abstract
+title: Summary
+collapse: open
+Description
+```
+
+
+
+```toc
+style: number
+```
+
+
+
+---
+
+
+
+### Summary
+
+
+
+| |
+|-|-
+| **Coffee type**: | `$=dv.current().Coffee.Type`
+| **Strength**: | `$=dv.current().Coffee.Strength`
+| **Country**: | `$=dv.current().Coffee.Country`
+| **Roast**: | `$=dv.current().Coffee.Roast`
+| **Brand**: | `$=dv.current().Coffee.Brand`
+
+
+
+---
+
+
+
+### Notes
+
+
\ No newline at end of file