Jump to content

User:Suffusion of Yellow/fdb-worker.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
/* jshint esversion: 11, esnext: false */
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
var __webpack_exports__ = {};

;// CONCATENATED MODULE: ./src/parserdata.js
const parserData = {
	functions: "bool|ccnorm_contains_all|ccnorm_contains_any|ccnorm|contains_all|contains_any|count|equals_to_any|float|get_matches|int|ip_in_range|ip_in_ranges|lcase|length|norm|rcount|rescape|rmdoubles|rmspecials|rmwhitespace|sanitize|set|set_var|specialratio|string|strlen|strpos|str_replace|str_replace_regexp|substr|ucase",
	operators: "==?=?|!==?|!=|\\+|-|/|%|\\*\\*?|<=?|>=?|\\(|\\)|\\[|\\]|&|\\||\\^|!|:=?|\\?|;|,",
	keywords: "contains|in|irlike|like|matches|regex|rlike|if|then|else|end",
	variables: "accountname|action|added_lines|added_lines_pst|added_links|all_links|edit_delta|edit_diff|edit_diff_pst|file_bits_per_channel|file_height|file_mediatype|file_mime|file_sha1|file_size|file_width|global_user_editcount|global_user_groups|moved_from_age|moved_from_first_contributor|moved_from_id|moved_from_last_edit_age|moved_from_namespace|moved_from_prefixedtitle|moved_from_recent_contributors|moved_from_restrictions_create|moved_from_restrictions_edit|moved_from_restrictions_move|moved_from_restrictions_upload|moved_from_title|moved_to_age|moved_to_first_contributor|moved_to_id|moved_to_last_edit_age|moved_to_namespace|moved_to_prefixedtitle|moved_to_recent_contributors|moved_to_restrictions_create|moved_to_restrictions_edit|moved_to_restrictions_move|moved_to_restrictions_upload|moved_to_title|new_content_model|new_html|new_pst|new_size|new_text|new_wikitext|oauth_consumer|old_content_model|old_links|old_size|old_wikitext|page_age|page_first_contributor|page_id|page_last_edit_age|page_namespace|page_prefixedtitle|page_recent_contributors|page_restrictions_create|page_restrictions_edit|page_restrictions_move|page_restrictions_upload|page_title|removed_lines|removed_links|summary|timestamp|tor_exit_node|user_age|user_app|user_blocked|user_editcount|user_emailconfirm|user_groups|user_mobile|user_name|user_rights|user_type|wiki_language|wiki_name",
	deprecated: "article_articleid|article_first_contributor|article_namespace|article_prefixedtext|article_recent_contributors|article_restrictions_create|article_restrictions_edit|article_restrictions_move|article_restrictions_upload|article_text|moved_from_articleid|moved_from_prefixedtext|moved_from_text|moved_to_articleid|moved_to_prefixedtext|moved_to_text",
	disabled: "minor_edit|old_html|old_text"
};

;// CONCATENATED MODULE: ./src/parse.js


class ParseError {
	constructor(message, start, end) {
		this.message = message;
		this.start = start;
		this.end = end;
	}
}

class ParseTree {
	constructor(filter) {
		if (typeof filter == 'object') {
			Object.assign(this, filter);
			return;
		}

		this.filter = filter;

		this.tokens = this.tokenize();

		this.pos = 0;
		this.tree = this.parseStatements();
		this.need("EOF");

		delete this.pos;
	}

	extractString(token, str) {
		const UTF8 = /^\\x([0-9A-F]{2})(?:\\x([89AB][0-9A-F]))?(?:\\x([89AB][0-9A-F]))?(?:\\x([89AB][0-9A-F]))?/i;
		let out = "", td = new TextDecoder();
		let strmap = [], t, p = 1, q = 0, cur;

		while (p < str.length - 1) {
			let in_size = 1;
			let out_size = 1;

			if (str[p] == '\\') {
				in_size = 2;
				if (str[p + 1] == 'n')
					out += '\n';
				else if (str[p + 1] == 'r')
					out += '\r';
				else if (str[p + 1] == 't')
					out += '\t';
				else if (str[p + 1] == str[0] || str[p + 1] == '\\')
					out += str[p + 1];
				else if (str[p + 1] == 'x' && (t = str.slice(p).match(UTF8))) {
					let bytes = t.slice(1)
						.filter(x => x !== undefined)
						.map(x => parseInt(x, 16));
					let chr = td.decode(new Uint8Array(bytes));

					out += chr;
					out_size = chr.length;
					in_size = t[0].length;
				} else {
					out += "\\" + str[p + 1];
					out_size = 2;
				}
			} else {
				out += str[p];
			}

			if (in_size == out_size && cur && cur[1] - cur[0] == cur[3] - cur[2]) {
				cur[1] += in_size;
				cur[3] += out_size;
			} else {
				cur = [p + token.start, p + token.start + in_size, q, q + out_size];
				strmap.push(cur);
			}

			p += in_size;
			q += out_size;
		}

		token.val = out;
		token.strmap = strmap;
	}

	tokenize() {
		const re = new RegExp(
			("(?<bool>(?:true|false)\\b)" +
			 "|(?<null>null\\b)" +
			 `|(?<keyword>(?:${parserData.keywords})\\b)` +
			 `|(?<function>(?:${parserData.functions})\\b)` +
			 `|(?<constant>(?:${parserData.variables}|${parserData.deprecated}|${parserData.disabled})\\b)` +
			 "|(?<whitespace>\\s+)" +
			 "|(?<comment>/\\*.*?\\*/)" +
			 `|(?<operator>(?:${parserData.operators}))` +
			 "|(?<float>[0-9]*\\.[0-9]+\\b|[0-9]+\\.)" +
			 "|(?<hex>0x[0-9A-Fa-f]+)\\b" +
			 "|(?<oct>0o[0-7]+)\\b" +
			 "|(?<bin>0b[01]+)\\b" +
			 "|(?<dec>[0-9]+)\\b" +
			 "|(?<var>[A-Za-z0-9_]+)" +
			 "|(?<string>\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')" +
			 "|(?<end>$)"
			), "usy");

		const alias = Object.assign(Object.create(null), {
			"=": "==",
			"set_var": "set",
			"strlen": "length",
			"regex": "rlike",
			"matches": "like",
			"article_articleid": "page_id",
			"article_first_contributor": "page_first_contributor",
			"article_namespace": "page_namespace",
			"article_prefixedtext": "page_prefixedtitle",
			"article_recent_contributors": "page_recent_contributors",
			"article_restrictions_create": "page_restrictions_create",
			"article_restrictions_edit": "page_restrictions_edit",
			"article_restrictions_move": "page_restrictions_move",
			"article_restrictions_upload": "page_restrictions_upload",
			"article_text": "page_title",
			"moved_from_articleid": "move_from_id",
			"moved_from_prefxedtext": "moved_from_prefixedtitle",
			"moved_from_text": "moved_from_title",
			"moved_to_prefxedtext": "moved_to_prefixedtitle",
			"moved_to_text": "moved_to_title"
		});

		let tokens = [], match, pos = 0;

		while ((match = re.exec(this.filter)) !== null) {
			let type = Object.keys(match.groups).filter(x => match.groups[x] !== undefined)[0];
			let str = match[0];
			let token = {
				start: pos,
				end: pos + str.length
			};

			pos += str.length;

			switch (type) {
			case 'whitespace':
			case 'comment':
				continue;
			case 'null':
				token.tok = 'literal';
				token.val = null;
				break;
			case 'bool':
				token.tok = 'literal';
				token.val = (str == 'true');
				break;
			case 'function':
				token.tok = 'function';
				token.val = alias[str] || str;
				break;
			case 'constant':
				token.tok = 'constant';
				token.val = alias[str.toLowerCase()] || str.toLowerCase();
				break;
			case 'var':
				token.tok = 'variable';
				token.val = str.toLowerCase();
				break;
			case 'operator':
			case 'keyword':
				token.tok = alias[str] || str;
				break;
			case 'float':
				token.tok = 'literal';
				token.val = parseFloat(str);
				break;
			case 'dec':
				token.tok = 'literal';
				token.val = parseInt(str, 10);
				break;
			case 'hex':
			case 'oct':
			case 'bin':
				token.tok = 'literal';
				token.val = parseInt(str.slice(2), str[1] == 'x' ? 16 : str[1] == 'o' ? 8 : 2);
				break;
			case 'string':
				token.tok = 'literal';
				this.extractString(token, str);

				break;
			case "end":
				token.tok = "EOF";
				break;
			}

			tokens.push(token);
			if (token.tok == "EOF")
				return tokens;
		}

		throw new ParseError(`Unexpected character "${this.filter[pos]}"`, pos, pos + 1);
	}

	peek(...args) {
		for (let t of args)
			if (this.tokens[this.pos].tok == t)
				return this.tokens[this.pos];

		return null;
	}

	want(...args) {
		let r = this.peek(...args);

		if (r != null)
			this.pos++;

		return r;
	}

	need(...args) {
		let r = this.want(...args);

		if (r === null)
			throw new ParseError(`Expected ${args.join(" or ")} got ${this.tokens[this.pos].tok}`,
								 this.tokens[this.pos].start,
								 this.tokens[this.pos].end);

		return r;
	}

	parseStatements() {
		let start = this.pos;
		let statements = [];


		for (;;) {
			if (this.want(";"))
				continue;
			if (this.peek(",", ")", "]", "EOF")) {
				if (statements.length == 0)
					return {
						value: null
					};
				else
					return {
						operation: "statements",
						inputs: statements,
						start: this.tokens[start].start,
						end: this.tokens[this.pos - 1].end
					};
			} else {
				statements.push(this.parseAssign());
				if (!this.peek(",", ")", "]", "EOF"))
					this.need(";");
			}
		}
	}

	parseAssign() {
		let start = this.pos;
		let a = this.parseIf();

		if (this.want(":=")) {
			let b = this.parseAssign();

			a = {
				operation: ":=",
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseIf() {
		let start = this.pos;

		if (this.want("if")) {
			let a, b, c;

			a = this.parseIf();

			this.need("then");

			b = this.parseIf();

			if (this.need("else", "end").tok == "else") {
				c = this.parseIf();
				this.need("end");
				return {
					operation: "conditional",
					inputs: [a, b, c],
					start: this.tokens[start].start,
					end: this.tokens[this.pos - 1].end
				};
			} else {
				return {
					operation: "conditional",
					inputs: [a, b, {
						value: null
					}],
					start: this.tokens[start].start,
					end: this.tokens[this.pos - 1].end
				};
			}
		}

		return this.parseTernary();
	}

	parseTernary() {
		let start = this.pos;
		let a = this.parseBool();

		if (this.want("?")) {
			let b = this.parseTernary();
			this.need(":");
			let c = this.parseTernary();
			a = {
				operation: "conditional",
				inputs: [a, b, c],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseBool() {
		let start = this.pos;
		let t, a = this.parseCompare();
		while ((t = this.want("&", "|", "^")) !== null) {
			let b = this.parseCompare();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseCompare() {
		let start = this.pos;
		let t, a = this.parseAdd();
		while ((t = this.want("<", ">", "<=", ">=", "=", "==", "!=", "!==", "===")) !== null) {
			let b = this.parseAdd();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseAdd() {
		let start = this.pos;
		let t, a = this.parseMul();
		while ((t = this.want("+", "-")) !== null) {
			let b = this.parseMul();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseMul() {
		let start = this.pos;
		let t, a = this.parseExp();
		while ((t = this.want("*", "/", "%")) !== null) {
			let b = this.parseExp();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseExp() {
		let start = this.pos;
		let t, a = this.parseNot();
		while ((t = this.want("**")) !== null) {
			let b = this.parseNot();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseNot() {
		let start = this.pos;
		if (this.want("!")) {
			let b = this.parseNot();
			return {
				operation: "!",
				inputs: [b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return this.parseKeywords();
	}

	parseKeywords() {
		let start = this.pos;
		let t, a = this.parseUnary();

		if ((t = this.want("contains", "in", "irlike", "like", "matches", "regex", "rlike")) !== null) {
			let b = this.parseUnary();
			a = {
				operation: t.tok,
				inputs: [a, b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return a;
	}

	parseUnary() {
		let start = this.pos;
		let t;

		if ((t = this.want("+", "-")) !== null) {
			let b = this.parseUnary();
			return {
				operation: t.tok,
				inputs: [b],
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return this.parseIndices();
	}

	parseIndices() {
		let start = this.pos;
		let a = this.parseFunction();

		while (this.want("[")) {
			if (!(this.want("]"))) {
				let b = this.parseStatements();
				this.need("]");

				a = {
					operation: "index",
					inputs: [a, b],
					start: this.tokens[start].start,
					end: this.tokens[this.pos - 1].end
				};
			} else {
				a = {
					operation: "index",
					inputs: [a],
					start: this.tokens[start].start,
					end: this.tokens[this.pos - 1].end
				};
			}
		}

		return a;
	}

	parseFunction() {
		const argCnts = {
			"lcase": [1, 1],
			"ucase": [1, 1],
			"length": [1, 1],
			"string": [1, 1],
			"int": [1, 1],
			"float": [1, 1],
			"bool": [1, 1],
			"norm": [1, 1],
			"ccnorm": [1, 1],
			"ccnorm_contains_any": [2, Infinity],
			"ccnorm_contains_all": [2, Infinity],
			"contains_any": [2, Infinity],
			"contains_all": [2, Infinity],
			"equals_to_any": [2, Infinity],
			"specialratio": [1, 1],
			"rmspecials": [1, 1],
			"rmdoubles": [1, 1],
			"rmwhitespace": [1, 1],
			"ip_in_ranges": [2, Infinity],
			"ip_in_range": [2, 2],
			"rescape": [1, 1],
			"substr": [2, 3],
			"strpos": [2, 3],
			"str_replace": [3, 3],
			"str_replace_regexp": [3, 3],
			"sanitize": [1, 1],
			"rcount": [1, 2],
			"count": [1, 2],
			"get_matches": [2, 2],
			"set": [2, 2]
		};

		let start = this.pos;
		let t;

		if ((t = this.want("function")) !== null) {
			let s, args = [];

			this.need("(");

			do {
				if (this.want(")"))
					break;
				args.push(this.parseStatements());

				s = this.need(",", ")");
			} while (s.tok != ")");

			if (args.length < argCnts[t.val][0] || args.length > argCnts[t.val][1])
				throw new ParseError(`Invalid argument count for ${t.val}`,
									 this.tokens[start].start,
									 this.tokens[this.pos - 1].end);

			return {
				operation: t.val,
				inputs: args,
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}

		return this.parseParens();
	}

	parseParens() {
		if (this.want("(")) {
			let s = this.parseStatements();

			this.need(")");

			return s;
		}

		return this.parseLiteral();
	}

	parseLiteral() {
		let start = this.pos;
		let s, t = this.need("literal", "variable", "constant", "[");

		if (t.tok == "literal") {
			let r = {
				value: t.val,
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
			if (t.strmap)
				r.strmap = t.strmap;
			return r;
		} else if (t.tok == "variable" || t.tok == "constant") {
			return {
				value: {
					name: t.val,
					indices: [],
					readonly: t.tok == "constant"
				},
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		} else {
			let arr = [];

			do {
				if (this.want("]"))
					break;
				arr.push(this.parseAssign());

				s = this.need(",", "]");
			} while (s.tok != "]");

			return {
				operation: "list",
				inputs: arr,
				start: this.tokens[start].start,
				end: this.tokens[this.pos - 1].end
			};
		}
	}

}



;// CONCATENATED MODULE: ./src/regex.js
let cache = new Map();

const FLAGS = {
	i: 0x01,
	s: 0x02,
	m: 0x04,
	x: 0x08,
	brackets: 0x10,
};

class RegexError {
	constructor(message) {
		this.message = message;
	}
	toString() {
		return this.message;
	}
}

class RE {
	constructor(parent) {
		this.src = parent.src;
		this.flags = parent.flags;
		this.start = null;
		this.end = null;
		this.repeat = null;
	}

	peek(pattern, rmfluff = false) {
		if (rmfluff) {
			while (this.want(/\\E|\\Q\\E|\(\?#[^)]*\)/uy) ||
				  (this.flags & FLAGS.x) && this.want(/\s+|#[^\n]*(?:\n|$)*/uy))
				;
		}

		if (this.src.pos >= this.src.text.length)
			return null;

		if (pattern == undefined || pattern == null)
			return [String.fromCodePoint(this.src.text.codePointAt(this.src.pos))];

		if (typeof pattern == 'string') {
			if (this.src.text.slice(this.src.pos, this.src.pos + pattern.length) == pattern) {
				return [pattern];
			}

			return null;
		}

		pattern.lastIndex = this.src.pos;

		return pattern.exec(this.src.text);
	}

	want(pattern, rmfluff = false) {
		let r = this.peek(pattern, rmfluff);

		if (r)
			this.src.pos += r[0].length;

		return r;
	}

	bracketize(str) {
		return this.flags & FLAGS.brackets ? str : "[" + str + "]";
	}

	escape(str) {
		let escapes = this.flags & FLAGS.brackets ?
			(/[\\{}().$^|[\]*+?-]/g) :
			(/[\\{}().$^|[\]*+?]/g);

		return str
			.replace(escapes, "\\$&")
			.replace(/[^\x20-\x7e]/ug, c => "\\u{" + c.codePointAt(0).toString(16) + "}");
	}

	outR(...args) {
		let suffix = "";

		if (this.repeat) {
			suffix = "{" + this.repeat.min + ",";
			if (this.repeat.max !== undefined)
				suffix += this.repeat.max;
			suffix += "}" + (this.repeat.ungreedy ? "?" : "");
		}

		return this.out(...args) + suffix;
	}

	getEscape() {
		let t, digits = this.peek(/[0-9]+/uy);

		if (digits) {
			let dec = parseInt(digits[0], 10);
			let oct = parseInt(digits[0].slice(0, 3), 8);

			if (digits[0][0] == "0") {
				this.want(/([0-7]{1,3})/uy);

				return new Literal(this, String.fromCodePoint(oct));
			}
			if (this.flags & FLAGS.brackets) {
				if (dec == 8 || dec == 9) {
					this.want();
					return new Literal(this, digits[0][0]);
				}
				this.want(/([0-7]{1,3})/uy);
				return new Literal(this, String.fromCodePoint(oct));
			}

			if (dec <= Math.max(7, this.src.caps)) {
				this.want(/[1-9][0-9]*/uy);
				return new BackRef(this, dec);
			}

			if (isNaN(oct))
				throw new RegexError("Invalid backreference");

			this.want(/[0-7]{1,3}/uy);
			return new Literal(this, String.fromCodePoint(oct));
		}

		let c = this.want()[0];

		switch (c) {
		case null:
			throw new RegexError("\\ at end");
		case "a":
			return new Literal(this, "\x07");
		case "e":
			return new Literal(this, "\x1b");
		case "f":
			return new Literal(this, "\x0c");
		case "n":
			return new Literal(this, "\n");
		case "r":
			return new Literal(this, "\r");
		case "t":
			return new Literal(this, "\t");
		case "b":
			return this.flags & FLAGS.brackets ?
				new Literal(this, "\x08") :
				new Boundary(this);
		case "B":
			return this.flags & FLAGS.brackets ?
				new Literal(this, "B") :
				new NoBoundary(this);
		case "p":
		case "P":
			t = this.want(/\{([A-Za-z:]+)\}/uy) || this.want(/([A-Za-z])/uy);
			if (!t)
				throw new RegexError("Invalid Unicode property");

			return new UnicodeProp(this, t[1], c == "P");
		case "d":
			return new Digit(this);
		case "D":
			return new NoDigit(this);
		case "w":
			return new Word(this);
		case "W":
			return new NoWord(this);
		case "s":
			return new Space(this);
		case "S":
			return new NoSpace(this);
		case "A":
			return new RealStart(this);
		case "Z":
			return new RealEnd(this);
		case "z":
			return new RealRealEnd(this);
		case "h":
			return new HorizSpace(this);
		case "H":
			return new NoHorizSpace(this);
		case "v":
			return new VertSpace(this);
		case "V":
			return new NoVertSpace(this);
		case "N":
			return this.flags & FLAGS.brackets ?
				new Literal(this, "N") :
				new NoNewline(this);
		case "c": {
			if (!(t = this.want(/[\x00-\x7f]/uy)))
				throw new RegexError("Invalid control escape");

			let cp = t[0].toUpperCase().codePointAt(0);

			return new Literal(this, String.fromCodePoint(cp ^ 0x40));
		}
		case "x":
			t = this.want(/\{([A-Za-z0-9]*)\}/uy) || this.want(/([A-Za-z0-9]{0,2})/uy);

			return new Literal(this, String.fromCodePoint(parseInt(t[1], 16) || 0));
		case "o":
			if ((t = this.want(/\{([0-7]*)\}/uy)))
				return new Literal(this, String.fromCodePoint(parseInt(t[1], 8)));

			throw new RegexError("Invalid octal escape");
		case "k":
			if (this.flags & FLAGS.brackets)
				return new Literal(this, "k");

			t = this.want(/<([\p{L}_][\p{L}\p{N}_]*)>/uy) ||
				this.want(/\{([\p{L}_][\p{L}\p{N}_]*)\}/uy) ||
				this.want(/'([\p{L}_][\p{L}\p{N}_]*)'>/uy);
			if (!t)
				throw new RegexError("Invalid backreference name");
			return new BackRef(this, t[1]);
		case "g": {
			if (this.flags & FLAGS.brackets)
				return new Literal(this, "g");

			if ((t = this.want(/\{([\p{L}_][\p{L}\p{N}_]*)\}/uy)))
				return new BackRef(this, t[1]);

			t = this.want(/\{(-?[0-9]+)\}/uy) || this.want(/(-?[0-9]+)/uy);
			if (!t)
				throw new RegexError("Invalid backreference name");

			let idx = parseInt(t[1], 10);
			if (idx <= 0)
				idx = this.src.caps + 1 + idx;

			return new BackRef(this, idx);
		}
		case 'G':
		case 'K':
			throw new RegexError("Unsupported escape: \\" + c);
		default:
			return new Literal(this, c);
		}
	}
}

class Literal extends RE {
	constructor(parent, str) {
		super(parent);
		this.literal = str;
	}
	out(caseTransform) {
		if (caseTransform === undefined && !(this.flags & FLAGS.i))
			return this.escape(this.literal);

		if (caseTransform == "U")
			return this.escape(this.literal.toUpperCase());
		if (caseTransform == "L")
			return this.escape(this.literal.toLowerCase());

		let r = "";
		for (let chr of this.literal) {
			let pair = this.escape(chr.toUpperCase()) + this.escape(chr.toLowerCase());

			r += this.bracketize(pair);
		}
		return r;
	}
	splitLastChr() {
		if (this.literal.length < 2)
			return null;

		let end = this.literal[this.literal.length - 1];

		this.literal = this.literal.slice(0, this.literal.length - 1);

		return new Literal(this, end);
	}
	append(a) {
		this.literal += a.literal;
	}
}

class Dot extends RE {
	out() {
		return this.flags & FLAGS.s ? "[\\s\\S]" : ".";
	}
}

class NoNewline extends RE {
	out() {
		return "[^\\n]";
	}
}

class Start extends RE {
	out() {
		return this.flags & FLAGS.m ? "(?<![^\\n])" : "^";
	}
}

class End extends RE {
	out() {
		return this.flags & FLAGS.m ? "(?![^\\n])" : "\n?$";
	}
}

class RealStart extends RE {
	out() {
		return "(?<![\\S\\s])";
	}
}

class RealEnd extends RE {
	out() {
		return "(?=\\n?(?![\\S\\s]))";
	}
}

class RealRealEnd extends RE {
	out() {
		return "(?![\\S\\s])";
	}
}

class Boundary extends RE {
	out(prev, next) {
		if (next instanceof Literal && !next.repeat && next.literal.match(/^[\p{L}\p{N}_]/u))
			return '(?<![\\p{L}\\p{N}_])';
		if (next instanceof Literal && !next.repeat && next.literal.match(/^[^\p{L}\p{N}_]/u))
			return '(?<![^\\p{L}\\p{N}_])';

		if (prev instanceof Literal && !prev.repeat && prev.literal.match(/[\p{L}\p{N}_]$/u))
			return '(?![\\p{L}\\p{N}_])';
		if (prev instanceof Literal && !prev.repeat && prev.literal.match(/[^\p{L}\p{N}_]$/u))
			return '(?![^\\p{L}\\p{N}_])';

		return "(?:(?![^\\p{L}\\p{N}_])(?<![\\p{L}\\p{N}_])|(?![\\p{L}\\p{N}_])(?<![^\\p{L}\\p{N}_]))";
	}
}
class NoBoundary extends RE {
	out(prev, next) {
		if (next instanceof Literal && !next.repeat && next.literal.match(/^[\p{L}\p{N}_]/u))
			return '(?<![^\\p{L}\\p{N}_])';
		if (next instanceof Literal && !next.repeat && next.literal.match(/^[^\p{L}\p{N}_]/u))
			return '(?<![\\p{L}\\p{N}_])';

		if (prev instanceof Literal && !prev.repeat && prev.literal.match(/[\p{L}\p{N}_]$/u))
			return '(?![^\\p{L}\\p{N}_])';
		if (prev instanceof Literal && !prev.repeat && prev.literal.match(/[^\p{L}\p{N}_]$/u))
			return '(?![\\p{L}\\p{N}_])';

		return "(?:(?<=[\\p{L}\\p{N}_])(?=[\\p{L}\\p{N}_])|(?<![\\p{L}\\p{N}_])(?![\\p{L}\\p{N}_]))";
	}
}
class Word extends RE {
	out() {
		return this.bracketize("\\p{L}\\p{N}_");
	}
}
class NoWord extends RE {
	out() {
		return this.bracketize("\\p{C}\\p{M}\\p{S}\\p{Z}\\p{Pd}\\p{Pe}\\p{Pf}\\p{Pi}\\p{Po}\\p{Pf}\\u{203F}\\u{2040}\\u{2054}\\u{FE33}\\u{FE34}\\u{FE4D}-\\u{FE4F}\\u{FF3F}");
	}
}
class Digit extends RE {
	out() {
		return "\\p{Nd}";
	}
}
class NoDigit extends RE {
	out() {
		return "\\P{Nd}";
	}
}
class Space extends RE {
	out() {
		return this.bracketize("\\x09-\\x0D\\x20\\x85\\xA0\\u{1680}\\u{180E}\\u{2000}-\\u{200A}\\u{2028}-\\u{2029}\\u{202F}\\u{205F}\\u{3000}");
	}
}
class NoSpace extends RE {
	out() {
		return this.bracketize("\\x00-\\x08\\x0E-\\x1F\\x21-\\x84\\x86-\\x9F\\xA1-\\u{167F}\\u{1681}-\\u{180D}\\u{180F}-\\u{1FFF}\\u{200B}-\\u{2027}\\u{202A}-\\u{202E}\\u{2030}-\\u{205E}\\u{2060}-\\u{2FFF}\\u{3001}-\\u{10FFFF}");
	}
}
class HorizSpace extends RE {
	out() {
		return this.bracketize("\\x09\\x20\\xA0\\u{1680}\\u{180E}\\u{2000}-\\u{200A}\\u{202F}\\u{205F}\\u{3000}");
	}
}
class NoHorizSpace extends RE {
	out() {
		return this.bracketize("\\x00-\\x08\\x0A-\\x1F\\x21-\\x9F\\xA1-\\u{167F}}\\u{1681}-\\u{180D}\\u{180F}-\\u{1FFF}\\u{200B}-\\u{202D}\\u{2030}-\\u{205E}}\\u{2060}-\\u{2FFF}\\u{3001}-\\u{10FFF}");
	}
}
class VertSpace extends RE {
	out() {
		return this.bracketize("\\x0A-\\x0D\\0x85\\u{2028}\\u{2029}");
	}
}
class NoVertSpace extends RE {
	out() {
		return this.bracketize("\\x00-\\0x09\\x0E-\\x84\\x86-\\u{2027}\\u{202A}-\\u{10FFFF}");
	}
}
class UnicodeProp extends RE {
	constructor(parent, prop, neg) {
		super(parent);

		this.prop = prop;
		this.neg = neg;
	}
	out() {
		return "\\" + (this.neg ? "P" : "p") + "{" + this.prop + "}";
	}
}

class BackRef extends RE {
	constructor(parent, id) {
		super(parent);

		this.id = id;
	}
	out() {
		let prefix = typeof this.id == 'string' ? "" : "_";
		return "\\k<" + prefix + this.id + ">";
	}
}

class Brackets extends RE {
	constructor(parent) {
		super(parent);
		this.flags |= FLAGS.brackets;
		this.alternatives = [];

		let qmode = false;
		let rangeStart = null, rangeEnd = null;
		for (;;) {
			if (this.src.pos >= this.src.text.length)
				throw new RegexError("Unclosed brackets");

			if (this.want("\\E")) {
				qmode = false;
				continue;
			}

			if (this.alternatives.length == 0 && this.want("^"))
				this.neg = true;

			if (!qmode && this.alternatives.length > 0 && this.want("]"))
				return;

			if (!qmode && this.alternatives.length && this.want(/-(?!(\\Q?\\E)*\])/uy)) {
				rangeStart = this.alternatives.pop()[0];
				continue;
			}

			if (!qmode && this.want("\\")) {
				if (this.want("Q")) {
					qmode = true;
					continue;
				} else {
					rangeEnd = this.getEscape(this);
				}
			} else {
				rangeEnd = new Literal(this, this.want()[0]);
			}

			if (rangeStart !== null) {
				if (!(rangeStart instanceof Literal) || !(rangeEnd instanceof Literal))
					throw new RegexError("Invalid range in character class");

				this.alternatives.push([rangeStart, rangeEnd]);

				rangeStart = null;
			} else {
				this.alternatives.push([rangeEnd]);
			}
		}
	}
	out() {
		let prefix = "[" + (this.neg ? "^" : "");

		for (let alt of this.alternatives) {
			if (alt.length == 1)
				prefix += alt[0].out();
			else if (!(this.flags & FLAGS.i))
				prefix += alt[0].out() + "-" + alt[1].out();
			else
				prefix += (alt[0].out("U") + "-" + alt[1].out("U") +
						   alt[0].out("L") + "-" + alt[1].out("L"));
		}

		return prefix + "]";
	}
}

class Alternatives extends RE {
	constructor(parent, depth = 0) {
		super(parent);

		this.alternatives = [[]];

		let t;

		if (this.src.pos !== 0) {
			if (this.want("*"))
				throw new RegexError("Control verbs are not supported");
			if (this.want("?")) {
				if ((t = this.want(/([imsx-]*):/uy))) {
					this.handleFlags(t[1]);
				} else if ((t = this.want(/<?[!=]/uy))) {
					this.lookaround = t[0];
				} else if ((t = this.want(/P?<([\p{L}_][\p{L}\p{N}_]*)>/uy)))
					this.capid = t[1];
				else if ((t = this.want(/'([\p{L}_][\p{L}\p{N}_]*)'/uy)))
					this.capid = t[1];
				else if ((t = this.want(/[>(|&]|[-+]?[0-9]|P>/uy)))
					throw new RegexError("Unsupported feature: (?" + t[0]);
				else
					throw new RegexError("Unknown characters after (?");
			} else {
				this.capid = ++this.src.caps;
			}
		}

		for (;;) {
			this.startMark();

			if (this.flags & FLAGS.x) {
				if ((t = this.want(/[^\\{}().$^|[\]*+?\s#]+/uy, true)))
					this.pushLiteral(new Literal(this, t[0]));
			} else if ((t = this.want(/[^\\{}().$^|[\]*+?]+/uy, true)))
				this.pushLiteral(new Literal(this, t[0]));

			let c = this.want(null, true);
			if (c !== null)
				c = c[0];

			switch (c) {
			case ")":
				if (depth === 0)
					throw new RegexError("Extra ')' at top level");
				return;
			case null:
				if (depth !== 0)
					throw new RegexError("Unclosed '('");
				return;
			case "(":
				if ((t = this.want(/\?([imsx-]*)\)/uy)))
					this.handleFlags(t[1]);
				else
					this.push(new Alternatives(this, depth + 1));
				break;
			case "|":
				this.alternatives.push([]);
				break;
			case "*":
			case "+":
			case "?":
				this.assignRepeat(c);
				this.shiftMark();
				break;
			case "{":
				if ((t = this.want(/([0-9]+)(,)?([0-9]*)\}/uy))) {
					let min = parseInt(t[1], 10);
					let max = !t[2] ? min : t[3].length ? parseInt(t[3], 10) : undefined;
					this.assignRepeat("{", min, max);
					this.shiftMark();
				} else {
					this.pushLiteral(new Literal(this, "{"));
				}
				break;
			case ".":
				this.push(new Dot(this));
				this.mark();
				break;
			case "^":
				this.push(new Start(this));
				this.mark();
				break;
			case "$":
				this.push(new End(this));
				this.mark();
				break;
			case "[":
				this.push(new Brackets(this));
				this.mark();
				break;
			case "\\":
				if (this.want("Q")) {
					let end = this.src.text.indexOf("\\E", this.src.pos);
					if (end == -1)
						end = this.src.text.length;

					this.pushLiteral(new Literal(this, this.src.text.slice(this.src.pos, end)));
					this.src.pos = end;
				} else if (!this.want("E")) {
					let esc = this.getEscape(this);

					if (esc instanceof Literal)
						this.pushLiteral(esc);
					else {
						this.push(esc);
						this.mark();
					}
				}
				break;
			default:
				this.pushLiteral(new Literal(this, c));
				break;
			}
		}
	}

	startMark() {
		this.markStart = this.src.pos;
	}
	push(x) {
		this.alternatives[this.alternatives.length - 1].push(x);
	}
	mark() {
		let cur = this.alternatives[this.alternatives.length - 1];
		if (cur.length) {
			cur[cur.length - 1].start = this.markStart;
			cur[cur.length - 1].end = this.src.pos;
		}
	}
	shiftMark() {
		let cur = this.alternatives[this.alternatives.length - 1];
		if (cur.length)
			cur[cur.length - 1].end = this.src.pos;
	}

	pushLiteral(literal) {
		let cur = this.alternatives[this.alternatives.length - 1];

		let combine = cur.length &&
			cur[cur.length - 1] instanceof Literal &&
			cur[cur.length - 1].flags == this.flags &&
			!cur[cur.length - 1].repeat;
		let repeat = this.peek(/[+*?{]/uy);
		let suffix = null;

		literal.start = this.markStart;
		literal.end = this.src.pos;

		if (repeat) {
			suffix = literal.splitLastChr();

			if (suffix) {
				suffix.start = this.src.pos - 1;
				suffix.end = this.src.pos;
				literal.end = this.src.pos - 1;
			} else {
				combine = false;
			}
		}

		if (!repeat && !combine) {
			cur.push(literal);
		} else if (!repeat && combine) {
			cur[cur.length - 1].append(literal);
			cur[cur.length - 1].end = literal.end;
		} else if (repeat && !combine) {
			cur.push(literal);
			if (suffix)
				cur.push(suffix);
		} else if (repeat && combine) {
			cur[cur.length - 1].append(literal);
			cur[cur.length - 1].end = literal.end;
			cur.push(suffix);
		}
	}

	handleFlags(flags) {
		let neg = false;

		for (let flag of flags) {
			if (flag == "-")
				neg = true;
			else if (neg)
				this.flags &= ~FLAGS[flag];
			else
				this.flags |= FLAGS[flag];
		}
	}

	assignRepeat(c, min, max) {
		let cur = this.alternatives[this.alternatives.length - 1];

		if (c == "?")
			max = 1;
		if (c == "+")
			min = 1;
		else if (c != "{")
			min = 0;

		if (cur.length == 0)
			throw new RegexError("Nothing to repeat");

		let prev = cur[cur.length - 1];

		if (prev.lookaround)
			throw new RegexError("Repeated lookaorund assertions not supported");

		if (prev.repeat) {
			if (!prev.repeat.ungreedy && c == "?")
				prev.repeat.ungreedy = true;
			else if (c == "+")
				throw new RegexError("Possessive repeats are not supported");
			else
				throw new RegexError("Duplicate repeat");
		} else {
			prev.repeat = { min, max };
		}
	}

	out(capmap = []) {
		let prefix = "(";

		if (this.lookaround)
			prefix += "?" + this.lookaround;
		else if (this.capid) {
			prefix += typeof this.capid == 'string' ? "?<" : "?<_";
			prefix += this.capid + ">";
			capmap.push([this.start, this.end, true]);
		} else {
			prefix += "?:";
		}

		for (let i = 0; i < this.alternatives.length; i++) {
			let run = [];

			for (let j = 0; j <= this.alternatives[i].length ; j++) {
				let part = this.alternatives[i][j];

				if (!part || part instanceof Alternatives) {
					if (run.length) {
						capmap.push([run[0].start, run[run.length - 1].end]);

						prefix += "(";
						for (let k = 0; k < run.length; k++) {
							if (run[k] instanceof Boundary || run[k] instanceof NoBoundary)
								prefix += run[k].outR(run[k - 1], run[k + 1]);
							else
								prefix += run[k].outR();
						}
						prefix += ")";

						run = [];
					}
					if (part)
						prefix += part.outR(capmap);
				} else {
					run.push(part);
				}
			}

			if (i !== this.alternatives.length - 1)
				prefix += "|";
		}

		return prefix + ")";
	}
}

class TopLevel extends RE {
	constructor(src, flags = "") {
		let init = {
			src: {
				text: src,
				pos: 0,
				caps: 0
			},
			flags: flags.split("").reduce((flags, flag) => flags | FLAGS[flag], 0)
		};

		super(init);

		this.alternatives = new Alternatives(this);
	}

	out(capmap) {
		return this.alternatives.out(capmap);
	}
}

class PCiRE extends RegExp {
	constructor(regexp, flags) {
		let myflags = "", realflags = "";

		let cached = cache.get(regexp + "," + flags);
		if (cached) {
			cached.lastIndex = 0;

			// Move to front
			cache.delete(regexp);
			cache.set(regexp, cached);

			return cached;
		} else if (cache.size > 1000) {
			// Delete last entry
			for (let k of cache.keys()) {
				cache.delete(k);
				break;
			}
		}

		if (flags)
			for (let f of flags) {
				if (f == "x" || new RegExp("\\(\\?[a-z]*-[a-z]*" + f).test(regexp))
					myflags += f;
				else
					realflags += f;
			}

		if (!realflags.includes("u"))
			realflags += "u";

		let capmap = [[0, regexp.length - 1]];

		let t = new TopLevel(regexp, myflags);
		let out = t.out(capmap);

		super(out, realflags);

		this.tree = t;
		this.capmap = capmap;
		this.origcaps = t.src.caps;
		this.orginal = regexp;

		cache.set(regexp + "," + flags, this);
	}

	exec(str) {
		let match = super.exec(str);

		if (match == null)
			return null;

		match.spans = [];

		for (let i = 1; i < match.length; i++) {
			if (match[i] && !this.capmap[i][2])
				match.spans.push(this.capmap[i]);
		}

		match.length = 1;
		for (let i = 1; i <= this.origcaps; i++)
			match.push(match.groups["_" + i]);

		return match;
	}
}



;// CONCATENATED MODULE: ./data/data.js
/* Derived from:
 * https://raw.githubusercontent.com/wikimedia/mediawiki-libs-Equivset/a5ca9c26726594b5bd294bd4c91822a6560072d6/dist/equivset.json
 * https://html.spec.whatwg.org/entities.json
 */

const equivset=[36,83,12,-4,1,-6,2,-4,1,-4,1,18,1,-12,10,-6,33,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,-17,37,0,1,-6,1,9,2,13,4,-22,1,-2,4,17,2,-3,2,-29,1,19,1,-30,1,46,4,-12,1,6,5,-16,1,2,1,0,1,0,1,0,1,0,1,0,2,2,1,2,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,-5,1,10,1,1,1,0,1,0,1,0,1,0,1,9,1,-9,1,6,1,0,1,0,1,0,1,4,1,-9,1,-14,1,-1,1,0,1,0,1,0,1,0,1,0,1,133,1,-131,1,2,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,-5,1,10,1,1,1,0,1,0,1,0,1,0,2,0,1,6,1,0,1,0,1,0,1,4,1,-9,1,9,1,-24,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,2,233,1,-232,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,2,259,1,-256,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,2,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,2,-24,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,3,1,-2,1,0,1,0,1,1,1,0,1,1,1,18,2,-13,1,-3,1,2,1,0,1,1,1,847,1,-836,1,-9,1,0,1,1,1,0,1,0,2,339,1,-338,1,0,1,2,1,-32,1,0,1,881,1,-848,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,4,1,0,1,1,1,0,1,-21,1,0,1,0,1,0,1,-19,1,33,1,0,2,-3,1,-7,3,0,1,424,2,0,3,-42,3,3,1,-393,1,0,1,8,1,0,1,6,1,0,1,6,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-16,1,-4,1,0,1,0,1,0,1,133,1,0,1,-127,1,0,1,0,1,0,1,4,1,0,1,6,1,0,1,0,1,0,1,-12,1,0,1,5,3,423,1,-426,1,0,2,9,1,-2,1,0,1,-13,1,0,1,133,1,0,1,-119,1,0,1,-14,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,6,1,0,1,0,1,0,1,3,1,0,1,0,1,0,1,3,1,0,1,0,1,0,1,-2,1,0,1,1,1,0,1,-15,1,0,1,3,1,0,1,6,1,-10,1,-12,1,0,1,34,1,0,1,-25,1,0,1,4,1,0,1,10,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,10,1,0,1,-13,1,2,1,6,1,-10,3,-9,1,2,1,0,1,9,1,8,1,-1,1,7,3,-24,1,19,1,838,1,-854,1,0,1,5,1,0,1,7,1,0,1,1,1,0,1,7,1,0,1,-24,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,3,5,1,-3,1,0,1,0,1,18,1,0,1,-24,1,7,2,1,1,0,1,0,1,3,1,0,1,0,2,11,2,-10,1,1,1,0,1,0,1,1,4,3,3,0,1,0,1,0,2,0,1,0,1,1,1,0,4,1,1,0,1,1,1,0,1,0,1,838,1,-846,1,846,1,-834,1,1,2,-21,2,-6,4,16,1,-13,3,6,1,2,1,1,1,1,1,5,16,-9,1,0,1,2,1,8,1,0,1,0,1,0,1,5,1,2,40,0,1,-13,1,7,1,5,143,-4,1,0,3,-6,1,0,4,-11,1,0,1,0,2,7,7,-9,2,4,1,3,1,1,2,6,2,10,1,848,1,-864,1,-8,1,1,1,16,2,-13,1,21,1,-18,1,7,1,-6,1,2,2,2,1,1,2,1,2,1,3,4,1,5,1,543,1,-544,3,-15,1,16,1,-24,1,4,1,9,1,-5,1,16,1,-24,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-14,1,16,1,-10,1,10,1,-2,1,-12,1,-9,2,23,1,0,1,0,1,543,1,-545,1,-9,5,-8,1,0,11,-20,1,0,8,30,1,-13,1,7,1,5,1,-10,1,0,3,-2,1,10,1,0,1,3,1,-13,1,0,1,0,1,2,1,0,1,3,1,10,1,-13,1,14,1,-10,1,0,1,1,2,-2,1,0,1,3,1,973,1,-959,2,-24,1,6,1,-5,1,16,1,-17,1,4,2,0,2,979,1,-973,1,853,1,-851,1,-5,1,7,1,849,1,-848,1,-13,1,17,1,5,1,543,1,-544,1,-3,1,-20,3,1,2,0,3,16,1,-17,1,1,1,0,1,16,1,-17,1,4,1,977,1,-977,1,979,1,0,1,-973,1,853,1,-851,1,-5,1,7,1,849,1,-848,1,-13,1,17,1,5,1,543,1,-544,1,-3,1,-20,3,1,1,1001,1,-1001,3,16,1,-13,1,0,1,3,1,10,1,-13,1,14,1,-10,1,0,1,1,2,-2,1,0,1,3,1,973,1,-959,2,-2,1,0,1,-21,1,0,15,13,1,0,1,7,1,0,5,-7,1,0,1,8,1,0,1,0,1,0,11,961,1,0,1,-982,1,0,1,14,1,0,1,2,1,0,1,-12,1,0,3,976,1,0,1,-977,1,0,1,6,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-3,1,0,7,-5,1,0,1,17,1,0,1,5,1,0,1,0,1,0,1,-1,1,0,3,1,1,0,1,-24,1,0,1,7,1,0,2,1140,1,0,1,0,1,-1139,3,2,1,0,1,853,1,0,1,-856,1,0,1,0,1,0,1,17,1,0,1,-12,1,0,1,-4,1,-8,1,0,1,0,1,0,1,133,1,0,1,-129,1,0,1,0,1,0,1,0,1,0,5,0,1,0,1,979,1,0,1,0,1,0,1,-969,1,0,1,0,1,0,1,0,1,0,3,10,1,0,1,0,1,0,1,0,1,0,1,-24,1,0,1,17,1,0,3,-12,1,0,1,18,1,0,1,0,1,0,1,-20,1,0,9,4,1,0,1,-1,1,0,13,10,1,0,1,6,1,0,1,-12,1,0,9,-3,1,0,8,13,1,1293,1,-1297,1,1299,1,1,1,-1300,1,1302,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-1319,1,1321,1,1,1,1,1,-1310,1,-16,1,1329,1,1,1,-1321,1,1323,1,1,1,1,1,-1325,1,7,1,1321,1,1,1,1,1,-1337,1,1339,1,1,1,-1331,1,-1,1,1335,4,-1375,1,0,2,57,4,-9,2,-6,3,0,10,-9,4,13,1,-11,3,4,4,0,1,7,4,-14,3,9,1,-1,2,6,2,-27,19,711,19,9,10,-3,8,0,1,0,1,-717,1,717,47,-736,1,-5,43,29,26,6,17,1540,5,-822,17,-708,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,3,1491,8,72,44,-1551,9,1534,1,0,17,54,3,-50,3,0,11,2,1,0,3,50,5,-52,18,159,5,-7,4,-1680,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,9,-11,63,729,1,1077,5,-1083,49,839,394,-833,58,28,22,-3,1,-32,1,1,18,-690,9,-22,77,746,42,-724,4,-23,3,1,21,718,1,1660,57,-1632,15,1571,2,7,25,-2302,1,-22,3,-1,24,719,58,28,1,1562,4,4,1,1,11,11,25,-2302,2,2329,1,1,1,1,4,4,21,-2358,57,747,42,-724,2,-22,26,721,26,2182,20,-8,14,0,10,33,5,-2210,10,2220,15,-2916,1,2886,1,-12,2,17,3,-12,1,-9,2,42,5,68,3,-60,10,-2920,1,2356,31,670,11,11,10,9,47,-3046,28,0,1,2356,2,642,1,1,1,1,11,11,1,1,1,1,8,8,2,2,5,5,12,12,2,2,1,1,52,-3043,1,3096,1,1,7,7,19,-3104,7,2874,19,7,4,-2881,3,2900,14,397,3,-380,2,2,9,9,1,0,1,3,1,0,1,0,30,348,162,228,8,8,4,4,5,-10,1,0,2,13,10,-11,30,-3524,6,3568,8,-2856,3,-699,56,3513,5,26,13,-8,1,1,2,2,1,1,1,1,25,25,1,1,15,15,1,1,1,1,1,1,2,-2881,3,-699,60,3772,273,-3772,25,699,10,-699,167,10,12,-20,686,13,4,-9,4,16,1,-24,1,9,1,-5,5,13,2,5,4,-10,4,-5,2,17,1,-10,2,-8,2,1,1,18,11,-25,1,1,3,16,2,5,1,-4,4,3,1,-3,4,-7,1,-9,3,13,4,-5,1,-1,11,-2,1,-1,1,-5,6,6,1,-1,1,-5,7,850,36,-733,8,-97,62,-6,2,-12,30,6,50,-24,18,5103,112,-5065,54,828,5,-844,1,16,10,-6,40,-16,5,4,17,-5,25,3,12,0,5,19,1,-10,7,-11,11,5198,1,-7,1,74,3,7,27,105,1,3,1,4,11,-4513,5,-852,1,852,56,-849,1,0,105,-11,204,5973,20,-2414,1,1,1,1,1,1,12,-2861,5,2878,8,-2878,1,2853,1,43,4,-11,1,12,54,-3596,134,6157,195,-6151,846,4,12,-20,77,-4,1,133,1,0,1,-132,1,1,1,1,1,0,1,1,1,0,1,4,1,1,1,1,1,1,1,1,1,1,1,1,1,-12,1,12,1,-12,1,12,1,259,1,-282,3,24,1,2,1,0,1,2,1,1,1,0,1,0,1,-8,1,9,1,1,1,3,1,-21,1,-19,2,32,1,841,1,5,1,-848,1,856,1,-8,1,-863,1,133,1,-132,1,0,1,2,1,1,1,0,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,-23,1,24,1,2,1,2,1,1,1,2,1,-22,1,0,1,0,1,133,1,-132,1,2,1,1,1,0,1,0,1,0,1,2,1,2,1,2,1,2,1,1,1,1,1,-12,1,7379,1,1,1,-7367,1,4,1,1,1,0,1,2,1,-1,1,7375,1,-7395,1,23,1,827,1,-284,1,-544,1,-15,1,9,1,3,1,1,1,-20,1,23,1,-9,1,552,1,-544,2,-22,1,2,1,2,1,7,1,1,1,2,1,2,1,0,1,1,1,1,1,6,1,-19,1,1,1,-1,2,2,1,0,1,7,1,5,1,0,1,-19,1,2,1,2,1,1,1,4,1,1,1,1,1,1,1,2,1,2,1,1,1,0,1,3,1,2,1,2,1,-25,1,0,1,3,1,1,1,0,1,0,1,0,1,4,1,-6,1,16,1,2,1,-16,1,-4,1,2,1,0,1,1,1,1,1,1,1,4,1,-3,1,1,1,1,1,0,1,0,1,0,1,1,1,2,1,0,1,0,1,1,1,10,1,-9,1,0,1,0,1,1,1,553,1,-549,1,0,1,1,1,1,1,0,1,0,1,1,1,837,1,-833,1,0,1,0,1,-21,1,10,65,-14,1,0,11,3,1,0,9,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,3,2,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,11,4,1,0,1,0,1,0,5,1,1,0,1,0,1,0,1,0,1,0,3,1,1,0,13,2,1,0,1,0,1,0,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,3,1,1,0,9,1,1,0,19,3,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,5,2,1,0,10,0,6,827,1,-851,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,5,10,1,0,37,10,1,0,1,0,1,0,1,0,1,0,1,0,1,0,7,-24,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,4,1,0,1,0,1,0,1,0,1,0,3,0,1,0,1,0,1,0,1,0,1,0,3,9,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-6,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,6,1,0,1,0,1,0,1,0,1,0,3,0,1,0,1,0,1,0,1,0,1,0,3,10,1,0,1,0,1,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,1,-2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,850,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-872,1,0,1,4,1,0,1,9,1,0,1,-5,1,0,1,6,1,0,1,10,1,0,1,-2,1,0,3,-22,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,13,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-6,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,15,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,850,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,-872,1,0,1,0,1,0,1,0,2,0,1,0,1,0,1,0,1,0,1,0,1,0,6,13,1,0,1,0,2,0,1,0,1,-9,1,0,1,3,1,0,1,0,4,1,1,0,1,0,1,0,3,0,1,0,1,0,1,0,1,0,1,0,5,16,1,0,1,0,1,0,1,-9,1,0,1,9,1,0,1,0,1,0,1,0,1,0,1,-9,6,7,1,0,1,0,2,0,1,0,1,-8,1,0,1,858,1,0,1,0,14,-937,1,0,1,0,1,0,1,0,1,0,25,0,1,0,1,0,1,0,2,0,1,0,15,63,37,-63,4,0,1,0,1,0,1,0,7,79,1,-6,3,-8,1,18,1,-12,1,-16,1,1,1,1,6,21,1,1,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,7,8,1,4,1,10,1,9,1,-19,1,3,1,3,1,1,1,1,1,1,1,2,1,3,1,1,5,-17,2,3,1,6,1,1,1,1,1,2,2,7,2,-19,1,1,1,6,1,9,3,-4,1,-9,1,-6,2,2,2,16,1,1,5,-4,2,-14,67,1,5,2,3,2,1,1,1,0,1,0,1,0,1,0,1,1,1,0,1,3,1,0,2,2,2,2,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,0,4,4,1,4,2,847,1,-852,1,5,1,-17,1,2,1,-10,1,1,1,1,1,2,1,0,1,0,1,1,1,0,1,7,1,2,5,-6,3,855,1,-839,1,-7,1,846,1,3,1,-860,3,18,1,-21,1,0,1,1,1,4,1,1,5,-4,18,3,4,13,5,2,3,-12,1,-9,1,1,1,9,1,-4,4,13,5,2,3,-12,1,-9,1,1,1,9,2,-9,2,-1,1,0,1,0,2,1,3,-18,1,19,117,-4,1,2,1,2,1,0,1,0,1,10,1,837,1,0,1,-847,1,0,1,0,1,0,1,0,1,0,2,859,2,3,7,-852,5,-14,10,858,1,-837,1,-8,1,7,150,838,1,-837,1,-8,1,7,413,-12,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,12,16,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-9258,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-9266,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-11,1,9243,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-9258,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1,-9242,596,-16,1,0,34,10,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1,-9248,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1,-9248,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,9264,1229,-9245,1,0,1,0,1,4,1,2,1,-17,1,19,1,-12,1,0,1,3,1,0,1,15,1,0,1,-25,1,12,1,-12,1,0,1,21,1,1,1,0,1,-1,3,546,1,-563,1,13,1,-3,1,-10,1,5,1,12,1,-3,1,7,25,-13,1,0,152,2,8,-10,27,10,196,-16,22,0,473,16,209,12329,923,975,423,455,852,778,261,184,2344,-1096,22,3620,111,-2161,577,2833,300,304,501,459,52,84,1,4,748,728,359,397,1,1,5,10,7,7,9,2,2,7,2,2,4,-19928,30,19964,18,18,39,26,2,13,1,-13,17,-101,2,48,4,92,3,2,2,0,17,17,1,1,14,-11,28,56,15,-213,36,144,58,151,11,-59,9,-33,5,99,21,-268,33,171,11,38,10,103,11,69,30,-128,12,125,1,-119,2,152,2,-160,10,186,17,-182,2,-255,3,246,1,205,2,2,1,-280,2,-169,6,194,18,19,8,39,11,203,3,-4,3,55,13,-261,43,136,1,-1,3,209,1,-124,4,-209,25,-3,2,-9,1,221,1,-9,19,-143,2,265,4,-332,1,-5,1,287,2,-278,7,282,4,61,3,-438,4,160,1,-140,7,207,4,-226,9,100,7,123,3,217,5,101,12,-492,7,-13,1,224,1,-30,2,-237,4,234,1,68,3,-72,1,278,1,-23,2,3,4,-193,1,-60,9,-120,1,333,11,-359,8,400,3,-153,2,-37,3,191,1,-4,1,-189,20,343,1,13,1,-13,2,15,3,8,15,-693,3,-128,1,445,12,-466,15,859,7,35,6,6,54,48,5,-5,9,11,6,21,6,6,1,0,14,14,3,-2,2,-166,8,182,4,3,2,3,7,7,31,22,1,5,6,-10,7,-501,4,512,2,20,3,-6,3,-7,3,-20,4,-206,3,238,9,-13,2,-17,1,-488,1,487,8,55,1,-15,1,27,9,-13,2,25,4,-41,1,-37,2,17,9,2,3,-28,1,97,3,-12,2,-79,1,37,1,66,1,-64,1,18,4,-15,1,15,2,0,20,-388,3,345,9,141,1,-653,4,-52,8,704,18,12,2,-497,2,521,2,-53,2,42,3,-24,4,12,4,-64,1,30,2,61,8,-56,1,41,1,0,2,-26,3,-20,8,94,43,39,2,4,4,8,15,12,3,-1115,8,-201,4,1168,1,167,2,-7,2,-160,4,175,8,-1025,27,1056,2,-1,28,26,2,-8,5,16,4,-15,9,6,3,-10,2,7,1,-1380,1,1406,14,30,1,0,1,0,27,27,3,-1473,3,1251,39,-1057,40,1366,14,-30,3,38,4,-8,1,12,6,-9,1,-24,16,29,49,47,31,-1008,11,991,16,24,21,-25,35,-1,18,122,4,-174,57,12,1,0,1,136,2,159,7,-133,1,-162,3,242,36,-47,8,-8020,4,6876,8,1194,4,3,9,-290,3,-1502,1,1500,1,-1455,2,1281,4,394,9,202,11,-334,1,273,3,-79,4,-262,12,69,15,198,3,-173,10,95,12,-233,4,14,2,-843,5,1295,4,-321,2,243,1,-282,2,274,6,-76,12,93,1,-161,5,73,1,88,1,-379,3,418,1,-287,1,83,3,-129,5,290,12,-30,10,194,2,45,8,-424,3,53,5,11,1,-8,2,379,7,-93,3,-282,2,222,4,-399,6,361,2,-246,7,-136,5,201,4,315,4,120,1,-51,4,-238,12,-177,1,-103,2,67,2,189,4,-325,4,-1369,1,1798,1,-1945,2,2047,5,127,2,-327,3,17,1,126,1,184,3,-1314,3,722,1,285,8,193,2,-195,11,362,5,10,4,-1363,5,1353,5,18,3,8,9,-3,1,4,2,-4,6,-1385,1,1391,4,-6,2,3,1,-1388,1,1410,3,-27,1,-1383,3,1389,2,-17,15,-855,48,-404,24,1368,6,-2359,16,2412,23,23,4,-96,9,-24,18,58,5,37,19,80,14,-37,34,-73,2,-10,5,-55,12,145,7,38,18,-64,5,-96,22,-1347,5,1467,3,38,5,-1557,3,-33,8,1468,2,123,7,136,7,-295,1,290,1,-81,5,6,17,-102,3,157,9,12,6,-244,2,311,14,-359,2,229,1,0,4,-182,8,314,3,-243,9,-75,3,-12,1,98,3,40,5,-1102,3,1180,2,-149,1,-89,1,77,4,-55,1,53,1,0,2,-40,5,-438,1,492,1,-53,1,233,5,168,2,-2798,1,1366,5,1440,2,-2806,1,2806,2,2,3,-77,1,82,7,-2306,2,989,15,-105,3,1451,1,-2665,4,2670,5,-2566,6,-4,12,114,7,2482,3,-1542,15,1551,23,35,1,-15,1,-1571,1,1543,2,28,2,-11,8,-2585,32,-2172,7,4816,15,12,7,-2656,23,2711,13,4,2,-67,13,-18,4,-2548,2,2663,12,-94,1,-17,33,-1017,5,1119,16,57,2,0,15,36,1,-59,8,-2557,26,2548,3,-116,7,126,17,-2446,16,2393,25,98,5,-2645,2,154,1,2356,13,255,1,-290,26,34,30,-1,2,247,2,-20,1,-88,1,0,4,63,1,-200,3,258,5,-167,3,111,1,-110,13,234,4,-38,4,7,1,-186,8,188,3,-2978,3,2882,7,176,1,-174,11,-94,9,-16,31,337,10,1,1,25,2,-13,5,22,2,-18,3,-2515,7,-517,6,1182,13,-659,3,2561,15,13,8,-2825,13,258,3,2583,1,-2581,5,2,1,2521,8,0,6,60,1,-60,1,80,1,-1493,4,1493,4,-51,1,-29,2,32,2,-2568,1,2596,5,-1898,2,1866,2,3,1,-3,9,-672,6,-1970,2,2747,1,-3571,3,3560,2,-2,1,3,5,22,1,0,4,-925,2,932,3,-1538,3,1544,7,-1157,4,1168,2,-1168,10,1178,6,-2844,3,-353,10,3215,3,-14,6,11,8,12,7,18,2,-31,4,36,4,-8,1,-27,19,-2633,1,-867,22,753,10,0,4,1497,4,-443,17,1799,47,59,7,7,4,-87,2,3,7,70,11,38,3,-2489,2,2485,1,-1287,1,1211,2,89,5,5,1,-2957,1,-695,1,0,9,3604,10,-40,27,137,9,-172,2,-1780,3,1961,30,32,14,-18,3,-48,3,-151,4,5,1,0,8,191,3,-88,9,-30,2,-1,5,-31,1,-1,1,46,5,19,10,84,2,-171,2,-46,1,52,14,12,1,-1817,6,1856,1,223,1,0,2,-2079,13,2108,13,13,5,-2689,6,9,2,2691,6,-3762,34,3773,6,3,4,30,3,-5,1,-17,3,22,10,1,2,-3197,1,3173,4,31,16,14,1,-1,1,26,1,-39,5,-18,4,-27,1,0,7,45,1,3,6,-4019,4,-88,1,0,1,496,1,-408,1,-54,4,920,3,421,1,-1217,1,4027,2,-4151,16,1350,2,989,7,-987,9,960,4,1859,5,-580,11,615,2,-739,2,710,2,-2820,1,13,1,2813,1,-2806,4,-3,1,-1263,5,4101,1,-2835,1,0,7,2692,3,-2693,3,6,2,2795,1,-2839,1,2831,1,14,1,-32,7,106,2,-89,4,-2827,3,0,2,2652,6,-1801,1,-2197,1,2197,2,-916,13,-1348,1,140,5,4229,2,-2823,17,-620,14,3468,2,-10,5,23,4,2,4,-2920,4,-428,2,3348,2,-2,2,-3481,1,3499,1,-26,3,33,1,-288,1,-1975,2,2267,4,-3109,1,0,2,3116,1,0,1,0,2,4,6,6,6,-4200,6,4203,5,-4201,8,-48,4,4273,5,-4105,2,-13,2,1188,5,2934,2,-4278,11,0,2,4295,9,-1672,3,-2176,1,15,7,3813,1,0,2,50,2,-56,1,-4054,14,-228,14,843,6,3208,25,-2396,27,-1499,21,4230,12,-3293,8,-1072,17,976,3,3469,5,19,18,-3277,18,712,21,-548,16,3109,9,-3388,2,3455,4,-2628,4,2653,5,-235,1,61,1,21,5,180,3,-3829,24,3788,11,-27,1,-2612,9,2418,7,201,1,1,9,-2,29,-17,4,130,11,-1581,1,1516,12,-165,3,116,6,-3360,1,3236,4,129,9,-126,2,287,1,28,5,-3775,5,3691,1,5,1,0,5,-117,4,119,1,-68,6,-167,1,-2,8,171,1,164,1,-1651,1,936,12,353,3,145,5,115,1,-3782,5,3575,1,-3631,1,3897,1,-177,3,248,3,-3025,1,2898,10,54,5,99,2,-216,3,-172,4,-1113,4,1052,6,-3776,7,478,4,3471,2,-479,3,427,4,-63,2,-1218,2,1679,11,-401,4,405,4,21,1,-365,10,112,4,-1451,1,1218,1,172,2,-221,2,280,2,106,2,-262,7,443,13,5,10,16,8,-3,1,-1,5,18,3,-26,1,9,1,-9,1,0,5,39,1,0,4,-3783,2,3788,16,-4040,25,1412,14,-2409,20,902,3,-768,25,2333,16,2633,6,-4930,7,4893,8,69,1,1,9,1,2,57,4,-82,3,89,2,-4549,2,4434,8,53,22,49,7,54,19,-5319,37,5345,14,-4532,1,4339,12,159,4,44,14,-191,3,118,4,-3945,2,3268,15,560,1,54,2,-10450,17,10573,2,7,2,-33,17,-4088,20,4057,26,-119,1,246,16,136,2,-56,1,-141,6,-538,3,711,2,-4981,10,4062,1,948,1,-174,1,-4526,3,-5970,2,10271,2,255,9,155,1,-151,5,-7,8,-224,1,250,2,-303,6,481,2,-153,6,111,1,-348,3,-38,7,198,3,-231,1,186,1,51,2,178,10,-70,11,8,3,70,1,-967,13,664,2,71,4,-122,3,-1,4,-7,1,290,1,-135,7,-4408,2,4509,3,-58,7,-56,2,362,2,-368,5,264,2,-173,5,-89,4,150,2,-208,1,-121,5,43,7,-73,1,430,6,-190,2,-35,3,-1,1,68,1,-259,1,135,3,206,3,-277,3,-4259,1,4390,8,-10562,1,10470,6,27,6,68,3,63,4,-5413,4,5804,1,-5075,3,4913,1,-353,1,282,1,-74,2,-334,3,590,3,-113,1,152,1,-38,2,-584,6,216,2,365,9,-467,3,547,2,-543,2,414,3,-132,2,186,1,-128,1,-293,5,496,1,-490,1,303,6,-265,2,188,3,27,5,-455,2,-3715,16,58,2,-1046,5,999,6,1377,5,-1377,1,4469,17,18,5,-1107,6,1087,2,-2377,1,2413,3,-3168,7,3147,3,14,1,0,2,-2563,1,-3273,5,5870,6,-1741,1,1749,1,-5850,8,4101,14,1771,11,4,5,-5919,17,5950,10,-10,12,32,5,-1433,6,1444,22,-4640,2,2371,1,-2505,19,3573,12,1230,10,37,18,-57,2,77,7,6,17,-2361,1,2348,6,-9725,6,9755,24,-7,7,2,1,1,5,-54,9,91,1,-131,14,-4722,5,4860,6,-77,7,-6063,9,6178,3,-84,1,0,1,-4814,1,4755,2,58,1,-33,5,-4641,7,4758,10,-176,1,-4631,7,4701,4,21,9,161,1,-11289,2,5004,2,6291,9,-6111,20,6140,8,8,3,-3,10,-3561,1,-1727,2,5307,7,7,9,-5371,8,1266,30,-1958,11,267,1,-629,15,6498,4,-5611,3,5545,45,-1132,10,1182,50,-3622,11,3741,3,4,1,-123,6,135,1,-82,1,-3873,10,906,3,-699,3,2035,10,457,1,1218,48,130,28,-226,14,99,3,-140,20,7,1,179,4,-89,5,-70,2,76,7,-3723,27,3984,3,-2479,7,2503,11,-290,1,-5,8,104,2,-11453,6,11450,11,14,4,168,3,-114,22,20,13,96,17,-1039,9,1060,3,-295,9,55,8,-125,7,-930,2,997,2,-762,5,1127,6,-393,8,211,5,-6728,6,6763,2,-260,8,-6449,9,6929,14,-232,16,-57,2,-6594,2,5568,2,811,4,155,4,385,5,-12100,8,11811,6,-44,6,-5797,2,5655,6,-74,5,215,1,400,1,-57,5,-213,5,6,3,97,1,-31,2,129,9,-282,9,181,5,-180,1,-6681,3,6478,12,227,2,251,6,-4346,2,3769,3,103,5,149,4,358,2,-602,10,295,5,-310,1,-2856,1,3162,2,309,1,-4336,2,4224,8,-198,1,-4,3,4,10,435,10,-734,3,-649,9,1401,14,-26,12,-43,2,-9,2,-479,11,102,4,-179,2,360,2,-177,3,295,3,-206,1,367,6,82,5,-453,1,-5324,4,5321,5,-217,3,507,1,168,6,-567,1,-112,16,564,7,-136,1,-383,2,278,1,349,1,-622,6,611,2,-145,1,-468,2,-103,1,704,1,-222,7,-381,5,383,3,168,2,82,7,-628,5,-6644,1,6440,5,481,3,-230,4,326,1,-373,7,179,4,-1733,16,-127,1,-3039,3,94,24,-516,2,5934,3,-2346,2,-3142,6,4004,4,1481,2,-2343,6,-1389,2,3797,9,-7374,1,0,1,1263,3,0,1,2730,2,3401,6,-4684,1,4690,23,12,6,7,6,-11,4,-12057,3,12076,2,-6821,1,6814,1,14,3,-37,1,-1028,4,-1585,3,1529,1,-3661,1,0,5,4813,2,-1614,3,1602,3,-6265,6,6291,9,9,1,-1620,34,1633,4,17,9,-20,4,38,23,13,8,14,1,7,7,9,4,-6786,16,383,7,6415,12,27,7,0,15,-10,10,-6812,15,6869,4,-6871,9,1,5,-688,6,7568,17,31,15,-6908,26,6793,18,-970,13,1110,3,-40,15,-6885,1,6815,21,-7506,7,7610,6,61,7,-136,7,-6843,1,6932,6,-6930,11,1248,3,5595,39,200,9,-7040,5,6971,18,-20,1,173,34,-7118,22,-5,1,6836,4,110,3,4,1,111,8,-7471,5,406,1,12,1,6874,1,-4666,11,4914,2,-7124,2,7035,11,-7035,3,7044,1,59,1,108,1,-76,1,60,4,-4124,5,4140,1,-365,3,283,2,-7124,7,6873,4,249,5,-221,1,135,8,188,10,-182,9,245,3,-7285,20,7031,9,68,8,-296,25,69,8,-6388,6,-495,3,6793,4,80,14,394,3,-224,1,-108,4,197,7,-4451,2,4672,8,-472,6,-42,2,295,13,-6773,8,6993,7,-292,4,-178,3,564,3,-199,5,-6835,1,6423,3,213,3,394,1,-90,2,-108,4,-4146,1,2544,4,1717,7,2,9,-485,8,-91,1,342,2,-99,2,-7870,5,8079,6,-101,3,222,3,-4285,7,3965,1,456,3,-35,1,70,13,-565,3,5,5,-88,3,690,8,-437,3,267,1,93,7,-442,1,303,7,84,8,-311,1,9,1,0,3,473,2,-571,1,86,10,255,3,-307,3,62,2,440,7,-334,3,-174,1,-193,2,584,3,-500,1,-22,1,587,3,-478,3,115,8,33,5,-12545,3,12394,2,9,1,78,3,8,13,-244,1,458,3,-417,2,419,1,-3235,1,2935,3,-7,5,77,7,330,1,-395,4,499,1,-497,2,511,7,-214,2,-443,2,538,3,90,1,93,3,-185,1,-212,1,-420,2,145,2,-115,4,-5608,3,5897,3,553,3,-730,5,-83,2,674,1,-1,2,181,4,-135,1,-637,1,730,4,0,4,-7731,2,7597,12,81,3,-423,2,-338,1,573,8,101,5,-563,3,461,1,52,3,-42,5,358,6,-465,1,104,3,-7,2,0,4,-26,1,-7548,16,7988,22,8,1,-7526,5,-470,10,5507,12,2530,3,-2676,6,-3310,1,-2834,21,18,7,8753,2,-9,9,-7979,16,8038,3,20,6,-2477,27,2483,5,-70,7,-2723,12,-1256,28,4036,9,-32,4,-2566,3,2633,8,13,1,-4084,3,4049,2,-2557,2,2586,3,-102,2,209,23,35,18,-215,2,235,24,-155,9,204,4,-252,3,43,3,72,3,-36,1,-157,1,39,9,81,5,-37,2,41,2,111,1,-68,3,-7008,6,7098,1,-241,7,92,3,141,4,-127,3,250,4,-84,1,-163,2,44,1,-2620,14,2533,3,-56,4,351,7,-294,11,319,1,-18,6,-9062,4,4754,1,-4833,8,9213,2,-8809,1,4499,1,-1359,1,-3558,1,4190,6,-1521,13,4355,5,2225,2,-3517,6,-2317,6,4223,14,-2440,9,4091,5,12,5,-6445,20,4782,7,1672,5,-16,25,60,5,12,1,-9168,37,122,14,9089,4,-37,21,-7996,7,8036,29,-55,5,57,3,-3,3,-55,2,-7794,1,7851,1,-3,4,-2387,5,-4165,16,-2152,9,8713,1,-11,2,3,1,20,3,-38,2,1,5,48,2,-87,1,-8506,2,8688,1,-63,1,-25,4,12,1,-30,4,-6506,1,-2080,67,8742,5,46,28,-7328,4,-1988,16,9287,5,-1988,26,1971,20,-5172,14,5255,6,4,6,-72,7,-20,17,118,7,-117,5,106,3,-84,4,179,13,-87,4,-12,2,14,14,-117,3,162,7,-46,2,-125,3,230,5,-135,5,-65,5,-22,3,223,5,-190,2,71,11,59,5,-107,5,189,6,68,7,-7387,32,7423,5,1,6,-8,9,-1,1,25,6,20,2,-7940,4,-1904,1,0,3,2085,20,86,5,5361,6,-1393,1,-6137,6,2449,1,0,1,7427,1,-5177,10,5184,4,-9883,5,7468,5,2448,4,-42,2,49,1,-9923,2,4185,2,5738,3,-49,1,-7874,7,556,6,0,4,7375,2,-8596,1,0,1,-167,65,3378,10,-2970,3,8440,24,-10,1,-2036,1,0,2,-3347,4,5362,1,0,8,-8409,7,3127,2,5287,2,-14,6,73,3,-8281,8,8326,3,-105,2,-7775,4,7760,7,103,4,-89,8,107,1,0,2,-9012,5,8883,4,81,1,3,1,-5964,1,5990,9,-5373,6,5272,5,187,2,-49,2,-54,1,-34,2,-60,1,49,2,-27,2,178,2,-54,1,59,1,-36,1,-1,2,-118,1,99,1,-3,10,-8791,6,8880,6,-6225,8,6235,3,-4075,3,-59,4,4140,2,-4081,10,4078,10,-221,8,257,2,-1,2,6,7,-3912,2,-5565,8,9493,2,-689,1,-7085,8,5271,4,2519,2,-705,3,-8958,2,9657,1,-2513,3,-6558,3,7152,3,-3351,6,5303,37,-5558,7,5602,31,-10247,17,2009,13,8273,2,15,2,-25,30,51,1,-9097,6,-895,2,9933,17,-34,4,-14007,2,14140,14,8,1,-10516,9,10496,6,-53,11,-5491,8,5610,4,-156,6,132,1,-7,15,-3601,6,3667,37,-5158,23,1068,7,2237,17,-2429,12,-876,13,5244,8,21,4,-63,4,-6941,2,-1185,1,8129,18,-3920,6,77,7,3838,7,-8217,9,-598,4,8829,6,54,1,-4,1,-46,3,-39,2,-935,1,-4252,1,5306,7,-91,2,-8131,1,0,1,8104,10,-2352,11,2440,9,-67,5,118,1,-23,3,39,2,46,2,-47,8,-165,8,-1574,6,1671,7,3,2,29,8,-55,11,77,4,16,9,-158,4,59,1,4,1,-64,1,-8101,1,6229,3,1933,7,233,1,-9086,12,-3824,7,2812,21,5698,2,-559,6,5016,23,-6772,4,6806,9,-7,1,-9,7,-33,12,-11,4,55,1,-6617,4,6628,4,-73,2,38,1,21,3,-56,13,-9609,2,9737,7,-6987,12,6867,2,14,24,-10516,16,3531,8,7098,6,63,14,-4372,3,-2568,14,6927,1,-43,3,-10636,10,10737,2,-11209,2,11221,8,-14559,2,14523,2,-9,1,18,1,-52,3,-36,7,119,8,0,1,-68,1,83,1,-84,7,54,2,-1729,2,1772,7,-7610,1,1650,6,-1935,28,7948,17,-8796,1,8806,1,-3425,3,-4444,1,7831,1,26,1,0,5,-3,1,-7854,4,7877,10,-9,1,-15,2,25,1,-2608,2,2573,8,-8508,11,-2849,5,441,2,10994,6,5,12,8,2,0,9,28,5,-7430,11,-2370,37,9008,4,-1431,12,2249,1,39,3,-54,1,-5473,2,5479,7,-1448,10,1523,9,-65,2,61,4,-506,3,470,4,40,11,27,8,-11591,4,9249,3,2227,1,95,8,-517,3,-9957,3,4190,3,1567,1,4726,40,-21,2,86,9,-43,7,48,5,-59,4,-110,5,88,1,-93,3,62,4,39,1,-7180,1,7171,1,-63,12,139,6,-78,2,91,5,32,5,14,6,-54,6,-1,3,-42,2,81,8,-38,12,-4379,2,4300,3,129,1,-95,1,-7526,5,7638,6,-10238,3,10121,10,5,2,210,1,-189,2,92,1,-71,2,85,1,68,1,-261,4,66,5,-64,1,216,2,-179,2,70,4,-10152,3,8553,7,1118,38,46,19,686,4,-25,1,-628,11,625,3,-600,1,653,19,-2715,1,2719,1,-23,2,-613,7,617,6,15,3,-9691,2,9659,2,-41,1,125,1,-85,2,-11903,1,0,2,421,3,11576,27,-7919,7,2966,5,-5934,7,-3900,2,3900,21,3251,12,7692,7,25,18,-4452,3,4424,7,-12050,4,12088,6,-63,17,38,4,-6646,2,6662,15,-14869,12,9649,7,-2431,21,7614,2,104,3,-7508,2,7525,5,50,4,-39,39,56,1,-7592,4,7599,7,-8124,8,8142,5,-161,9,-10652,4,10652,7,-6414,3,6617,3,-8929,2,8754,7,-7484,1,-3416,3,10989,2,-29,10,-42,9,-11883,11,11883,1,-20,4,211,3,-68,1,-143,1,-11699,17,11735,14,-78,3,-28,1,-8682,4,9034,2,-7234,2,-1800,2,9028,7,-12396,1,11997,1,12,1,-1,1,-3,1,-8637,1,8642,1,-3,1,22,1,-18,1,67,1,-75,1,9,1,230,1,-211,1,-4,1,-4,1,1,1,2,1,154,1,-164,1,16,1,265,1,-110,1,-157,1,-7952,1,7936,1,22,1,20,1,-31,1,-6,1,3,1,152,1,-113,1,-8,1,-1,1,195,1,-176,1,-17,1,-3,1,292,1,-274,1,206,1,-202,1,-10,1,4,1,-7,1,320,1,-301,1,-13,1,66,1,-4506,1,4457,1,13,1,257,1,-238,1,-34,1,39,1,-15,1,-4,1,17,1,-18,1,-12,1,9,1,19,1,21,1,-3,1,-10,1,16,1,3,1,3,1,-52,1,62,1,-17,1,-10917,1,10991,1,-20,2,206,1,-210,1,17,1,-14,1,23,1,-16,1,64,1,-87,1,18,1,-19,1,7,1,-14972,1,14968,1,10,1,-22,1,-7,1,31,1,-11,1,-16,1,20,1,19,1,18,1,-2,1,1,1,20,1,176,1,-163,1,-7,1,-21,1,31,1,-135,1,113,1,-72,1,64,1,24,1,-75,1,70,1,26,1,-34,1,-9,1,87,1,-79,1,-7,1,2,1,38,1,18,1,4,1,-2,1,14,1,-20,1,7,1,113,1,-98,1,-35,1,7,1,108,1,-68,1,-4,1,-3,1,97,1,-6726,1,6649,1,-1,1,67,1,-46,1,-5,1,-3,1,28,1,16,1,-14,1,-1,1,4,1,22,2,-11025,1,1168,6,7406,4,17,1,0,4,-7260,1,-336,3,7571,1,25,2,-7596,1,43,2,9772,18,-6832,3,7254,8,-9088,2,9090,5,-11982,2,11990,1,-8,4,-4997,4,5025,2,-17,1,-11707,2,11693,1,29,1,13,1,0,6,-9415,13,-3185,2,5169,5,2413,2,5052,1,-4,3,2,1,-12632,16,12645,12,22,13,-12644,14,12646,2,-299,6,297,4,22,9,19,1,4,3,-25,1,25,1,-408,2,384,3,-6397,2,6437,1,-6858,5,6864,1,0,8,-1304,6,-288,1,1,5,-10162,1,5529,6,-6040,8,12296,2,-5,2,-5462,11,-2663,27,-2370,9,860,9,9685,2,13,1,-13,3,0,1,0,1,13,2,-10097,1,10056,1,-11276,1,11325,1,-39,1,10,2,1,3,-11297,1,0,1,11295,2,52,3,-996,2,0,1,-9664,3,1202,18,6667,8,-9115,3,5391,21,6563,9,-12062,3,12073,3,-6570,2,-5811,4,5810,1,6547,11,-11717,9,11046,2,-5852,12,6505,3,-17755,2,17858,9,-6628,4,6574,2,0,2,71,18,-29,8,-11236,4,4625,2,-5930,8,12605,8,-107,8,60,5,-12526,8,12464,8,42,10,-12338,1,12416,5,-37,5,-82,8,91,5,-122,11,221,3,-11188,6,8279,7,2688,2,184,5,-180,4,-15559,2,-2216,7,11246,2,6744,3,-117,15,-336,2,272,1,71,1,6,7,-137,2,192,1,-18,4,-40,2,129,6,7,3,-78,1,-93,1,-3,5,37,1,5,2,200,3,-11893,3,-1331,5,7532,1,-1272,6,5971,6,-10763,6,3773,4,8022,3,-13301,1,870,1,-822,1,6057,3,-639,1,0,21,1853,6,6012,1,-6624,11,-128,4,6752,17,21,6,-9712,9,9707,10,-6177,1,149,2,6027,4,-6176,1,6187,6,53,5,3,1,0,3,-12532,8,10817,6,971,10,-1163,41,-10483,10,-5,10,1220,6,11188,10,54,7,-3234,1,3258,10,-12942,18,11140,3,1857,14,-10938,1,2221,18,7541,4,-4635,7,-6873,19,9194,4,3349,1,206,10,-46,4,-9364,9,4302,2,-1870,2,1738,1,968,1,-260,4,-4797,8,2517,23,-2598,11,9411,1,-57,12,76,5,-143,16,-3929,2,247,4,3794,10,-62,4,2,4,-5329,4,-1682,1,-5184,23,1195,4,-1209,1,12207,4,-9288,3,-155,1,4805,13,-2746,2,7335,3,229,4,-52,7,-29,16,-11690,1,10322,6,-12289,6,13866,2,-212,1,87,16,69,4,-12291,3,12239,6,-88,5,-3117,9,-9087,2,8981,2,3224,2,-167,1,177,5,-11033,2,4309,1,6715,8,-11,28,88,1,-9,5,-8661,5,8615,30,-184,4,157,6,-9533,5,6313,6,1339,16,-10320,13,12273,1,-241,4,-10938,1,11189,6,-12861,3,12765,9,149,1,-7497,2,7728,4,-2113,5,1741,2,-12296,10,12592,5,-1,2,-26,1,-352,7,-9276,1,-153,3,2913,3,1070,11,5826,2,-293,3,164,2,123,4,-6691,1,0,3,6394,4,14,1,-180,2,256,3,-93,2,225,8,77,7,-5431,1,4938,1,455,2,-60,4,-2586,6,2774,9,141,8,-529,1,-2402,1,2786,2,-584,2,634,3,-11061,3,11099,4,-478,1,-12566,5,13106,1,-447,7,-102,3,216,3,-185,2,-1819,2,2391,10,-587,8,-13637,7,516,4,13502,1,-372,1,460,6,16,7,-7,1,-13247,4,12796,3,-1835,1,1823,4,-1820,1,1,3,-14206,7,16542,2,-684,1,743,1,-96,1,-19,1,-2,3,-7091,3,6803,2,-6582,2,6926,2,-716,1,-11226,3,11944,1,-635,8,-11309,1,12099,2,-6942,1,-90,3,6972,2,-521,2,367,4,-554,2,-94,9,-12609,2,7650,11,5518,3,-6672,2,6477,2,538,16,-9417,4,-2154,1,-1160,5,12766,1,-11,3,-12888,4,4797,4,-6181,8,14301,11,-64,18,-3527,12,-661,27,4292,25,48,8,-4340,24,4377,14,8,10,18,2,-87,12,101,3,-22,1,-4395,1,65,2,4242,32,-24,1,95,27,-106,10,-4948,7,4946,2,-13,7,-4914,4,116,3,4981,2,-4375,10,4346,2,-24,20,-114,6,1,3,8,1,-614,17,883,8,-27,4,4,2,-246,3,102,3,214,1,-126,6,96,21,-314,9,219,3,-87,3,-135,4,100,5,-78,6,2,4,196,1,-200,7,207,1,132,1,39,1,-261,1,138,3,-225,1,196,10,-64,3,-9770,1,9687,5,257,1,-100,2,-13522,6,13361,5,-53,3,402,2,-313,1,329,8,11,2,-14635,4,13818,9,-7651,1,-4555,1,-1670,1,4135,4,8669,1,-11638,2,-441,1,441,11,10646,5,246,8,-11333,3,568,12,1761,3,4373,5,7340,11,-34,6,-2675,1,-8158,43,-846,2,-402,9,12147,4,-10880,3,10809,1,96,3,-10905,1,10915,3,-27,17,64,3,-1815,5,-12199,3,3076,1,10943,6,-12268,3,2031,2,10188,2,-50,6,-13863,4,13847,6,-2698,4,-7676,11,-1333,4,1333,1,10420,1,46,1,-2659,1,-82,3,2798,3,-14950,8,14941,4,-45,2,0,6,-54,6,-10814,1,10771,7,95,3,-29,2,-52,2,-2579,6,2589,2,-9302,3,9254,3,65,2,-10812,12,11021,6,-12401,2,3883,1,5961,1,0,5,-5732,6,3720,5,-4632,2,4525,1,-10371,13,-5,9,15066,5,41,2,-9256,3,9242,3,-27,1,-1,1,1,1,2,1,-8305,1,8310,1,3,1,2,1,15,1,-9242,1,9247,1,-11,1,30,1,-26,1,1,1,9,1,3,1,5,3,-9235,1,5875,4,-11660,4,4975,10,10089,11,7,2,-12,2,17,2,-9,6,-6161,3,6187,22,-10152,7,-7074,4,109,5,5377,2,-1887,11,3175,2,-3255,5,6259,4,7510,7,-13783,26,40,7,1872,4,-3143,16,1303,2,13695,10,-12534,4,1684,1,11,6,2913,4,-2722,14,8,8,10764,18,-144,6,22,1,-10852,20,10917,7,-13932,11,14023,3,-13860,7,219,15,13575,17,-13582,5,13669,7,63,9,-13786,5,13589,7,-11173,6,-2618,5,91,5,356,2,2914,1,10399,3,-33,1,-11143,1,-2122,2,-8,1,3296,3,398,1,9848,7,-63,3,-13439,11,11986,3,-6524,4,-5692,6,3360,2,-3757,2,557,2,13413,1,164,1,-10694,11,-3471,1,13959,1,-17206,2,1950,1,15551,1,-15551,5,15492,4,-10574,1,10630,6,-387,1,8,1,-6,1,1,1,138,1,194,1,-319,1,-4,1,2,1,389,1,-382,1,1,1,-10174,1,10171,1,349,1,-358,1,14,1,-6,1,265,1,-42,1,66,1,-229,1,-49,1,8,1,12,1,-22,1,187,1,-13841,1,13658,1,216,1,-202,1,-3,1,-7,1,25,1,5,1,-13772,1,13792,1,6,1,253,1,-257,1,-7,1,-10532,1,10510,1,-13779,1,13982,1,-167,1,-6,1,-4,1,2,1,281,1,-285,1,52,1,-2,1,-30,1,25,1,-22,1,7,1,12,1,36,1,-27,1,-16,1,-4,1,36,1,-41,1,2,1,-1,1,-11,1,1,1,106,1,-91,1,1,1,-15067,1,15178,1,-129,1,279,1,-215,1,2,1,-5,1,-4,1,-10748,1,10759,1,-13,1,16,1,-23,1,25,1,-4,1,-8046,1,8083,1,45,1,-41,1,47,1,130,1,-175,1,-24,1,-7,1,23,1,18,1,-43,1,39,1,-24,1,3,1,16,1,-162,1,134,1,17,1,190,1,-201,1,68,1,-10,1,-26,1,46,1,-62,1,27,1,45,1,-19,1,1,1,-30,1,9,1,15,1,150,1,-14058,1,13899,1,7,1,-20,1,40,1,-48,1,-1,1,75,1,116,1,-134,1,7,1,3,1,-9,1,-54,1,56,1,-9,1,41,1,5,1,-19,1,2,1,-1,1,46,1,-4,1,3,1,-14,1,-98,1,-13471,1,13652,1,-42,1,-9,1,43,1,-4438,8,-2966,7,-1536,2,-3112,2,-3666,1,10315,3,1115,2,-11430,4,13379,3,-8056,10,-4652,2,15245,9,-6450,10,6468,4,-6588,15,48,3,929,1,-907,6,51,9,88,18,-9463,5,0,4,-28,18,1289,1,3748,2,10920,7,-12551,1,0,3,-3468,4,15697,2,-5992,6,-8389,7,14679,2,-11933,12,-2983,18,14618,6,363,7,29,4,-7331,1,7339,1,-118,1,1,1,2,1,-1,1,3,1,-1,1,11,1,54,1,-10123,1,-1863,1,11928,1,5,1,-4,1,1,1,-3,1,15,1,70,1,-77,1,-4,1,-15903,1,15960,1,-35,1,-17,1,12,1,-8,1,6,1,-2,1,7,1,-4,1,5,1,-3,1,-10912,1,10983,1,-60,1,-4,1,-18,1,17,1,-1,1,81,1,-76,1,-2,1,41,1,-25,1,-4,1,9,1,-8,1,20,1,7,1,-2,1,43,1,-56,1,-2,1,56,1,-59,1,8,1,-1,1,7,1,13,1,1,1,16,1,-10,1,-1,1,3,1,1,1,13,1,-392,1,388,1,1,1,5,1,2,1,-7335,7,2648,2,0,5,4784,17,17,4,-2,7,12,8,-21,4,-1,15,22,10,38,65,-31,7,83,2,-15918,12,9688,8,6246,9,13,8,-1739,2,-7074,6,8799,1,52,1,-10859,9,10829,14,-5202,10,5132,8,-10050,1,10102,1,-9615,4,9526,4,77,1,-11,1,-11,3,124,1,-42,3,-4425,8,-1909,3,-7359,8,13644,1,0,6,-73,1,72,7,-62,1,84,1,-17,2,-56,4,108,1,-81,1,78,2,68,5,-119,1,158,6,-70,4,46,1,29,4,-13,3,-3666,3,-12522,2,16222,14,-2,6,-16220,7,584,14,5630,5,10045,18,-8980,4,-1065,29,-1116,2,11200,18,2,24,-3321,1,3382,2,-9082,13,-954,14,6654,1,-6187,8,9455,1,1,1,1,1,6,1,-1,1,3,1,117,1,-10160,1,10129,1,-75,1,128,1,-9117,1,9017,1,105,1,-108,1,1,1,3,1,-24,1,7,1,119,1,-104,1,3,1,1,1,11,1,1,1,68,1,-70,1,-1,1,-2,1,-2,1,15,1,2,1,7,1,11,1,3,1,-12,1,8,1,-7,1,14,1,-13,1,-3,1,23,1,8,1,-12,1,13,1,-4,1,41,1,-28,1,-1,1,-6,1,8,1,7,1,7,6,-4074,3,4152,3,-15620,1,0,1,0,5,15616,1,13,1,-2,3,-15885,36,15906,11,33,3,-25,6,-12494,2,136,1,-2976,6,2980,1,-2220,5,14089,1,-16286,1,11192,8,5620,5,-10,2,-11946,2,1021,7,10970,2,-12430,4,12373,10,5,2,-14598,4,636,5,13972,2,-8624,1,-6608,1,15219,6,-15661,2,15662,4,-428,7,431,4,-16441,1,7826,1,8600,2,-12329,1,12320,3,-12319,3,12310,1,31,7,-11938,2,11991,1,-51,1,-3,1,-8959,4,9084,2,-5497,2,5410,6,63,3,-98,1,-6131,3,1650,1,4451,1,72,2,78,2,-154,3,-30,2,41,3,16,3,17,2,-48,1,0,3,-15386,2,15516,1,-21,24,-10453,25,972,8,9605,15,-15501,6,15545,1,1,4,-8875,10,-5526,5,11043,3,3325,2,-16973,10,16981,2,-16600,3,16629,3,-17010,9,16984,2,-13,1,-16971,1,17030,16,-1718,1,1634,6,62,3,-22,2,61,2,-62,2,22,3,32,1,-83,12,154,1,11,1,-92,1,-17091,30,15443,5,0,23,-2346,3,-3382,3,7486,2,14,11,-5,6,-17228,2,17228,3,-11551,10,-4355,1,15926,5,-11,10,-1776,1,-11970,4,13771,1,-2362,2,2361,2,-1,1,-16095,1,4355,4,11817,1,-2299,1,-2800,1,-9731,2,-1092,2,15929,20,-12142,6,3751,18,-10128,35,15914,36,-10684,7,-2396,11,3653,4,12085,7,-4809,2,4817,56,-15531,22,7079,50,3863,6,501,3,4253,13,-6684,10,-6467,30,13145,16,-13145,4,10516,6,-9454,1,12106,13,-8712,17,137,9,4282,26,1445,14,-13598,8,7950,5,1611,1,6969,9,-3635,11,3784,2,-1716,17,1693,3,5,3,-11728,7,1546,9,10121,8,-16690,9,16658,4,-5113,4,5062,10,-18830,3,18748,3,-16267,9,16152,1,276,7,11,7,-3009,13,-15903,5,19003,1,-8,3,-16690,1,-2307,2,2254,4,16452,2,220,13,-126,13,-127,1,0,9,-6773,9,-9687,4,9747,2,-1970,4,8978,1,-14213,1,13807,3,368,2,-5157,8,4854,1,104,1,-16559,2,-2169,1,18988,3,-481,1,2,1,1,1,9,1,-5,1,-1,1,2,1,-4,1,34,1,3,1,-19,1,-3,1,46,1,-41,1,-6,1,355,1,-333,1,353,1,-357,1,14,1,32,1,-27,1,30,1,-13374,1,13349,1,7,1,-2672,1,2661,1,190,1,53,1,-235,1,-1,1,-11,1,-9928,1,9953,1,388,1,-404,1,25,1,-38,1,36,1,-33,1,17,1,-21,1,58,1,115,1,-71,1,-12181,1,12134,1,-4858,1,4854,1,34,1,-24,1,-5,1,38,1,-24,1,38,1,1,1,-45,1,-1,1,-1,1,87,1,-68,1,-29,1,556,1,-602,1,84,1,-15,1,-27,1,25,1,-1,1,5,1,-31,1,11,1,511,1,-450,1,54,1,-12,1,-38,1,111,1,38,1,-101,1,68,1,-31,1,20,1,288,1,-374,1,429,1,-437,1,60,1,-16,1,-11,1,257,1,-79,1,-194,1,-5,1,59,1,-35,1,-14,1,346,1,-354,1,278,1,-298,1,27,1,-31,1,29,1,130,1,-111,1,-51,1,45,1,-16505,1,16471,1,392,1,-355,1,-40,1,35,1,80,1,287,1,-4604,1,4291,1,95,1,-71,1,215,1,-106,1,-167,1,223,1,-166,1,-11,1,-4804,1,4906,1,-92,1,-7,1,-47,1,3,1,33,1,-11,1,-13,1,49,1,304,1,1,1,-372,1,8,1,8,1,28,1,7,1,44,1,-12,1,116,1,-17,1,-58,1,-7,1,-13,1,6,1,31,1,-63,1,20,1,20,1,2,1,3,1,334,1,-356,1,-8,1,22,1,303,1,-276,1,-57,1,59,1,-60,1,24,1,1,1,85,1,-125,1,59,1,-26,1,76,1,-29,1,-1,1,145,1,-98,1,-34,1,-4437,1,4461,1,-3016,1,-5727,1,8805,1,-74,1,16,1,20,1,-55,1,53,1,98,1,-67,1,135,1,-161,1,69,1,-31,1,-18,1,-3,1,223,1,-197,1,6,1,-5,1,12,1,-25,1,6,1,-34,1,-1681,1,1724,1,151,1,-8888,1,8782,1,-6,1,1,1,-16,1,-194,1,211,1,3,1,-16,1,-14,1,-11768,1,11781,1,68,1,9,1,-13,1,-25,1,110,1,-82,1,90,1,-77,1,89,1,-128,1,32,1,49,1,-23,1,3,1,-4,1,-16812,1,16825,1,21,1,15,1,-5,1,19,1,1,9,261,10,16,2,-13959,19,-3469,4,0,2,661,3,188,11,16621,5,-11889,4,11846,11,-11783,1,-260,3,2427,13,-7811,1,5156,2,5390,2,-10546,5,7912,1,8004,6,1505,1,2,1,1,1,3,1,2,1,-1,1,-16440,1,16519,1,-71,1,57,1,-55,1,-3,1,5,1,1,1,-8,1,-13526,1,13538,1,1,1,15,1,-5450,1,5511,1,-60,1,4,1,38,1,-46,1,-2,1,-2,1,10,2,6,1,-5,1,33,1,-15,1,-5,1,-3,2,9,1,-2,1,-55,1,54,1,-9569,1,9585,1,-9,1,29,1,-9706,1,9685,1,9,1,-4,1,2,1,3,1,9,1,6,1,-14618,1,0,6,-81,5,-2293,2,958,2,15,3,-17,2,9021,2,-5217,3,-3574,14,-167,2,-11,2,3586,12,-3555,4,16054,4,12,1,0,1,-17166,5,17134,6,-7614,7,7613,3,-12478,2,3734,1,-8449,2,1129,5,3752,7,-3576,5,15939,1,-72,4,-15865,7,15938,4,-1444,2,1409,1,-15806,2,3279,2,12602,3,-1493,5,1492,2,-7704,7,7705,2,3,1,-76,3,111,1,0,3,-17100,4,2849,8,-3610,4,17868,6,-12155,4,-2007,1,10002,3,-12977,2,17155,1,-12173,1,12171,3,-18438,2,10996,1,7427,2,-12156,11,1241,2,-7562,9,9892,12,5494,3,-6710,3,1523,4,-2474,1,10614,1,-3914,11,1668,2,2246,7,202,2,-14379,15,10932,2,-6881,3,10331,5,-14,2,58,2,-17254,2,7342,1,-7343,9,17291,8,2,2,6,1,-5,11,17,5,-5840,15,5862,6,-7555,11,7572,2,-14755,3,2684,14,11788,4,-14403,2,7069,23,-4454,4,5641,2,6435,3,-18610,2,14781,1,3859,3,-5914,24,2055,1,3911,1,-24,1,-5942,1,5944,1,6,1,6,1,5,1,-2,2,17,4,-4525,9,4533,4,-17192,19,4671,18,12541,7,-18478,2,2393,7,8474,4,7628,1,-7602,3,4748,1,-4748,13,7585,6,-3367,4,3437,1,-12817,3,-1279,2,-4273,1,0,3,11245,5,4574,4,2482,8,-12749,6,12739,1,1,1,1,1,4,1,-2,1,1,1,2,1,2,1,7,1,-6,1,8,1,-5,1,-12546,1,12544,1,3,1,1,1,97,1,-89,1,-1,1,3,1,7,1,15,1,2,1,-22,1,-10459,1,625,1,9844,1,-29,1,50,1,-13,1,-7622,1,7631,1,-7657,1,0,1,7672,1,6,1,6,1,-4,1,5,1,-4,1,-2,1,38,1,-17,1,-18388,1,18379,1,12,1,-6622,1,6628,1,1,1,4,1,4,1,-18060,9,520,2,-450,7,4158,9,878,1,0,4,13036,4,-18142,2,0,1,4228,1,13889,1,1,1,1,1,7,1,2,1,4,1,-1,1,5,1,-13030,1,13036,1,0,2,-6765,2,6786,2,4,16,16,13,10,4,-15,7,-7197,2,-11090,6,1077,8,-1623,2,12635,3,6218,3,7,8,-5869,4,-1358,5,-3,4,-10053,4,10068,14,7189,3,-7175,1,7257,6,-91,6,6,5,37,3,-4,4,-42,1,4,1,-1,1,3,1,78,1,-74,1,83,1,-82,1,1,1,2,1,2,1,3,1,44,1,-32,1,-5,1,3,1,3,1,-11,1,24,1,70,1,-73,1,-5,1,10,1,-11,1,12,1,-10,1,12,1,5,1,-3,1,-18874,1,18873,1,3,1,7,1,-1,1,6,1,-5897,1,5919,1,6,1,-7,1,9,1,31,1,-29,1,2,1,-9,1,4,1,10,1,1,1,-4,1,-7265,1,7272,1,22,3,-6405,19,6475,3,-18425,15,11208,7,7226,2,-13367,2,0,22,13411,3,-18769,13,18741,6,44,15,-17831,5,17820,27,42,7,-14000,6,7714,2,250,7,6039,7,-5417,5,-8044,1,10366,1,3138,14,-14509,5,-195,15,307,3,14255,1,1,1,4,1,3,1,-1,1,-13369,1,13375,1,8,1,161,1,-142,1,7,1,4,1,-6,1,-7,1,100,1,-102,1,13,1,-12,1,4,1,134,1,-131,1,117,1,-18881,1,18788,1,-14435,1,14525,1,-89,1,-4,1,-11,1,137,1,-1,1,-105,1,86,1,-85,1,-10,1,7,1,16,1,-1,1,-1,1,-8,1,7,1,64,1,-10,1,-41,1,20,1,-9,1,19,1,-33,1,43,1,-19,1,-3,1,13,1,11,1,-5,1,6,1,11,1,16,1,6,1,1,1,-2,4,70,4,-6652,6,-12635,4,16058,2,-3358,9,201,6,6396,2,-6435,3,6452,3,-6582,1,169,1,-12901,1,12862,1,6458,3,13,10,-19417,3,7427,4,-6193,4,0,1,18196,5,-19478,13,10003,2,9258,3,-12942,7,6499,1,-2773,12,8700,6,754,2,25,3,-13692,1,0,1,12290,1,-16597,1,16711,1,-12404,1,12359,1,-12359,1,0,1,12397,2,-10983,1,0,8,12313,2,-7825,6,-4575,9,7272,4,5147,10,-2,9,-2404,28,-2861,38,-14871,10,15680,1,-11712,19,16031,9,168,1,0,12,55,47,-20221,6,1,1,0,26,1,24,20315,6,46,6,-175,9,215,10,-46,25,-21,5,-182,1,1,2,28,1,-15,1,7,1,5,2,6,1,7,1,2,1,11,1,234,1,-237,1,8,1,-1,1,-8,1,7,1,206,1,-210,1,3,1,-4529,1,4539,1,25,1,-9,1,-12,1,8,1,92,1,-102,1,196,1,13,1,-194,1,-16268,1,16283,1,-29,1,187,1,-410,1,444,1,-73,1,8,1,-112,1,90,1,20,1,-119,1,-90,1,97,1,-17,1,71,1,-43,1,4,1,20,1,-21,1,22,1,-10,1,3,1,3,1,-10,1,5,1,14,1,-21,1,13,1,82,1,-70,1,-32,1,137,1,-85,1,7,1,89,1,-113,1,36,2,-8,1,-3,1,-20335,1,20337,1,-9,3,-10,1,33,1,18,1,-5,1,-5,1,-3,1,4,1,-10,1,-3,1,23,1,11,1,10,1,1,1,-14,1,-6,1,-10,2,17,1,26,1,-3,1,4,1,-5,1,29,2,-8,1,-4,4,-19064,4,17622,1,-17622,2,17651,1,-17658,4,0,11,-1233,5,20463,4,-13,1,-1588,17,8,30,-18868,10,-1,26,19206,3,1347,18,-15858,6,15774,14,-20467,32,20584,6,-20583,5,13987,6,4885,9,-5855,6,5870,4,-18886,1,0,4,6805,11,13797,24,-11197,4,11294,11,-20698,11,0,19,20536,1,-8,1,-100,1,4,1,-1547,1,1560,1,-2,1,-2,1,229,1,-206,1,163,1,-183,1,17,1,29,1,100,1,142,1,-237,1,-10,1,8,1,-20,1,13,1,-2,1,-2,1,226,1,-232,1,208,1,-12,1,-170,1,1,1,18,1,-14,1,15,1,-4,1,10,1,-14,1,21,1,3,1,-2,1,0,1,15,1,-3,1,-11,1,161,1,-151,1,5,1,17,1,33,1,-41,1,20,1,-15,1,-3,1,2,1,27,1,1,1,-19,1,116,1,-83,1,9,1,-7,1,33,1,-37,1,41,1,-26,1,4,1,33,1,-8,1,-16,1,7,1,1,1,7,1,-5,1,-8,1,34,1,68,1,-71,1,7,1,21,1,-9,1,12,1,6,1,2,2,13,1,-14,1,19,1,3,1,12,1,-3,1,-19124,4,340,3,9151,1,-8206,1,17937,3,-8675,3,0,2,0,5,8691,12,-20557,9,20569,4,-8703,2,8718,4,-1859,5,-12400,5,0,1,12400,3,1863,3,-12510,1,-8067,1,0,7,20603,8,6,2,-6891,4,6899,2,-4080,5,4087,5,-17804,10,-2034,10,19856,2,-2017,2,2008,1,8,7,20,6,-6178,1,61,2,5402,1,23,3,694,1,3,1,7,6,-10322,2,-9483,2,17876,28,1968,6,4,5,-19001,2,19012,3,-1825,7,-18817,1,5870,3,10080,1,-1707,1,-14243,1,14243,1,-6865,17,-6517,2,19809,2,-18925,2,-194,1,14676,9,4459,3,-7678,9,-5630,1,13285,1,1,1,2,1,8,1,2,1,-8,1,7,1,-4,1,10,1,6,1,-4460,1,4466,1,5,1,-9371,1,-10060,2,0,1,-1506,1,11566,6,9402,1,-9402,1,9400,1,1,1,-20757,1,11083,1,8830,1,-19913,3,1548,1274,19508,2,-118,14,6,4,882,10,-3,4,-270,1,-88,1,338,2,10,394,-41822,1,0,1,-21,1,0,1,1001,1,0,15,-982,1,0,1,-20,1,0,1,863,1,0,1,-851,1,0,1,2,1,0,1,0,1,0,21,-14,1,0,165,7,1,0,9,-2,1,13,13,-16,1,0,1,8,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,3,1,0,1,0,1,0,3,1,1,0,1,0,1,0,1,552,1,0,1,-551,1,0,1,0,1,0,5,5,1,0,1,1,1,0,16,-19,1,8,1,1,1,1,1,4,1,0,7,-11,16,-6,3,13,1,0,3,-11,1,5,1,-6,1,0,1,4,1,0,7,1,1,0,1,4,1,0,1,3,1,0,1,4,1,0,1,1,1,0,1,-11,1,-3,1,2,1,5,1,-3,1,8,1,-6,1,9,1,-10,1,14,1,-22,1,0,1,21,1,0,1,-2,1,0,1,-20,1,0,1,8,1,0,1,12,1,0,5,-18,1,16,1,7,1,-22,1,0,1,15,1,0,870,-18,1,133,1,-129,1,0,1,0,1,1,1,1,1,5,1,0,1,0,1,1,1,1,1,0,1,1,1,0,2,259,1,0,5,-256,1,0,1,0,1,0,1,0,8,3,1,3,1,0,1,0,1,0,1,0,1,0,1,0,1,1,2,-17,1,4,1,0,1,9,5,-20,1,872,1,-440,11,-415,4,-9,4,16,1,-24,1,9,1,-5,5,13,2,5,4,-10,4,-5,2,17,1,-10,2,-8,2,1,1,18,11,-25,1,1,3,16,2,5,1,-4,4,3,1,-3,4,-7,1,-9,3,13,4,-5,1,-7,21151,-5,131,1540,1,0,54,-1524,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,12200,1,10,1,1,1,-12,1,250,1,-9,1,-81,1,2,1,2,1,2,1,2,1,58,1,2,1,2,1,-36,1,57,1,-90,1,2,1,2,1,2,1,2,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,-93,1,99,1,3,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,4,1,-90,1,1,1,202,1,-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,864,-12566,53444,-12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,2,2,1,1,3,3,3,3,1,1,3,3,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,2,2,1,1,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,-24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,2,4,4,1,1,1,1,1,1,1,1,1,1,1,1,2,-24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-17,1,1,3,-9,1,1,1,16,1,834,1,-847,1,21,1,-18,1,7,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-1,1,852,1,-847,1,5,1,543,1,-544,1,848,1,1,1,-21,1,-851,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-18,1,0,1,10,1,929,1,-376,1,-552,1,7,1,-22,1,1,1,16,1,834,1,-847,1,21,1,-18,1,7,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-1,1,852,1,-847,1,5,1,543,1,-544,1,848,1,1,1,-21,1,-851,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-18,1,0,1,10,1,929,1,-376,1,-552,1,7,1,-22,1,1,1,16,1,834,1,-847,1,21,1,-18,1,7,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-1,1,852,1,-847,1,5,1,543,1,-544,1,848,1,1,1,-21,1,-851,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-18,1,0,1,10,1,929,1,-376,1,-552,1,7,1,-22,1,1,1,16,1,834,1,-847,1,21,1,-18,1,7,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-1,1,852,1,-847,1,5,1,543,1,-544,1,848,1,1,1,-21,1,-851,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-18,1,0,1,10,1,929,1,-376,1,-552,1,7,1,-22,1,1,1,16,1,834,1,-847,1,21,1,-18,1,7,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-1,1,852,1,-847,1,5,1,543,1,-544,1,848,1,1,1,-21,1,-851,1,1,1,23,1,827,1,-847,1,21,1,-12,1,1,1,-6,1,2,1,848,1,-846,1,1,1,848,1,-847,1,849,1,-848,1,-13,1,12,1,5,1,5,1,543,1,-544,1,848,1,-849,1,-18,1,0,1,10,1,929,1,-376,1,-552,1,7,1,-17,1,0,3,9,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,22,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,22,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,22,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,22,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,6401,22,1,0,1,-6,1,-23,1,19,1,-4,1,18,1,-12,1,-16,1,1,1,1,1,22,1,0,1,0,3,-14,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,-23,1,15,4,-17,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,-25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-10,92,-15,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,];
const entities={AElig:198,AMP:38,Aacute:193,Abreve:258,Acirc:194,Acy:1040,Afr:120068,Agrave:192,Alpha:913,Amacr:256,And:10835,Aogon:260,Aopf:120120,ApplyFunction:8289,Aring:197,Ascr:119964,Assign:8788,Atilde:195,Auml:196,Backslash:8726,Barv:10983,Barwed:8966,Bcy:1041,Because:8757,Bernoullis:8492,Beta:914,Bfr:120069,Bopf:120121,Breve:728,Bscr:8492,Bumpeq:8782,CHcy:1063,COPY:169,Cacute:262,Cap:8914,CapitalDifferentialD:8517,Cayleys:8493,Ccaron:268,Ccedil:199,Ccirc:264,Cconint:8752,Cdot:266,Cedilla:184,CenterDot:183,Cfr:8493,Chi:935,CircleDot:8857,CircleMinus:8854,CirclePlus:8853,CircleTimes:8855,ClockwiseContourIntegral:8754,CloseCurlyDoubleQuote:8221,CloseCurlyQuote:8217,Colon:8759,Colone:10868,Congruent:8801,Conint:8751,ContourIntegral:8750,Copf:8450,Coproduct:8720,CounterClockwiseContourIntegral:8755,Cross:10799,Cscr:119966,Cup:8915,CupCap:8781,DD:8517,DDotrahd:10513,DJcy:1026,DScy:1029,DZcy:1039,Dagger:8225,Darr:8609,Dashv:10980,Dcaron:270,Dcy:1044,Del:8711,Delta:916,Dfr:120071,DiacriticalAcute:180,DiacriticalDot:729,DiacriticalDoubleAcute:733,DiacriticalGrave:96,DiacriticalTilde:732,Diamond:8900,DifferentialD:8518,Dopf:120123,Dot:168,DotDot:8412,DotEqual:8784,DoubleContourIntegral:8751,DoubleDot:168,DoubleDownArrow:8659,DoubleLeftArrow:8656,DoubleLeftRightArrow:8660,DoubleLeftTee:10980,DoubleLongLeftArrow:10232,DoubleLongLeftRightArrow:10234,DoubleLongRightArrow:10233,DoubleRightArrow:8658,DoubleRightTee:8872,DoubleUpArrow:8657,DoubleUpDownArrow:8661,DoubleVerticalBar:8741,DownArrow:8595,DownArrowBar:10515,DownArrowUpArrow:8693,DownBreve:785,DownLeftRightVector:10576,DownLeftTeeVector:10590,DownLeftVector:8637,DownLeftVectorBar:10582,DownRightTeeVector:10591,DownRightVector:8641,DownRightVectorBar:10583,DownTee:8868,DownTeeArrow:8615,Downarrow:8659,Dscr:119967,Dstrok:272,ENG:330,ETH:208,Eacute:201,Ecaron:282,Ecirc:202,Ecy:1069,Edot:278,Efr:120072,Egrave:200,Element:8712,Emacr:274,EmptySmallSquare:9723,EmptyVerySmallSquare:9643,Eogon:280,Eopf:120124,Epsilon:917,Equal:10869,EqualTilde:8770,Equilibrium:8652,Escr:8496,Esim:10867,Eta:919,Euml:203,Exists:8707,ExponentialE:8519,Fcy:1060,Ffr:120073,FilledSmallSquare:9724,FilledVerySmallSquare:9642,Fopf:120125,ForAll:8704,Fouriertrf:8497,Fscr:8497,GJcy:1027,GT:62,Gamma:915,Gammad:988,Gbreve:286,Gcedil:290,Gcirc:284,Gcy:1043,Gdot:288,Gfr:120074,Gg:8921,Gopf:120126,GreaterEqual:8805,GreaterEqualLess:8923,GreaterFullEqual:8807,GreaterGreater:10914,GreaterLess:8823,GreaterSlantEqual:10878,GreaterTilde:8819,Gscr:119970,Gt:8811,HARDcy:1066,Hacek:711,Hat:94,Hcirc:292,Hfr:8460,HilbertSpace:8459,Hopf:8461,HorizontalLine:9472,Hscr:8459,Hstrok:294,HumpDownHump:8782,HumpEqual:8783,IEcy:1045,IJlig:306,IOcy:1025,Iacute:205,Icirc:206,Icy:1048,Idot:304,Ifr:8465,Igrave:204,Im:8465,Imacr:298,ImaginaryI:8520,Implies:8658,Int:8748,Integral:8747,Intersection:8898,InvisibleComma:8291,InvisibleTimes:8290,Iogon:302,Iopf:120128,Iota:921,Iscr:8464,Itilde:296,Iukcy:1030,Iuml:207,Jcirc:308,Jcy:1049,Jfr:120077,Jopf:120129,Jscr:119973,Jsercy:1032,Jukcy:1028,KHcy:1061,KJcy:1036,Kappa:922,Kcedil:310,Kcy:1050,Kfr:120078,Kopf:120130,Kscr:119974,LJcy:1033,LT:60,Lacute:313,Lambda:923,Lang:10218,Laplacetrf:8466,Larr:8606,Lcaron:317,Lcedil:315,Lcy:1051,LeftAngleBracket:10216,LeftArrow:8592,LeftArrowBar:8676,LeftArrowRightArrow:8646,LeftCeiling:8968,LeftDoubleBracket:10214,LeftDownTeeVector:10593,LeftDownVector:8643,LeftDownVectorBar:10585,LeftFloor:8970,LeftRightArrow:8596,LeftRightVector:10574,LeftTee:8867,LeftTeeArrow:8612,LeftTeeVector:10586,LeftTriangle:8882,LeftTriangleBar:10703,LeftTriangleEqual:8884,LeftUpDownVector:10577,LeftUpTeeVector:10592,LeftUpVector:8639,LeftUpVectorBar:10584,LeftVector:8636,LeftVectorBar:10578,Leftarrow:8656,Leftrightarrow:8660,LessEqualGreater:8922,LessFullEqual:8806,LessGreater:8822,LessLess:10913,LessSlantEqual:10877,LessTilde:8818,Lfr:120079,Ll:8920,Lleftarrow:8666,Lmidot:319,LongLeftArrow:10229,LongLeftRightArrow:10231,LongRightArrow:10230,Longleftarrow:10232,Longleftrightarrow:10234,Longrightarrow:10233,Lopf:120131,LowerLeftArrow:8601,LowerRightArrow:8600,Lscr:8466,Lsh:8624,Lstrok:321,Lt:8810,Map:10501,Mcy:1052,MediumSpace:8287,Mellintrf:8499,Mfr:120080,MinusPlus:8723,Mopf:120132,Mscr:8499,Mu:924,NJcy:1034,Nacute:323,Ncaron:327,Ncedil:325,Ncy:1053,NegativeMediumSpace:8203,NegativeThickSpace:8203,NegativeThinSpace:8203,NegativeVeryThinSpace:8203,NestedGreaterGreater:8811,NestedLessLess:8810,NewLine:10,Nfr:120081,NoBreak:8288,NonBreakingSpace:160,Nopf:8469,Not:10988,NotCongruent:8802,NotCupCap:8813,NotDoubleVerticalBar:8742,NotElement:8713,NotEqual:8800,NotEqualTilde:[8770,824],NotExists:8708,NotGreater:8815,NotGreaterEqual:8817,NotGreaterFullEqual:[8807,824],NotGreaterGreater:[8811,824],NotGreaterLess:8825,NotGreaterSlantEqual:[10878,824],NotGreaterTilde:8821,NotHumpDownHump:[8782,824],NotHumpEqual:[8783,824],NotLeftTriangle:8938,NotLeftTriangleBar:[10703,824],NotLeftTriangleEqual:8940,NotLess:8814,NotLessEqual:8816,NotLessGreater:8824,NotLessLess:[8810,824],NotLessSlantEqual:[10877,824],NotLessTilde:8820,NotNestedGreaterGreater:[10914,824],NotNestedLessLess:[10913,824],NotPrecedes:8832,NotPrecedesEqual:[10927,824],NotPrecedesSlantEqual:8928,NotReverseElement:8716,NotRightTriangle:8939,NotRightTriangleBar:[10704,824],NotRightTriangleEqual:8941,NotSquareSubset:[8847,824],NotSquareSubsetEqual:8930,NotSquareSuperset:[8848,824],NotSquareSupersetEqual:8931,NotSubset:[8834,8402],NotSubsetEqual:8840,NotSucceeds:8833,NotSucceedsEqual:[10928,824],NotSucceedsSlantEqual:8929,NotSucceedsTilde:[8831,824],NotSuperset:[8835,8402],NotSupersetEqual:8841,NotTilde:8769,NotTildeEqual:8772,NotTildeFullEqual:8775,NotTildeTilde:8777,NotVerticalBar:8740,Nscr:119977,Ntilde:209,Nu:925,OElig:338,Oacute:211,Ocirc:212,Ocy:1054,Odblac:336,Ofr:120082,Ograve:210,Omacr:332,Omega:937,Omicron:927,Oopf:120134,OpenCurlyDoubleQuote:8220,OpenCurlyQuote:8216,Or:10836,Oscr:119978,Oslash:216,Otilde:213,Otimes:10807,Ouml:214,OverBar:8254,OverBrace:9182,OverBracket:9140,OverParenthesis:9180,PartialD:8706,Pcy:1055,Pfr:120083,Phi:934,Pi:928,PlusMinus:177,Poincareplane:8460,Popf:8473,Pr:10939,Precedes:8826,PrecedesEqual:10927,PrecedesSlantEqual:8828,PrecedesTilde:8830,Prime:8243,Product:8719,Proportion:8759,Proportional:8733,Pscr:119979,Psi:936,QUOT:34,Qfr:120084,Qopf:8474,Qscr:119980,RBarr:10512,REG:174,Racute:340,Rang:10219,Rarr:8608,Rarrtl:10518,Rcaron:344,Rcedil:342,Rcy:1056,Re:8476,ReverseElement:8715,ReverseEquilibrium:8651,ReverseUpEquilibrium:10607,Rfr:8476,Rho:929,RightAngleBracket:10217,RightArrow:8594,RightArrowBar:8677,RightArrowLeftArrow:8644,RightCeiling:8969,RightDoubleBracket:10215,RightDownTeeVector:10589,RightDownVector:8642,RightDownVectorBar:10581,RightFloor:8971,RightTee:8866,RightTeeArrow:8614,RightTeeVector:10587,RightTriangle:8883,RightTriangleBar:10704,RightTriangleEqual:8885,RightUpDownVector:10575,RightUpTeeVector:10588,RightUpVector:8638,RightUpVectorBar:10580,RightVector:8640,RightVectorBar:10579,Rightarrow:8658,Ropf:8477,RoundImplies:10608,Rrightarrow:8667,Rscr:8475,Rsh:8625,RuleDelayed:10740,SHCHcy:1065,SHcy:1064,SOFTcy:1068,Sacute:346,Sc:10940,Scaron:352,Scedil:350,Scirc:348,Scy:1057,Sfr:120086,ShortDownArrow:8595,ShortLeftArrow:8592,ShortRightArrow:8594,ShortUpArrow:8593,Sigma:931,SmallCircle:8728,Sopf:120138,Sqrt:8730,Square:9633,SquareIntersection:8851,SquareSubset:8847,SquareSubsetEqual:8849,SquareSuperset:8848,SquareSupersetEqual:8850,SquareUnion:8852,Sscr:119982,Star:8902,Sub:8912,Subset:8912,SubsetEqual:8838,Succeeds:8827,SucceedsEqual:10928,SucceedsSlantEqual:8829,SucceedsTilde:8831,SuchThat:8715,Sum:8721,Sup:8913,Superset:8835,SupersetEqual:8839,Supset:8913,THORN:222,TRADE:8482,TSHcy:1035,TScy:1062,Tab:9,Tau:932,Tcaron:356,Tcedil:354,Tcy:1058,Tfr:120087,Therefore:8756,Theta:920,ThickSpace:[8287,8202],ThinSpace:8201,Tilde:8764,TildeEqual:8771,TildeFullEqual:8773,TildeTilde:8776,Topf:120139,TripleDot:8411,Tscr:119983,Tstrok:358,Uacute:218,Uarr:8607,Uarrocir:10569,Ubrcy:1038,Ubreve:364,Ucirc:219,Ucy:1059,Udblac:368,Ufr:120088,Ugrave:217,Umacr:362,UnderBar:95,UnderBrace:9183,UnderBracket:9141,UnderParenthesis:9181,Union:8899,UnionPlus:8846,Uogon:370,Uopf:120140,UpArrow:8593,UpArrowBar:10514,UpArrowDownArrow:8645,UpDownArrow:8597,UpEquilibrium:10606,UpTee:8869,UpTeeArrow:8613,Uparrow:8657,Updownarrow:8661,UpperLeftArrow:8598,UpperRightArrow:8599,Upsi:978,Upsilon:933,Uring:366,Uscr:119984,Utilde:360,Uuml:220,VDash:8875,Vbar:10987,Vcy:1042,Vdash:8873,Vdashl:10982,Vee:8897,Verbar:8214,Vert:8214,VerticalBar:8739,VerticalLine:124,VerticalSeparator:10072,VerticalTilde:8768,VeryThinSpace:8202,Vfr:120089,Vopf:120141,Vscr:119985,Vvdash:8874,Wcirc:372,Wedge:8896,Wfr:120090,Wopf:120142,Wscr:119986,Xfr:120091,Xi:926,Xopf:120143,Xscr:119987,YAcy:1071,YIcy:1031,YUcy:1070,Yacute:221,Ycirc:374,Ycy:1067,Yfr:120092,Yopf:120144,Yscr:119988,Yuml:376,ZHcy:1046,Zacute:377,Zcaron:381,Zcy:1047,Zdot:379,ZeroWidthSpace:8203,Zeta:918,Zfr:8488,Zopf:8484,Zscr:119989,aacute:225,abreve:259,ac:8766,acE:[8766,819],acd:8767,acirc:226,acute:180,acy:1072,aelig:230,af:8289,afr:120094,agrave:224,alefsym:8501,aleph:8501,alpha:945,amacr:257,amalg:10815,amp:38,and:8743,andand:10837,andd:10844,andslope:10840,andv:10842,ang:8736,ange:10660,angle:8736,angmsd:8737,angmsdaa:10664,angmsdab:10665,angmsdac:10666,angmsdad:10667,angmsdae:10668,angmsdaf:10669,angmsdag:10670,angmsdah:10671,angrt:8735,angrtvb:8894,angrtvbd:10653,angsph:8738,angst:197,angzarr:9084,aogon:261,aopf:120146,ap:8776,apE:10864,apacir:10863,ape:8778,apid:8779,apos:39,approx:8776,approxeq:8778,aring:229,ascr:119990,ast:42,asymp:8776,asympeq:8781,atilde:227,auml:228,awconint:8755,awint:10769,bNot:10989,backcong:8780,backepsilon:1014,backprime:8245,backsim:8765,backsimeq:8909,barvee:8893,barwed:8965,barwedge:8965,bbrk:9141,bbrktbrk:9142,bcong:8780,bcy:1073,bdquo:8222,becaus:8757,because:8757,bemptyv:10672,bepsi:1014,bernou:8492,beta:946,beth:8502,between:8812,bfr:120095,bigcap:8898,bigcirc:9711,bigcup:8899,bigodot:10752,bigoplus:10753,bigotimes:10754,bigsqcup:10758,bigstar:9733,bigtriangledown:9661,bigtriangleup:9651,biguplus:10756,bigvee:8897,bigwedge:8896,bkarow:10509,blacklozenge:10731,blacksquare:9642,blacktriangle:9652,blacktriangledown:9662,blacktriangleleft:9666,blacktriangleright:9656,blank:9251,blk12:9618,blk14:9617,blk34:9619,block:9608,bne:[61,8421],bnequiv:[8801,8421],bnot:8976,bopf:120147,bot:8869,bottom:8869,bowtie:8904,boxDL:9559,boxDR:9556,boxDl:9558,boxDr:9555,boxH:9552,boxHD:9574,boxHU:9577,boxHd:9572,boxHu:9575,boxUL:9565,boxUR:9562,boxUl:9564,boxUr:9561,boxV:9553,boxVH:9580,boxVL:9571,boxVR:9568,boxVh:9579,boxVl:9570,boxVr:9567,boxbox:10697,boxdL:9557,boxdR:9554,boxdl:9488,boxdr:9484,boxh:9472,boxhD:9573,boxhU:9576,boxhd:9516,boxhu:9524,boxminus:8863,boxplus:8862,boxtimes:8864,boxuL:9563,boxuR:9560,boxul:9496,boxur:9492,boxv:9474,boxvH:9578,boxvL:9569,boxvR:9566,boxvh:9532,boxvl:9508,boxvr:9500,bprime:8245,breve:728,brvbar:166,bscr:119991,bsemi:8271,bsim:8765,bsime:8909,bsol:92,bsolb:10693,bsolhsub:10184,bull:8226,bullet:8226,bump:8782,bumpE:10926,bumpe:8783,bumpeq:8783,cacute:263,cap:8745,capand:10820,capbrcup:10825,capcap:10827,capcup:10823,capdot:10816,caps:[8745,65024],caret:8257,caron:711,ccaps:10829,ccaron:269,ccedil:231,ccirc:265,ccups:10828,ccupssm:10832,cdot:267,cedil:184,cemptyv:10674,cent:162,centerdot:183,cfr:120096,chcy:1095,check:10003,checkmark:10003,chi:967,cir:9675,cirE:10691,circ:710,circeq:8791,circlearrowleft:8634,circlearrowright:8635,circledR:174,circledS:9416,circledast:8859,circledcirc:8858,circleddash:8861,cire:8791,cirfnint:10768,cirmid:10991,cirscir:10690,clubs:9827,clubsuit:9827,colon:58,colone:8788,coloneq:8788,comma:44,commat:64,comp:8705,compfn:8728,complement:8705,complexes:8450,cong:8773,congdot:10861,conint:8750,copf:120148,coprod:8720,copy:169,copysr:8471,crarr:8629,cross:10007,cscr:119992,csub:10959,csube:10961,csup:10960,csupe:10962,ctdot:8943,cudarrl:10552,cudarrr:10549,cuepr:8926,cuesc:8927,cularr:8630,cularrp:10557,cup:8746,cupbrcap:10824,cupcap:10822,cupcup:10826,cupdot:8845,cupor:10821,cups:[8746,65024],curarr:8631,curarrm:10556,curlyeqprec:8926,curlyeqsucc:8927,curlyvee:8910,curlywedge:8911,curren:164,curvearrowleft:8630,curvearrowright:8631,cuvee:8910,cuwed:8911,cwconint:8754,cwint:8753,cylcty:9005,dArr:8659,dHar:10597,dagger:8224,daleth:8504,darr:8595,dash:8208,dashv:8867,dbkarow:10511,dblac:733,dcaron:271,dcy:1076,dd:8518,ddagger:8225,ddarr:8650,ddotseq:10871,deg:176,delta:948,demptyv:10673,dfisht:10623,dfr:120097,dharl:8643,dharr:8642,diam:8900,diamond:8900,diamondsuit:9830,diams:9830,die:168,digamma:989,disin:8946,div:247,divide:247,divideontimes:8903,divonx:8903,djcy:1106,dlcorn:8990,dlcrop:8973,dollar:36,dopf:120149,dot:729,doteq:8784,doteqdot:8785,dotminus:8760,dotplus:8724,dotsquare:8865,doublebarwedge:8966,downarrow:8595,downdownarrows:8650,downharpoonleft:8643,downharpoonright:8642,drbkarow:10512,drcorn:8991,drcrop:8972,dscr:119993,dscy:1109,dsol:10742,dstrok:273,dtdot:8945,dtri:9663,dtrif:9662,duarr:8693,duhar:10607,dwangle:10662,dzcy:1119,dzigrarr:10239,eDDot:10871,eDot:8785,eacute:233,easter:10862,ecaron:283,ecir:8790,ecirc:234,ecolon:8789,ecy:1101,edot:279,ee:8519,efDot:8786,efr:120098,eg:10906,egrave:232,egs:10902,egsdot:10904,el:10905,elinters:9191,ell:8467,els:10901,elsdot:10903,emacr:275,empty:8709,emptyset:8709,emptyv:8709,emsp13:8196,emsp14:8197,emsp:8195,eng:331,ensp:8194,eogon:281,eopf:120150,epar:8917,eparsl:10723,eplus:10865,epsi:949,epsilon:949,epsiv:1013,eqcirc:8790,eqcolon:8789,eqsim:8770,eqslantgtr:10902,eqslantless:10901,equals:61,equest:8799,equiv:8801,equivDD:10872,eqvparsl:10725,erDot:8787,erarr:10609,escr:8495,esdot:8784,esim:8770,eta:951,eth:240,euml:235,euro:8364,excl:33,exist:8707,expectation:8496,exponentiale:8519,fallingdotseq:8786,fcy:1092,female:9792,ffilig:64259,fflig:64256,ffllig:64260,ffr:120099,filig:64257,fjlig:[102,106],flat:9837,fllig:64258,fltns:9649,fnof:402,fopf:120151,forall:8704,fork:8916,forkv:10969,fpartint:10765,frac12:189,frac13:8531,frac14:188,frac15:8533,frac16:8537,frac18:8539,frac23:8532,frac25:8534,frac34:190,frac35:8535,frac38:8540,frac45:8536,frac56:8538,frac58:8541,frac78:8542,frasl:8260,frown:8994,fscr:119995,gE:8807,gEl:10892,gacute:501,gamma:947,gammad:989,gap:10886,gbreve:287,gcirc:285,gcy:1075,gdot:289,ge:8805,gel:8923,geq:8805,geqq:8807,geqslant:10878,ges:10878,gescc:10921,gesdot:10880,gesdoto:10882,gesdotol:10884,gesl:[8923,65024],gesles:10900,gfr:120100,gg:8811,ggg:8921,gimel:8503,gjcy:1107,gl:8823,glE:10898,gla:10917,glj:10916,gnE:8809,gnap:10890,gnapprox:10890,gne:10888,gneq:10888,gneqq:8809,gnsim:8935,gopf:120152,grave:96,gscr:8458,gsim:8819,gsime:10894,gsiml:10896,gt:62,gtcc:10919,gtcir:10874,gtdot:8919,gtlPar:10645,gtquest:10876,gtrapprox:10886,gtrarr:10616,gtrdot:8919,gtreqless:8923,gtreqqless:10892,gtrless:8823,gtrsim:8819,gvertneqq:[8809,65024],gvnE:[8809,65024],hArr:8660,hairsp:8202,half:189,hamilt:8459,hardcy:1098,harr:8596,harrcir:10568,harrw:8621,hbar:8463,hcirc:293,hearts:9829,heartsuit:9829,hellip:8230,hercon:8889,hfr:120101,hksearow:10533,hkswarow:10534,hoarr:8703,homtht:8763,hookleftarrow:8617,hookrightarrow:8618,hopf:120153,horbar:8213,hscr:119997,hslash:8463,hstrok:295,hybull:8259,hyphen:8208,iacute:237,ic:8291,icirc:238,icy:1080,iecy:1077,iexcl:161,iff:8660,ifr:120102,igrave:236,ii:8520,iiiint:10764,iiint:8749,iinfin:10716,iiota:8489,ijlig:307,imacr:299,image:8465,imagline:8464,imagpart:8465,imath:305,imof:8887,imped:437,in:8712,incare:8453,infin:8734,infintie:10717,inodot:305,int:8747,intcal:8890,integers:8484,intercal:8890,intlarhk:10775,intprod:10812,iocy:1105,iogon:303,iopf:120154,iota:953,iprod:10812,iquest:191,iscr:119998,isin:8712,isinE:8953,isindot:8949,isins:8948,isinsv:8947,isinv:8712,it:8290,itilde:297,iukcy:1110,iuml:239,jcirc:309,jcy:1081,jfr:120103,jmath:567,jopf:120155,jscr:119999,jsercy:1112,jukcy:1108,kappa:954,kappav:1008,kcedil:311,kcy:1082,kfr:120104,kgreen:312,khcy:1093,kjcy:1116,kopf:120156,kscr:120000,lAarr:8666,lArr:8656,lAtail:10523,lBarr:10510,lE:8806,lEg:10891,lHar:10594,lacute:314,laemptyv:10676,lagran:8466,lambda:955,lang:10216,langd:10641,langle:10216,lap:10885,laquo:171,larr:8592,larrb:8676,larrbfs:10527,larrfs:10525,larrhk:8617,larrlp:8619,larrpl:10553,larrsim:10611,larrtl:8610,lat:10923,latail:10521,late:10925,lates:[10925,65024],lbarr:10508,lbbrk:10098,lbrace:123,lbrack:91,lbrke:10635,lbrksld:10639,lbrkslu:10637,lcaron:318,lcedil:316,lceil:8968,lcub:123,lcy:1083,ldca:10550,ldquo:8220,ldquor:8222,ldrdhar:10599,ldrushar:10571,ldsh:8626,le:8804,leftarrow:8592,leftarrowtail:8610,leftharpoondown:8637,leftharpoonup:8636,leftleftarrows:8647,leftrightarrow:8596,leftrightarrows:8646,leftrightharpoons:8651,leftrightsquigarrow:8621,leftthreetimes:8907,leg:8922,leq:8804,leqq:8806,leqslant:10877,les:10877,lescc:10920,lesdot:10879,lesdoto:10881,lesdotor:10883,lesg:[8922,65024],lesges:10899,lessapprox:10885,lessdot:8918,lesseqgtr:8922,lesseqqgtr:10891,lessgtr:8822,lesssim:8818,lfisht:10620,lfloor:8970,lfr:120105,lg:8822,lgE:10897,lhard:8637,lharu:8636,lharul:10602,lhblk:9604,ljcy:1113,ll:8810,llarr:8647,llcorner:8990,llhard:10603,lltri:9722,lmidot:320,lmoust:9136,lmoustache:9136,lnE:8808,lnap:10889,lnapprox:10889,lne:10887,lneq:10887,lneqq:8808,lnsim:8934,loang:10220,loarr:8701,lobrk:10214,longleftarrow:10229,longleftrightarrow:10231,longmapsto:10236,longrightarrow:10230,looparrowleft:8619,looparrowright:8620,lopar:10629,lopf:120157,loplus:10797,lotimes:10804,lowast:8727,lowbar:95,loz:9674,lozenge:9674,lozf:10731,lpar:40,lparlt:10643,lrarr:8646,lrcorner:8991,lrhar:8651,lrhard:10605,lrm:8206,lrtri:8895,lsaquo:8249,lscr:120001,lsh:8624,lsim:8818,lsime:10893,lsimg:10895,lsqb:91,lsquo:8216,lsquor:8218,lstrok:322,lt:60,ltcc:10918,ltcir:10873,ltdot:8918,lthree:8907,ltimes:8905,ltlarr:10614,ltquest:10875,ltrPar:10646,ltri:9667,ltrie:8884,ltrif:9666,lurdshar:10570,luruhar:10598,lvertneqq:[8808,65024],lvnE:[8808,65024],mDDot:8762,macr:175,male:9794,malt:10016,maltese:10016,map:8614,mapsto:8614,mapstodown:8615,mapstoleft:8612,mapstoup:8613,marker:9646,mcomma:10793,mcy:1084,mdash:8212,measuredangle:8737,mfr:120106,mho:8487,micro:181,mid:8739,midast:42,midcir:10992,middot:183,minus:8722,minusb:8863,minusd:8760,minusdu:10794,mlcp:10971,mldr:8230,mnplus:8723,models:8871,mopf:120158,mp:8723,mscr:120002,mstpos:8766,mu:956,multimap:8888,mumap:8888,nGg:[8921,824],nGt:[8811,8402],nGtv:[8811,824],nLeftarrow:8653,nLeftrightarrow:8654,nLl:[8920,824],nLt:[8810,8402],nLtv:[8810,824],nRightarrow:8655,nVDash:8879,nVdash:8878,nabla:8711,nacute:324,nang:[8736,8402],nap:8777,napE:[10864,824],napid:[8779,824],napos:329,napprox:8777,natur:9838,natural:9838,naturals:8469,nbsp:160,nbump:[8782,824],nbumpe:[8783,824],ncap:10819,ncaron:328,ncedil:326,ncong:8775,ncongdot:[10861,824],ncup:10818,ncy:1085,ndash:8211,ne:8800,neArr:8663,nearhk:10532,nearr:8599,nearrow:8599,nedot:[8784,824],nequiv:8802,nesear:10536,nesim:[8770,824],nexist:8708,nexists:8708,nfr:120107,ngE:[8807,824],nge:8817,ngeq:8817,ngeqq:[8807,824],ngeqslant:[10878,824],nges:[10878,824],ngsim:8821,ngt:8815,ngtr:8815,nhArr:8654,nharr:8622,nhpar:10994,ni:8715,nis:8956,nisd:8954,niv:8715,njcy:1114,nlArr:8653,nlE:[8806,824],nlarr:8602,nldr:8229,nle:8816,nleftarrow:8602,nleftrightarrow:8622,nleq:8816,nleqq:[8806,824],nleqslant:[10877,824],nles:[10877,824],nless:8814,nlsim:8820,nlt:8814,nltri:8938,nltrie:8940,nmid:8740,nopf:120159,not:172,notin:8713,notinE:[8953,824],notindot:[8949,824],notinva:8713,notinvb:8951,notinvc:8950,notni:8716,notniva:8716,notnivb:8958,notnivc:8957,npar:8742,nparallel:8742,nparsl:[11005,8421],npart:[8706,824],npolint:10772,npr:8832,nprcue:8928,npre:[10927,824],nprec:8832,npreceq:[10927,824],nrArr:8655,nrarr:8603,nrarrc:[10547,824],nrarrw:[8605,824],nrightarrow:8603,nrtri:8939,nrtrie:8941,nsc:8833,nsccue:8929,nsce:[10928,824],nscr:120003,nshortmid:8740,nshortparallel:8742,nsim:8769,nsime:8772,nsimeq:8772,nsmid:8740,nspar:8742,nsqsube:8930,nsqsupe:8931,nsub:8836,nsubE:[10949,824],nsube:8840,nsubset:[8834,8402],nsubseteq:8840,nsubseteqq:[10949,824],nsucc:8833,nsucceq:[10928,824],nsup:8837,nsupE:[10950,824],nsupe:8841,nsupset:[8835,8402],nsupseteq:8841,nsupseteqq:[10950,824],ntgl:8825,ntilde:241,ntlg:8824,ntriangleleft:8938,ntrianglelefteq:8940,ntriangleright:8939,ntrianglerighteq:8941,nu:957,num:35,numero:8470,numsp:8199,nvDash:8877,nvHarr:10500,nvap:[8781,8402],nvdash:8876,nvge:[8805,8402],nvgt:[62,8402],nvinfin:10718,nvlArr:10498,nvle:[8804,8402],nvlt:[60,8402],nvltrie:[8884,8402],nvrArr:10499,nvrtrie:[8885,8402],nvsim:[8764,8402],nwArr:8662,nwarhk:10531,nwarr:8598,nwarrow:8598,nwnear:10535,oS:9416,oacute:243,oast:8859,ocir:8858,ocirc:244,ocy:1086,odash:8861,odblac:337,odiv:10808,odot:8857,odsold:10684,oelig:339,ofcir:10687,ofr:120108,ogon:731,ograve:242,ogt:10689,ohbar:10677,ohm:937,oint:8750,olarr:8634,olcir:10686,olcross:10683,oline:8254,olt:10688,omacr:333,omega:969,omicron:959,omid:10678,ominus:8854,oopf:120160,opar:10679,operp:10681,oplus:8853,or:8744,orarr:8635,ord:10845,order:8500,orderof:8500,ordf:170,ordm:186,origof:8886,oror:10838,orslope:10839,orv:10843,oscr:8500,oslash:248,osol:8856,otilde:245,otimes:8855,otimesas:10806,ouml:246,ovbar:9021,par:8741,para:182,parallel:8741,parsim:10995,parsl:11005,part:8706,pcy:1087,percnt:37,period:46,permil:8240,perp:8869,pertenk:8241,pfr:120109,phi:966,phiv:981,phmmat:8499,phone:9742,pi:960,pitchfork:8916,piv:982,planck:8463,planckh:8462,plankv:8463,plus:43,plusacir:10787,plusb:8862,pluscir:10786,plusdo:8724,plusdu:10789,pluse:10866,plusmn:177,plussim:10790,plustwo:10791,pm:177,pointint:10773,popf:120161,pound:163,pr:8826,prE:10931,prap:10935,prcue:8828,pre:10927,prec:8826,precapprox:10935,preccurlyeq:8828,preceq:10927,precnapprox:10937,precneqq:10933,precnsim:8936,precsim:8830,prime:8242,primes:8473,prnE:10933,prnap:10937,prnsim:8936,prod:8719,profalar:9006,profline:8978,profsurf:8979,prop:8733,propto:8733,prsim:8830,prurel:8880,pscr:120005,psi:968,puncsp:8200,qfr:120110,qint:10764,qopf:120162,qprime:8279,qscr:120006,quaternions:8461,quatint:10774,quest:63,questeq:8799,quot:34,rAarr:8667,rArr:8658,rAtail:10524,rBarr:10511,rHar:10596,race:[8765,817],racute:341,radic:8730,raemptyv:10675,rang:10217,rangd:10642,range:10661,rangle:10217,raquo:187,rarr:8594,rarrap:10613,rarrb:8677,rarrbfs:10528,rarrc:10547,rarrfs:10526,rarrhk:8618,rarrlp:8620,rarrpl:10565,rarrsim:10612,rarrtl:8611,rarrw:8605,ratail:10522,ratio:8758,rationals:8474,rbarr:10509,rbbrk:10099,rbrace:125,rbrack:93,rbrke:10636,rbrksld:10638,rbrkslu:10640,rcaron:345,rcedil:343,rceil:8969,rcub:125,rcy:1088,rdca:10551,rdldhar:10601,rdquo:8221,rdquor:8221,rdsh:8627,real:8476,realine:8475,realpart:8476,reals:8477,rect:9645,reg:174,rfisht:10621,rfloor:8971,rfr:120111,rhard:8641,rharu:8640,rharul:10604,rho:961,rhov:1009,rightarrow:8594,rightarrowtail:8611,rightharpoondown:8641,rightharpoonup:8640,rightleftarrows:8644,rightleftharpoons:8652,rightrightarrows:8649,rightsquigarrow:8605,rightthreetimes:8908,ring:730,risingdotseq:8787,rlarr:8644,rlhar:8652,rlm:8207,rmoust:9137,rmoustache:9137,rnmid:10990,roang:10221,roarr:8702,robrk:10215,ropar:10630,ropf:120163,roplus:10798,rotimes:10805,rpar:41,rpargt:10644,rppolint:10770,rrarr:8649,rsaquo:8250,rscr:120007,rsh:8625,rsqb:93,rsquo:8217,rsquor:8217,rthree:8908,rtimes:8906,rtri:9657,rtrie:8885,rtrif:9656,rtriltri:10702,ruluhar:10600,rx:8478,sacute:347,sbquo:8218,sc:8827,scE:10932,scap:10936,scaron:353,sccue:8829,sce:10928,scedil:351,scirc:349,scnE:10934,scnap:10938,scnsim:8937,scpolint:10771,scsim:8831,scy:1089,sdot:8901,sdotb:8865,sdote:10854,seArr:8664,searhk:10533,searr:8600,searrow:8600,sect:167,semi:59,seswar:10537,setminus:8726,setmn:8726,sext:10038,sfr:120112,sfrown:8994,sharp:9839,shchcy:1097,shcy:1096,shortmid:8739,shortparallel:8741,shy:173,sigma:963,sigmaf:962,sigmav:962,sim:8764,simdot:10858,sime:8771,simeq:8771,simg:10910,simgE:10912,siml:10909,simlE:10911,simne:8774,simplus:10788,simrarr:10610,slarr:8592,smallsetminus:8726,smashp:10803,smeparsl:10724,smid:8739,smile:8995,smt:10922,smte:10924,smtes:[10924,65024],softcy:1100,sol:47,solb:10692,solbar:9023,sopf:120164,spades:9824,spadesuit:9824,spar:8741,sqcap:8851,sqcaps:[8851,65024],sqcup:8852,sqcups:[8852,65024],sqsub:8847,sqsube:8849,sqsubset:8847,sqsubseteq:8849,sqsup:8848,sqsupe:8850,sqsupset:8848,sqsupseteq:8850,squ:9633,square:9633,squarf:9642,squf:9642,srarr:8594,sscr:120008,ssetmn:8726,ssmile:8995,sstarf:8902,star:9734,starf:9733,straightepsilon:1013,straightphi:981,strns:175,sub:8834,subE:10949,subdot:10941,sube:8838,subedot:10947,submult:10945,subnE:10955,subne:8842,subplus:10943,subrarr:10617,subset:8834,subseteq:8838,subseteqq:10949,subsetneq:8842,subsetneqq:10955,subsim:10951,subsub:10965,subsup:10963,succ:8827,succapprox:10936,succcurlyeq:8829,succeq:10928,succnapprox:10938,succneqq:10934,succnsim:8937,succsim:8831,sum:8721,sung:9834,sup1:185,sup2:178,sup3:179,sup:8835,supE:10950,supdot:10942,supdsub:10968,supe:8839,supedot:10948,suphsol:10185,suphsub:10967,suplarr:10619,supmult:10946,supnE:10956,supne:8843,supplus:10944,supset:8835,supseteq:8839,supseteqq:10950,supsetneq:8843,supsetneqq:10956,supsim:10952,supsub:10964,supsup:10966,swArr:8665,swarhk:10534,swarr:8601,swarrow:8601,swnwar:10538,szlig:223,target:8982,tau:964,tbrk:9140,tcaron:357,tcedil:355,tcy:1090,tdot:8411,telrec:8981,tfr:120113,there4:8756,therefore:8756,theta:952,thetasym:977,thetav:977,thickapprox:8776,thicksim:8764,thinsp:8201,thkap:8776,thksim:8764,thorn:254,tilde:732,times:215,timesb:8864,timesbar:10801,timesd:10800,tint:8749,toea:10536,top:8868,topbot:9014,topcir:10993,topf:120165,topfork:10970,tosa:10537,tprime:8244,trade:8482,triangle:9653,triangledown:9663,triangleleft:9667,trianglelefteq:8884,triangleq:8796,triangleright:9657,trianglerighteq:8885,tridot:9708,trie:8796,triminus:10810,triplus:10809,trisb:10701,tritime:10811,trpezium:9186,tscr:120009,tscy:1094,tshcy:1115,tstrok:359,twixt:8812,twoheadleftarrow:8606,twoheadrightarrow:8608,uArr:8657,uHar:10595,uacute:250,uarr:8593,ubrcy:1118,ubreve:365,ucirc:251,ucy:1091,udarr:8645,udblac:369,udhar:10606,ufisht:10622,ufr:120114,ugrave:249,uharl:8639,uharr:8638,uhblk:9600,ulcorn:8988,ulcorner:8988,ulcrop:8975,ultri:9720,umacr:363,uml:168,uogon:371,uopf:120166,uparrow:8593,updownarrow:8597,upharpoonleft:8639,upharpoonright:8638,uplus:8846,upsi:965,upsih:978,upsilon:965,upuparrows:8648,urcorn:8989,urcorner:8989,urcrop:8974,uring:367,urtri:9721,uscr:120010,utdot:8944,utilde:361,utri:9653,utrif:9652,uuarr:8648,uuml:252,uwangle:10663,vArr:8661,vBar:10984,vBarv:10985,vDash:8872,vangrt:10652,varepsilon:1013,varkappa:1008,varnothing:8709,varphi:981,varpi:982,varpropto:8733,varr:8597,varrho:1009,varsigma:962,varsubsetneq:[8842,65024],varsubsetneqq:[10955,65024],varsupsetneq:[8843,65024],varsupsetneqq:[10956,65024],vartheta:977,vartriangleleft:8882,vartriangleright:8883,vcy:1074,vdash:8866,vee:8744,veebar:8891,veeeq:8794,vellip:8942,verbar:124,vert:124,vfr:120115,vltri:8882,vnsub:[8834,8402],vnsup:[8835,8402],vopf:120167,vprop:8733,vrtri:8883,vscr:120011,vsubnE:[10955,65024],vsubne:[8842,65024],vsupnE:[10956,65024],vsupne:[8843,65024],vzigzag:10650,wcirc:373,wedbar:10847,wedge:8743,wedgeq:8793,weierp:8472,wfr:120116,wopf:120168,wp:8472,wr:8768,wreath:8768,wscr:120012,xcap:8898,xcirc:9711,xcup:8899,xdtri:9661,xfr:120117,xhArr:10234,xharr:10231,xi:958,xlArr:10232,xlarr:10229,xmap:10236,xnis:8955,xodot:10752,xopf:120169,xoplus:10753,xotime:10754,xrArr:10233,xrarr:10230,xscr:120013,xsqcup:10758,xuplus:10756,xutri:9651,xvee:8897,xwedge:8896,yacute:253,yacy:1103,ycirc:375,ycy:1099,yen:165,yfr:120118,yicy:1111,yopf:120170,yscr:120014,yucy:1102,yuml:255,zacute:378,zcaron:382,zcy:1079,zdot:380,zeetrf:8488,zeta:950,zfr:120119,zhcy:1078,zigrarr:8669,zopf:120171,zscr:120015,zwj:8205,zwnj:8204,};

;// CONCATENATED MODULE: ./src/evaluate.js



let ccMap = new Uint32Array(0x110000);
let ccBuf = new Uint16Array(1 << 20);
let ccEncoding = new TextDecoder("utf-16le").decode(new Uint16Array([0x1234])) === "\u1234" ?
	"utf-16le" : "utf-16be";
let entMap = Object.create(null);

for (let i = 0; i <= 0x10FFFF; i++)
	ccMap[i] = i;

for (let i = 0, u = 0, v = 0; i < equivset.length; i += 2) {
	u += equivset[i];
	v += equivset[i + 1];
	ccMap[u] = v;
}

for (let e of Object.keys(entities))
	entMap[e] = String.fromCodePoint(...(entities[e].length ? entities[e] : [entities[e]]));

class EvaluationError {
	constructor(message) {
		this.message = message;
	}
}

class TrackedString {
	constructor(str, origin) {
		if (str instanceof TrackedString) {
			this.str = str.str;
			this.origin = str.origin.slice();
		} else {
			this.str = str || "";
			this.origin = origin ? origin.slice() : [];
		}
	}
	toString() {
		return this.str;
	}
	valueOf() {
		return this.str;
	}
	static concat(a, b) {
		let r = new TrackedString(a);
		r.str += b.str;
		for (let s of b.origin) {
			r.origin.push([s[0], s[1], s[2] + a.str.length, s[3] + a.str.length]);
		}
		return r;
	}
	static untrack(a) {
		if (a instanceof TrackedString)
			return a.str;
		return a;
	}
	getRanges(spans) {
		let i = 0, ranges = [];

		for (let span of spans) {
			let spanStart = span[0];
			let spanEnd = span[1];

			while (i < this.origin.length && this.origin[i][3] < spanStart) {
				i++;
			}

			while (i < this.origin.length && spanStart < this.origin[i][3]) {
				let part = this.origin[i];
				let markStart = spanStart - part[2] + part[0];
				let markEnd = part[3] - part[2] == 1 ?
					part[1] :
					Math.min(spanEnd - part[2] + part[0], part[1]);

				ranges.push({
					start: markStart,
					end: markEnd
				});

				if (spanEnd >= part[3]) {
					spanStart = part[3];
					i++;
				} else {
					break;
				}
			}
		}

		return ranges;
	}
}

function regexMatch(needle, haystack, flags = "", swap = false, capture = false) {
	let details = { matches: [] };

	let count = 0, result, captures = [], re;
	try {
		re = new PCiRE(string(needle), "u" + flags);
	} catch (err) {
		if (err instanceof RegexError)
			throw new EvaluationError("Invalid regular expression: " + err.message);
		else
			throw err;
	}
	while ((result = re.exec(haystack)) !== null) {
		if (count == 0) {
			details.matches.push({
				arg_needle: swap ? 1 : 0,
				arg_haystack: swap ? 0 : 1,
				match: [result.index, result.index + result[0].length],
				ranges: type(needle) == 'trackedstring' ? needle.getRanges(result.spans) : []
			});

			if (capture)
				captures.push(result.map(x => x === undefined ? false : x));
		}
		count++;

		if (!flags.includes("g"))
			break;

		if (result.index == re.lastIndex) // Avoid infinite loop on empty match
			re.lastIndex++;
	}

	if (capture) {
		if (captures.length === 0)
			return [(new Array(re.origcaps + 1)).fill(false), details];
		else
			return [captures[0], details];
	} else {
		return [count, details];
	}
}

function escapeRegexForJS(s) {
	return s.replace(/[.\\+*?[^\]$(){}|]/g, "\\$&");
}

function contains(matchall, haystack, ...needles) {
	let details = { matches: [] };

	for (let i = 0; i < needles.length; i++) {
		let n = needles[i], s = string(n);
		let idx = s.length ? string(haystack).indexOf(s) : -1;

		if (idx >= 0) {
			details.matches.push({
				arg_haystack: 0,
				arg_needle: i + 1,
				match: [idx, idx + s.length],
				ranges: type(n) == 'trackedstring' ? n.getRanges([[0, s.length]]) : []
			});
		}
	}

	return [matchall ? (details.matches.length == needles.length) : (details.matches.length > 0),
		details];
}

function parseIP(ip) {
	let bits = "";

	if (ip.match(/^([0-9]+\.){3}[0-9]+$/) != null) {
		let parts = ip.split(".");

		for (let part of parts) {
			let t = parseInt(part, 10);

			if (t > 255)
				return null;

			bits += t.toString(2).padStart(8, "0");
		}

		return bits;
	} else if (ip.match(/^((([0-9A-F]{1,4}:)*[0-9A-F]{1,4})?::(([0-9A-F]{1,4}:)*[0-9A-F]{1,4})?|(([0-9A-F]{1,4}:){7}[0-9A-F]{1,4}))$/i)) {
		let parts = ip.split(":");

		if (parts[0] === "")
			parts.shift();
		if (parts[parts.length - 1] === "")
			parts.pop();

		if (parts.length > 8)
			return null;

		for (let part of parts) {
			if (part.length == 0)
				bits += "0".repeat(16 * (9 - parts.length));
			else
				bits += parseInt(part, 16).toString(2).padStart(16, "0");

		}
		return bits;
	}

	return null;
}

function ipInRanges(ip, ...ranges) {
	ip = parseIP(ip);

	if (ip == null)
		return false;

	for (let range of ranges) {
		if (range.includes("/")) {
			let parts = range.split("/");
			let ipr = parseIP(parts[0]);
			let mask = parseInt(parts[1], 10);

			if (parts.length != 2 && ipr === null || !(mask >= 0 && mask <= ipr.length))
				throw new EvaluationError(`Invalid IP range: ${range}`);

			if (ipr.length === ip.length && ip.slice(0, mask) == ipr.slice(0, mask))
				return true;
		} else if (range.includes("-")) {
			let parts = range.split(/ *- */);

			let start = parseIP(parts[0]);
			let end = parseIP(parts[1]);

			if (parts.length != 2 || start == null || end == null || start.length != end.length)
				throw new EvaluationError(`Invalid IP range: ${range}`);

			if (start.length == ip.length && start <= ip && ip <= end)
				return true;
		} else {
			let ipr = parseIP(range);

			if (ipr === null)
				throw new EvaluationError(`Invalid IP range: ${range}`);

			if (ipr == ip)
				return true;
		}
	}

	return false;
}

function unescapeHTML(s) {
	return s.replace(/&[A-Za-z0-9_#]+;/g, ref => {
		if (ref[1] == '#') {
			try {
				let m = ref.match(/^&#([0-9]+);$/);
				if (m)
					return String.fromCodePoint(parseInt(m[1], 10));

				m = ref.match(/^&#x([0-9a-z]+);$/i);
				if (m)
					return String.fromCodePoint(parseInt(m[1], 16));
			} catch (e) {
				// Invalid code point
				return ref;
			}
			return ref;
		} else {
			return entMap[ref.slice(1, ref.length - 1)] || ref;
		}
	});
}

function codePointLength(s) {
	let pos = 0;

	// [...s].length is slow!
	for (let i = 0; i < s.length; i++) {
		let t = s.charCodeAt(i);

		if (t < 0xD800 || t > 0xDBFF)
			pos++;
	}

	return pos;
}

function codePointSubstring(s, start, len) {
	let pos = 0;
	let end = (len == undefined ? Infinity : start + len);
	let idx1, idx2;

	for (let i = 0; i < s.length; i++) {
		let t = s.charCodeAt(i);

		if (pos == start)
			idx1 = i;
		if (pos == end) {
			idx2 = i;
			break;
		}

		if (t < 0xD800 || t > 0xDBFF)
			pos++;

	}

	return idx1 === undefined ? "" : s.slice(idx1, idx2);
}

function ccnorm(s) {
	let k = 0;

	// output is never longer than input
	if (ccBuf.length < s.length)
		ccBuf = new Uint16Array(2 * s.length);

	// This seems much faster than just appending each character to the string...
	for (let i = 0; i < s.length; i++) {
		const t = s.codePointAt(i);
		const u = ccMap[t];

		if (u == 0) {
			continue;
		} else if (u <= 0xFFFF) {
			ccBuf[k++] = u;
		} else {
			ccBuf[k++] = 0xD800 | (u >> 10);
			ccBuf[k++] = 0xDC00 | (u & 0x3FF);
		}

		if (t > 0xFFFF)
			i++;
	}

	return (new TextDecoder(ccEncoding)).decode(ccBuf.subarray(0, k));
}


function rmspecials(s) {
	return s.replace(/[^\p{L}\p{N}\x09-\x0D\x20\x85\xA0\u{1680}\u{180E}\u{2000}-\u{200A}\u{2028}-\u{2029}\u{202F}\u{205F}\u{3000}]/ug, "");
}

function rmdoubles(s) {
	return s.replace(/(.)\1+/ug, "$1");
}

function rmwhitespace(s) {
	return s.replace(/[\x09-\x0D\x20\x85\xA0\u{1680}\u{180E}\u{2000}-\u{200A}\u{2028}-\u{2029}\u{202F}\u{205F}\u{3000}]/ug, "");
}

function type(d) {
	if (typeof d == 'object') {
		if (d == null)
			return 'null';
		if (d.name !== undefined)
			return 'reference';
		if (Array.isArray(d))
			return 'array';
		if (d instanceof TrackedString)
			return 'trackedstring';

		throw new EvaluationError("Unknown type");
	}
	return typeof d;
}

function string(d) {
	switch (type(d)) {
	case 'trackedstring':
		d = TrackedString.untrack(d);
		// falls through
	case 'string':
		return d;
	case 'boolean':
		return d ? "1" : "";
	case 'number':
		return d.toString();
	case 'null':
		return "";
	case 'array': {
		let r = "";

		for (let n of d)
			r += string(n) + "\n";
		return r;
	}
	}
}

function bool(d) {
	switch (type(d)) {
	case 'trackedstring':
		d = TrackedString.untrack(d);
		// falls through
	case 'string':
		return !(d === "" || d === "0");
	case 'boolean':
		return d;
	case 'number':
		return d !== 0;
	case 'null':
		return false;
	case 'array':
		return d.length > 0;
	}
}

function evaluate_float(d) {
	switch (type(d)) {
	case 'trackedstring':
		d = TrackedString.untrack(d);
		// falls through
	case 'string':
		return parseFloat(d) || 0;
	case 'boolean':
		return d ? 1 : 0;
	case 'number':
		return d;
	case 'null':
		return 0;
	case 'array':
		return d.length;
	}
}

function evaluate_int(d) {
	return d === undefined ? undefined : Math.trunc(evaluate_float(d));
}

function deepCopy(a) {
	switch (type(a)) {
	case 'array':
		return a.map(deepCopy);
	case 'trackedstring':
		return new TrackedString(a);
	default:
		return a;
	}
}

function isEqual(a, b, strict) {
	if (type(a) == 'array' && type(b) == 'array') {
		if (a.length != b.length)
			return false;

		for (let i = 0; i < a.length; i++)
			if (!isEqual(a[i], b[i], strict))
				return false;
		return true;
	}

	a = TrackedString.untrack(a);
	b = TrackedString.untrack(b);

	if (type(a) == type(b))
		return a === b;

	if (strict)
		return false;

	if (type(a) == 'array')
		return a.length == 0 && (b === false || b === null);
	if (type(b) == 'array')
		return b.length == 0 && (a === false || a === null);

	return string(a) == string(b);
}

function compare(a, b) {
	const isNum = /^\s*[+-]?(?:[0-9]+\.[0-9]*|\.?[0-9]+)(?:[Ee][+-]?[0-9]+)?\s*/;

	if (type(a) == 'number' && type(b) == 'number')
		return a - b;

	a = string(a);
	b = string(b);

	if (isNum.test(a) && isNum.test(b))
		return parseFloat(a) - parseFloat(b);

	return a == b ? 0 : a < b ? -1 : 1;
}

function checkFinite(n) {
	if (!isFinite(n))
		throw new EvaluationError("Arithmetic error");

	return n;
}

let operations = Object.assign(Object.create(null), {
	"statements": {
		args: [1, Infinity],
		operation: function(...a) {
			return a[a.length - 1];
		}
	},
	"conditional": {
		args: [3, 3],
		operation: function(a, b, c) {
			return bool(a) ? b : c;
		}
	},
	":=": {
		args: [2, 2],
		operation: function(a, b) {
			return this.setvar(a, b);
		}
	},
	"&": {
		args: [2, 2],
		operation: function(a, b) {
			return bool(a) && bool(b);
		}
	},
	"|": {
		args: [2, 2],
		operation: function(a, b) {
			return bool(a) || bool(b);
		}
	},
	"^": {
		args: [2, 2],
		operation: function(a, b) {
			return bool(bool(a) ^ bool(b));
		}
	},
	"!": {
		args: [1, 1],
		operation: function(a) {
			return !bool(a);
		}
	},
	"==": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return isEqual(a, b, false);
		}
	},
	"===": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return isEqual(a, b, true);
		}
	},
	"!=": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return !isEqual(a, b, false);
		}
	},
	"!==": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return !isEqual(a, b, true);
		}
	},
	"<": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return compare(a, b) < 0;
		}
	},
	">": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return compare(a, b) > 0;
		}
	},
	"<=": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return compare(a, b) <= 0;
		}
	},
	">=": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return compare(a, b) >= 0;
		}
	},
	"+": {
		args: [1, 2],
		operation: function(a, b) {
			if (b === undefined)
				return a;

			if ((type(a) == 'number' || type(a) == 'null' || type(a) == 'boolean') &&
				(type(b) == 'number' || type(b) == 'null' || type(b) == 'boolean'))
				return checkFinite(a + b); // JS rules are the same as PHP here

			if (type(a) == 'array' && type(b) == 'array')
				return a.concat(b);

			if (type(a) == 'trackedstring' && type(b) == 'trackedstring')
				return TrackedString.concat(a, b);

			return string(a) + string(b);
		}
	},
	"-": {
		args: [1, 2],
		operation: function(a, b) {
			return b === undefined ? -evaluate_float(a) : checkFinite(evaluate_float(a) - evaluate_float(b));
		}
	},
	"*": {
		args: [2, 2],
		operation: function(a, b) {
			return checkFinite(evaluate_float(a) * evaluate_float(b));
		}
	},
	"/": {
		args: [2, 2],
		operation: function(a, b) {
			return checkFinite(evaluate_float(a) / evaluate_float(b));
		}
	},
	"%": {
		args: [2, 2],
		operation: function(a, b) {
			return checkFinite(evaluate_int(a) % evaluate_int(b));
		}
	},
	"**": {
		args: [2, 2],
		operation: function(a, b) {
			return checkFinite(evaluate_float(a) ** evaluate_float(b));
		}
	},
	"index": {
		args: [1, 2],
		operation: function(a, b) {
			return type(a) == 'reference' ? ({
				name: a.name,
				indices: a.indices.concat([b]),
				readonly: a.readonly
			}) : this.arraylookup(a, b);
		}
	},
	"list": {
		args: [0, Infinity],
		operation: function(...a) {
			return [...a];
		}
	},
	"contains": {
		args: [2, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			return contains(false, string(a), b);
		}
	},
	"in": {
		args: [2, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			let [r, d] = contains(false, string(b), a);

			if (d.matches.length) {
				d.matches[0].arg_haystack = 1;
				d.matches[0].arg_needle = 0;
			}

			return [r, d];
		}
	},
	"rlike": {
		args: [2, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			let [r, d] = regexMatch(b, string(a), "", true);
			return [r > 0, d];
		}
	},
	"irlike": {
		args: [2, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			let [r, d] = regexMatch(b, string(a), "i", true);
			return [r > 0, d];
		}
	},
	"like": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			let regex = string(b)
				.replace(/[.\\+^$(){}|]/g, "\\$&")
				.replace(/[*?]/g, ".$&")
				.replace(/\[!/g, "[^");

			return (new RegExp(`^${regex}$`)).test(string(a));
		}
	},
	"lcase": {
		args: [1, 1],
		operation: function(a) {
			return string(a).toLowerCase();
		}
	},
	"ucase": {
		args: [1, 1],
		operation: function(a) {
			return string(a).toUpperCase();
		}
	},
	"length": {
		args: [1, 1],
		operation: function(a) {
			return type(a) == 'array' ? a.length : codePointLength(string(a));
		}
	},
	"string": {
		args: [1, 1],
		operation: function(a) {
			return string(a);
		}
	},
	"int": {
		args: [1, 1],
		operation: function(a) {
			return evaluate_int(a);
		}
	},
	"float": {
		args: [1, 1],
		operation: function(a) {
			return evaluate_float(a);
		}
	},
	"bool": {
		args: [1, 1],
		operation: function(a) {
			return bool(a);
		}
	},
	"norm": {
		args: [1, 1],
		operation: function(a) {
			return rmwhitespace(rmspecials(rmdoubles(ccnorm(string(a)))));
		}
	},
	"ccnorm": {
		args: [1, 1],
		operation: function(a) {
			return ccnorm(unescapeHTML(string(a)));
		}
	},
	"ccnorm_contains_any": {
		args: [2, Infinity],
		report: true,
		details: true,
		operation: function(...a) {
			return contains(false, ...a.map(c => ccnorm(string(c))));
		}
	},
	"ccnorm_contains_all": {
		args: [2, Infinity],
		report: true,
		details: true,
		operation: function(...a) {
			return contains(true, ...a.map(c => ccnorm(string(c))));
		}
	},
	"contains_any": {
		args: [2, Infinity],
		report: true,
		details: true,
		operation: function(...a) {
			return contains(false, ...a);
		}
	},
	"contains_all": {
		args: [2, Infinity],
		report: true,
		details: true,
		operation: function(...a) {
			return contains(true, ...a);
		}
	},
	"equals_to_any": {
		args: [2, Infinity],
		report: true,
		operation: function(a, ...b) {
			for (let n of b)
				if (isEqual(a, n, true))
					return true;

			return false;
		}
	},
	"specialratio": {
		args: [1, 1],
		operation: function(a) {
			let origLen = codePointLength(string(a));
			let newLen = codePointLength(rmspecials(string(a)));

			return ((origLen - newLen) / origLen) || 0;
		}
	},
	"rmspecials": {
		args: [1, 1],
		operation: function(a) {
			return rmspecials(string(a));
		}
	},
	"rmdoubles": {
		args: [1, 1],
		operation: function(a) {
			return rmdoubles(string(a));
		}
	},
	"rmwhitespace": {
		args: [1, 1],
		operation: function(a) {
			return rmwhitespace(string(a));
		}
	},
	"ip_in_ranges": {
		args: [2, Infinity],
		report: true,
		operation: function(a, ...b) {
			return ipInRanges(string(a), ...b.map(string));
		}
	},
	"ip_in_range": {
		args: [2, 2],
		report: true,
		operation: function(a, b) {
			return ipInRanges(string(a), string(b));
		}
	},
	"rescape": {
		args: [1, 1],
		operation: function(a) {
			return string(a).replace(/[.\\+*?[^\]$(){}=!<>|:-]/g, "\\$&");
		}
	},
	"substr": {
		args: [2, 3],
		operation: function(a, b, c) {
			return codePointSubstring(string(a), evaluate_int(b), evaluate_int(c));
		}
	},
	"strpos": {
		args: [2, 3],
		operation: function(a, b, c) {
			let needle = string(b);

			if (needle.length == 0)
				return -1;

			let start = c === undefined ? 0 : evaluate_int(c);
			let haystack = start == 0 ? string(a) : codePointSubstring(string(a), start);
			let idx = haystack.indexOf(needle);

			return idx < 0 ? -1 : start + codePointLength(haystack.slice(0, idx));
		}
	},
	"str_replace": {
		args: [3, 3],
		operation: function(a, b, c) {
			let escapedRegex = new PCiRE(escapeRegexForJS(string(b)), "g");
			let escapedReplacement = string(c).replace(/\$/g, "$$");

			return string(a).replace(escapedRegex, escapedReplacement);
		}
	},
	"str_replace_regexp": {
		args: [3, 3],
		operation: function(a, b, c) {
			return string(a).replace(new PCiRE(string(b), "g"), string(c));
		}
	},
	"sanitize": {
		args: [1, 1],
		operation: function(a) {
			return unescapeHTML(unescapeHTML(string(a))); // Why twice?
		}
	},
	"rcount": {
		args: [1, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			if (b === undefined)
				return [string(a).split(",").length, {}];
			return regexMatch(a, string(b), "g");
		}
	},
	"count": {
		args: [1, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			if (b === undefined) {
				if (type(a) == 'array')
					return [a.length, {}];
				return [string(a).split(",").length, {}];
			} else {
				a = string(a);
				if (a.length == 0)
					return [0, {}];

				return regexMatch(escapeRegexForJS(a), string(b), "g");
			}
		}
	},
	"get_matches": {
		args: [2, 2],
		report: true,
		details: true,
		operation: function(a, b) {
			return regexMatch(a, string(b), "", false, true);
		}
	},
	"set": {
		args: [2, 2],
		operation: function(a, b) {
			return this.setvar({
				name: string(a).toLowerCase(),
				indices: []
			}, b);
		}
	}
});

class Evaluator {
	constructor(vars = {}) {
		this.rovars = Object.assign(Object.create(null), vars);
		this.vars = Object.create(null);
	}

	arraylookup(arr, index) {
		if (type(arr) != 'array')
			throw new EvaluationError(`Attempting to index a ${type(arr)}`);
		if (type(index) != 'number')
			throw new EvaluationError(`Invalid array index: ${index} ${type(index)}`);
		if (index < 0 || index >= arr.length)
			throw new EvaluationError(`Out of bounds array index: ${index}`);

		return arr[index];
	}

	getvar(ref, write = false) {
		let v = null;

		if (this.rovars[ref.name] !== undefined) {
			v = this.rovars[ref.name];
		} else if (this.vars[ref.name] !== undefined)
			v = this.vars[ref.name];

		if (!ref.readonly && v == null)
			throw new EvaluationError("Unset variable: " + ref.name);

		if (ref.indices.length) {
			for (let i = 0; i < ref.indices.length - 1; i++)
				v = this.arraylookup(v, ref.indices[i]);

			if (!write) {
				if (ref.indices[ref.indices.length - 1] === undefined)
					throw new EvaluationError("Empty array index");
				return this.arraylookup(v, ref.indices[ref.indices.length - 1]);
			} else {
				// Trigger exception on out-of-bounds
				if (ref.indices[ref.indices.length - 1] !== undefined)
					this.arraylookup(v, ref.indices[ref.indices.length - 1]);
			}
		}

		return v;
	}

	setvar(ref, value) {
		if (type(ref) !== 'reference')
			throw new EvaluationError(`Cannot assign to a ${type(ref)}`);

		if (ref.readonly)
			throw new EvaluationError(`Cannot write to read-only variable ${ref.name}`);

		if (ref.indices.length == 0)
			return (this.vars[ref.name] = deepCopy(value));

		let index = ref.indices[ref.indices.length - 1];
		let v = this.getvar(ref, true);

		if (index === undefined)
			return v.push(deepCopy(value));
		else
			return (v[index] = deepCopy(value));
	}

	evaluate(parsetree, log, scmode) {
		this.scmode = scmode || 'blank';
		this.log = log;

		if (this.log)
			this.log.length = 0;

		return TrackedString.untrack(this.evalnode(parsetree.tree));
	}

	evalnode(node, skip) {
		let saved, result, inputs = [], details = {};

		if (skip && this.scmode == 'fast')
			return;

		if (skip && this.scmode == 'allpaths') {
			saved = {};
			for (let v of Object.keys(this.vars))
				saved[v] = deepCopy(this.vars[v]);
		}

		if (skip && this.scmode == 'blank') {
			if (node.inputs)
				for (let input of node.inputs)
					this.evalnode(input, true);

			if (this.log && node.operation && operations[node.operation].report) {
				this.log.push({
					operation: node.operation,
					start: node.start,
					end: node.end
				});
			}
		} else if (node.operation === undefined) {
			if (typeof node.value == 'string')
				result = new TrackedString(node.value, node.strmap);
			else
				result = node.value; // Leaf node
		} else {
			try {
				// Short-curcuit evaluation
				if (node.operation == "&" || node.operation == "|" || node.operation == "conditional") {
					inputs[0] = this.evalnode(node.inputs[0], false);

					let truthy = type(inputs[0]) == 'reference' ?
						bool(this.getvar(inputs[0])) :
						bool(inputs[0]);

					switch (node.operation) {
					case "&":
						inputs[1] = this.evalnode(node.inputs[1], !truthy);
						break;
					case "|":
						inputs[1] = this.evalnode(node.inputs[1], truthy);
						break;
					case "conditional":
						inputs[1] = this.evalnode(node.inputs[1], !truthy);
						inputs[2] = this.evalnode(node.inputs[2], truthy);
						break;
					}
				} else {
					for (let i = 0; i < node.inputs.length; i++)
						inputs[i] = this.evalnode(node.inputs[i], false);
				}

				// Look up variables
				if (node.operation == ":=" || node.operation == "index") {
					if (type(inputs[1]) == 'reference')
						inputs[1] = this.getvar(inputs[1]);
				} else {
					for (let i = 0 ; i < inputs.length; i++)
						if (type(inputs[i]) == 'reference')
							inputs[i] = this.getvar(inputs[i]);
				}

				let op = operations[node.operation];

				if (!op)
					throw new EvaluationError("Internal Error: Unknown operation " + node.operation);

				if (inputs.length < op.args[0] || inputs.length > op.args[1])
					throw new EvaluationError(`Wrong number of arguments to ${node.operation}`);

				result = op.operation.call(this, ...inputs);
				if (op.details) {
					details = {
						inputs: inputs.map(string),
						...result[1]
					};
					result = result[0];
				}

				if (result === undefined)
					throw new EvaluationError("Undefined value");

				if (op.report && this.log)
					this.log.push({
						operation: node.operation,
						start: node.start,
						end: node.end,
						result: bool(result),
						details: details
					});
			} catch (error) {
				if (skip && this.scmode == 'allpaths')
					result = null;
				else {
					if (!error.logged && this.log)
						this.log.push({
							operation: node.operation,
							start: node.start,
							end: node.end,
							error: error.message
						});
					error.logged = true;
					throw error;
				}
			}

		}

		if (skip && this.scmode == 'allpaths') {
			this.vars = saved;
		}
		return result;
	}
}



;// CONCATENATED MODULE: ./src/VarCache.js
class VarCache {
	static getURL(base, entry) {
		if (entry.id)
			return `${base}/filter-debugger/abuselog/${entry.id}`;
		else
			return `${base}/filter-debugger/generated/${entry.revid}`;
	}
	static async open() {
		VarCache.cache = await self.caches.open("filter-debugger").catch(() => null);
	}
	static async getCachedVars(base, list, expensive, progress) {
		if (!VarCache.cache)
			return {};

		let result = {}, found = 0, promises = [];

		for (let entry of list) {
			promises.push(
				VarCache.cache.match(VarCache.getURL(base, entry)).then(async response => {
					if (response) {
						response = await response.json();
						if (!expensive || !response.partial) {
							result[entry.id] = response;

							progress(++found);
						}
					}
				}));
		}

		await Promise.all(promises);

		return result;
	}
	static cacheVars(base, list, cached) {
		if (VarCache.cache)
			for (let entry of list)
				if (!(entry.id in cached))
					VarCache.cache.put(VarCache.getURL(base, entry), new Response(JSON.stringify(entry)));
	}
	static async clearIfBiggerThan(size) {
		if (VarCache.cache && (size <= 0 || (await VarCache.cache.keys()) > size)) {
			await self.caches.delete("filter-debugger");
			await VarCache.open();
		}
	}
}

;// CONCATENATED MODULE: ./src/JSONStream.js
class JSONStream extends TransformStream {
	constructor() {
		super({
			start() {
				this.state = {
					decoder: new TextDecoder(),
					buf: new Uint8Array(1 << 20),
					pos: 0,
					stack: new Uint8Array(1024),
					sp: 0,
					string: false,
					escape: false
				};
			},
			async transform(chunk, controller) {
				let state = this.state;

				if (state.pos + chunk.length >= state.buf.length - 1) {
					let len = Math.max(state.buf.length * 2, state.buf.length + chunk.length);
					let buf = new Uint8Array(len);
					buf.set(state.buf);
					state.buf = buf;
				}

				for (let i = 0; i < chunk.length; i++) {
					let c = chunk[i];


					state.buf[state.pos++] = c;

					if (state.string) {
						if (!state.escape && c == 0x22)
							state.string = false;
						else if (c == 0x5C)
							state.escape = true;
						else
							state.escape = false;
					} else {
						if (c == 0x22) {
							state.string = true;
						} else if (c == 0x5B || c == 0x7B) {
							if (state.sp == 1) {
								state.buf[0] = c;
								state.pos = 1;
							}

							if (state.sp >= state.stack.length)
								throw new Error("Too much nesting in JSON");

							state.stack[state.sp++] = c;
						} else if (c == 0x5D || c == 0x7D) {
							if (state.sp == 0 || state.stack[--state.sp] != c - 2)
								throw new Error("Invalid JSON");

							if (state.sp == 1) {
								controller.enqueue(JSON.parse(state.decoder.decode(state.buf.subarray(0, state.pos))));
								state.pos = 0;
							}
						}
					}
				}
			},
			flush() {
				this.state = null;
			}
		});
	}
}

;// CONCATENATED MODULE: ./lib/diff_match_patch.min.js
/**
 * Diff Match and Patch
 * Copyright 2018 The diff-match-patch Authors.
 * https://github.com/google/diff-match-patch
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var diff_match_patch=function(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=.5;this.Patch_Margin=4;this.Match_MaxBits=32},DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;diff_match_patch.Diff=function(a,b){this[0]=a;this[1]=b};diff_match_patch.Diff.prototype.length=2;diff_match_patch.Diff.prototype.toString=function(){return this[0]+","+this[1]};
diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[new diff_match_patch.Diff(DIFF_EQUAL,a)]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);f=this.diff_commonSuffix(a,b);var g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,
b.length-f);a=this.diff_compute_(a,b,e,d);c&&a.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));g&&a.push(new diff_match_patch.Diff(DIFF_EQUAL,g));this.diff_cleanupMerge(a);return a};
diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[new diff_match_patch.Diff(DIFF_INSERT,b)];if(!b)return[new diff_match_patch.Diff(DIFF_DELETE,a)];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[new diff_match_patch.Diff(DIFF_INSERT,e.substring(0,g)),new diff_match_patch.Diff(DIFF_EQUAL,f),new diff_match_patch.Diff(DIFF_INSERT,e.substring(g+f.length))],a.length>b.length&&(c[0][0]=c[2][0]=DIFF_DELETE),c):1==f.length?[new diff_match_patch.Diff(DIFF_DELETE,
a),new diff_match_patch.Diff(DIFF_INSERT,b)]:(e=this.diff_halfMatch_(a,b))?(b=e[1],f=e[3],a=e[4],e=this.diff_main(e[0],e[2],c,d),c=this.diff_main(b,f,c,d),e.concat([new diff_match_patch.Diff(DIFF_EQUAL,a)],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,d):this.diff_bisect_(a,b,d)};
diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case DIFF_INSERT:e++;g+=a[b][1];break;case DIFF_DELETE:d++;f+=a[b][1];break;case DIFF_EQUAL:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,
0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=2*f,h=Array(g),l=Array(g),k=0;k<g;k++)h[k]=-1,l[k]=-1;h[f+1]=0;l[f+1]=0;k=d-e;for(var m=0!=k%2,p=0,x=0,w=0,q=0,t=0;t<f&&!((new Date).getTime()>c);t++){for(var v=-t+p;v<=t-x;v+=2){var n=f+v;var r=v==-t||v!=t&&h[n-1]<h[n+1]?h[n+1]:h[n-1]+1;for(var y=r-v;r<d&&y<e&&a.charAt(r)==b.charAt(y);)r++,y++;h[n]=r;if(r>d)x+=2;else if(y>e)p+=2;else if(m&&(n=f+k-v,0<=n&&n<g&&-1!=l[n])){var u=d-l[n];if(r>=
u)return this.diff_bisectSplit_(a,b,r,y,c)}}for(v=-t+w;v<=t-q;v+=2){n=f+v;u=v==-t||v!=t&&l[n-1]<l[n+1]?l[n+1]:l[n-1]+1;for(r=u-v;u<d&&r<e&&a.charAt(d-u-1)==b.charAt(e-r-1);)u++,r++;l[n]=u;if(u>d)q+=2;else if(r>e)w+=2;else if(!m&&(n=f+k-v,0<=n&&n<g&&-1!=h[n]&&(r=h[n],y=f+r-n,u=d-u,r>=u)))return this.diff_bisectSplit_(a,b,r,y,c)}}return[new diff_match_patch.Diff(DIFF_DELETE,a),new diff_match_patch.Diff(DIFF_INSERT,b)]};
diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,g=-1,h=d.length;g<a.length-1;){g=a.indexOf("\n",c);-1==g&&(g=a.length-1);var l=a.substring(c,g+1);(e.hasOwnProperty?e.hasOwnProperty(l):void 0!==e[l])?b+=String.fromCharCode(e[l]):(h==f&&(l=a.substring(c),g=a.length),b+=String.fromCharCode(h),e[l]=h,d[h++]=l);c=g+1}return b}var d=[],e={};d[0]="";var f=4E4,g=c(a);f=65535;var h=c(b);return{chars1:g,chars2:h,lineArray:d}};
diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;d=0;for(var e=1;;){var f=a.substring(c-e);f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,k,l,m;-1!=(e=b.indexOf(d,e+1));){var p=f.diff_commonPrefix(a.substring(c),b.substring(e)),u=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<u+p&&(g=b.substring(e-u,e)+b.substring(e,e+p),h=a.substring(0,c-u),k=a.substring(c+p),l=b.substring(0,e-u),m=b.substring(e+p))}return 2*g.length>=a.length?[h,k,l,m,g]:null}if(0>=this.Diff_Timeout)return null;
var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4));d=c(d,e,Math.ceil(d.length/2));if(g||d)g=d?g?g[4].length>d[4].length?g:d:d:g;else return null;if(a.length>b.length){d=g[0];e=g[1];var h=g[2];var l=g[3]}else h=g[0],l=g[1],d=g[2],e=g[3];return[d,e,h,l,g[4]]};
diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,l=0,k=0;f<a.length;)a[f][0]==DIFF_EQUAL?(c[d++]=f,g=l,h=k,k=l=0,e=a[f][1]):(a[f][0]==DIFF_INSERT?l+=a[f][1].length:k+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(l,k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,d--,f=0<d?c[d-1]:-1,k=l=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<
a.length;){if(a[f-1][0]==DIFF_DELETE&&a[f][0]==DIFF_INSERT){b=a[f-1][1];c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,c.substring(0,d))),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,b.substring(0,e))),a[f-1][0]=DIFF_INSERT,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=DIFF_DELETE,
a[f+1][1]=b.substring(e),f++;f++}f++}};
diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_);c=g&&c.match(diff_match_patch.linebreakRegex_);d=h&&d.match(diff_match_patch.linebreakRegex_);var k=c&&a.match(diff_match_patch.blanklineEndRegex_),l=d&&b.match(diff_match_patch.blanklineStartRegex_);
return k||l?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(a[c-1][0]==DIFF_EQUAL&&a[c+1][0]==DIFF_EQUAL){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g){var h=e.substring(e.length-g);d=d.substring(0,d.length-g);e=h+e.substring(0,e.length-g);f=h+f}g=d;h=e;for(var l=f,k=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);e=e.substring(1)+f.charAt(0);f=f.substring(1);var m=b(d,e)+b(e,f);m>=k&&(k=m,g=d,h=e,l=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-
1,1),c--),a[c][1]=h,l?a[c+1][1]=l:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,l=!1,k=!1;f<a.length;)a[f][0]==DIFF_EQUAL?(a[f][1].length<this.Diff_EditCost&&(l||k)?(c[d++]=f,g=l,h=k,e=a[f][1]):(d=0,e=null),l=k=!1):(a[f][0]==DIFF_DELETE?k=!0:l=!0,e&&(g&&h&&l&&k||e.length<this.Diff_EditCost/2&&3==g+h+l+k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,e=null,g&&h?(l=k=!0,d=0):(d--,f=0<d?c[d-1]:-1,l=k=!1),b=!0)),f++;b&&this.diff_cleanupMerge(a)};
diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case DIFF_INSERT:d++;f+=a[b][1];b++;break;case DIFF_DELETE:c++;e+=a[b][1];b++;break;case DIFF_EQUAL:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&a[b-c-d-1][0]==DIFF_EQUAL?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,new diff_match_patch.Diff(DIFF_EQUAL,f.substring(0,g))),b++),f=f.substring(g),e=e.substring(g)),
g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-g),e=e.substring(0,e.length-g))),b-=c+d,a.splice(b,c+d),e.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_DELETE,e)),b++),f.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_INSERT,f)),b++),b++):0!==b&&a[b-1][0]==DIFF_EQUAL?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)a[b-1][0]==DIFF_EQUAL&&a[b+1][0]==DIFF_EQUAL&&(a[b][1].substring(a[b][1].length-
a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};
diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==DIFF_INSERT&&(c+=a[g][1].length);a[g][0]!==DIFF_DELETE&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===DIFF_DELETE?f:f+(b-e)};
diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],l=a[g][1].replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case DIFF_INSERT:b[g]='<ins style="background:#e6ffe6;">'+l+"</ins>";break;case DIFF_DELETE:b[g]='<del style="background:#ffe6e6;">'+l+"</del>";break;case DIFF_EQUAL:b[g]="<span>"+l+"</span>"}}return b.join("")};
diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_INSERT&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_DELETE&&(b[c]=a[c][1]);return b.join("")};
diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][1];switch(a[e][0]){case DIFF_INSERT:c+=f.length;break;case DIFF_DELETE:d+=f.length;break;case DIFF_EQUAL:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case DIFF_INSERT:b[c]="+"+encodeURI(a[c][1]);break;case DIFF_DELETE:b[c]="-"+a[c][1].length;break;case DIFF_EQUAL:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=new diff_match_patch.Diff(DIFF_INSERT,decodeURI(h))}catch(k){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var l=parseInt(h,10);if(isNaN(l)||0>l)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=l);"="==f[g].charAt(0)?c[d++]=new diff_match_patch.Diff(DIFF_EQUAL,h):c[d++]=
new diff_match_patch.Diff(DIFF_DELETE,h);break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return f.Match_Distance?e+g/f.Match_Distance:g?1:e}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));var l=1<<b.length-1;h=-1;for(var k,m,p=b.length+a.length,x,w=0;w<b.length;w++){k=0;for(m=p;k<m;)d(w,
c+m)<=g?k=m:p=m,m=Math.floor((p-k)/2+k);p=m;k=Math.max(1,c-m+1);var q=Math.min(c+m,a.length)+b.length;m=Array(q+2);for(m[q+1]=(1<<w)-1;q>=k;q--){var t=e[a.charAt(q-1)];m[q]=0===w?(m[q+1]<<1|1)&t:(m[q+1]<<1|1)&t|(x[q+1]|x[q])<<1|1|x[q+1];if(m[q]&l&&(t=d(w,q-1),t<=g))if(g=t,h=q-1,h>c)k=Math.max(1,2*c-h);else break}if(d(w+1,c)>g)break;x=m}return h};
diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){if(null===a.start2)throw Error("patch not initialized");for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));(d=b.substring(a.start2+a.length1,
a.start2+a.length1+d))&&a.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,d));a.start1-=c.length;a.start2-=c.length;a.length1+=c.length+d.length;a.length2+=c.length+d.length}};
diff_match_patch.prototype.patch_make=function(a,b,c){if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c){var d=a;b=this.diff_main(d,b,!0);2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b))}else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,l=0;l<b.length;l++){var k=b[l][0],m=b[l][1];e||k===DIFF_EQUAL||(a.start1=f,a.start2=g);switch(k){case DIFF_INSERT:a.diffs[e++]=b[l];a.length2+=m.length;d=d.substring(0,g)+m+d.substring(g);break;case DIFF_DELETE:a.length1+=m.length;a.diffs[e++]=b[l];d=d.substring(0,g)+d.substring(g+m.length);break;case DIFF_EQUAL:m.length<=2*this.Patch_Margin&&e&&b.length!=l+1?(a.diffs[e++]=b[l],a.length1+=m.length,a.length2+=m.length):
m.length>=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}k!==DIFF_INSERT&&(f+=m.length);k!==DIFF_DELETE&&(g+=m.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};
diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=new diff_match_patch.Diff(d.diffs[f][0],d.diffs[f][1]);e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),l=-1;if(h.length>this.Match_MaxBits){var k=this.match_main(b,h.substring(0,this.Match_MaxBits),g);-1!=k&&(l=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==l||k>=l)&&(k=-1)}else k=this.match_main(b,h,
g);if(-1==k)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=k-g,g=-1==l?b.substring(k,k+h.length):b.substring(k,l+this.Match_MaxBits),h==g)b=b.substring(0,k)+this.diff_text2(a[f].diffs)+b.substring(k+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);h=0;var m;for(l=0;l<a[f].diffs.length;l++){var p=a[f].diffs[l];p[0]!==DIFF_EQUAL&&(m=this.diff_xIndex(g,h));p[0]===
DIFF_INSERT?b=b.substring(0,k+m)+p[1]+b.substring(k+m):p[0]===DIFF_DELETE&&(b=b.substring(0,k+m)+b.substring(k+this.diff_xIndex(g,h+p[1].length)));p[0]!==DIFF_DELETE&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;d=a[0];var e=d.diffs;if(0==e.length||e[0][0]!=DIFF_EQUAL)e.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;
0==e.length||e[e.length-1][0]!=DIFF_EQUAL?(e.push(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,l=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g)));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){g=d.diffs[0][0];var k=d.diffs[0][1];g===DIFF_INSERT?(h.length2+=
k.length,f+=k.length,h.diffs.push(d.diffs.shift()),l=!1):g===DIFF_DELETE&&1==h.diffs.length&&h.diffs[0][0]==DIFF_EQUAL&&k.length>2*b?(h.length1+=k.length,e+=k.length,l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),d.diffs.shift()):(k=k.substring(0,b-h.length1-this.Patch_Margin),h.length1+=k.length,e+=k.length,g===DIFF_EQUAL?(h.length2+=k.length,f+=k.length):l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),k==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(k.length))}g=this.diff_text2(h.diffs);
g=g.substring(g.length-this.Patch_Margin);k=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==k&&(h.length1+=k.length,h.length2+=k.length,0!==h.diffs.length&&h.diffs[h.diffs.length-1][0]===DIFF_EQUAL?h.diffs[h.diffs.length-1][1]+=k:h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,k)));l||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_DELETE,g));else if("+"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_INSERT,g));else if(" "==e)f.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g));else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};
diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
diff_match_patch.patch_obj.prototype.toString=function(){for(var a=["@@ -"+(0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1)+" +"+(0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2)+" @@\n"],b,c=0;c<this.diffs.length;c++){switch(this.diffs[c][0]){case DIFF_INSERT:b="+";break;case DIFF_DELETE:b="-";break;case DIFF_EQUAL:b=" "}a[c+1]=b+encodeURI(this.diffs[c][1])+"\n"}return a.join("").replace(/%20/g," ")};

// Everything above is unmodifed. This allows importing as an ES6 module.



;// CONCATENATED MODULE: ./src/Diff.js


class Diff {
	static diffChars(old_text, new_text) {
		let dmp = new diff_match_patch();
		let diff = dmp.diff_main(old_text, new_text);

		dmp.diff_cleanupSemantic(diff);

		return diff;
	}

	static diffLines(old_text, new_text, context) {
		let dmp = new diff_match_patch();

		let munged = dmp.diff_linesToChars_(old_text, new_text);
		let diff = dmp.diff_main(munged.chars1, munged.chars2, false);
		dmp.diff_charsToLines_(diff, munged.lineArray);

		let added = [], removed = [];
		let hunk = "", unified = "";
		let new_start = 1, old_start = 1, new_end = 1, old_end = 1;

		for (let b = 0; b < diff.length; b++) {
			let block = diff[b];
			let lines = block[1].split("\n");

			if (lines[lines.length - 1] == "")
				lines.pop();

			if (block[0] == 0 && lines.length > 2 * context) {
				if (b > 0) {
					for (let i = 0; i < context; i++)
						hunk += " " + lines[i] + "\n";

					unified += `@@ -${old_start},${old_end - old_start + context} +${new_start},${new_end - new_start + context} @@\n${hunk}`;
				}
				hunk = "";

				if (b < diff.length - 1) {
					for (let i = lines.length - context; i < lines.length; i++)
						hunk += " " + lines[i] + "\n";

					old_end += lines.length;
					new_end += lines.length;
					old_start = old_end - context;
					new_start = new_end - context;
				}
			} else {
				let prefix;

				if (block[0] == -1) {
					prefix = "-";
					old_end += lines.length;
				} else if (block[0] == 1) {
					prefix = "+";
					new_end += lines.length;
				} else {
					prefix = " ";
					new_end += lines.length;
					old_end += lines.length;
				}

				for (let i = 0; i < lines.length; i++)
					hunk += prefix + lines[i] + "\n";
			}

			if (block[0] == 1)
				added.push(...lines);
			else if (block[0] == -1)
				removed.push(...lines);
		}

		if (hunk.length)
			unified += `@@ -${old_start},${old_end - old_start} +${new_start},${new_end - new_start} @@\n${hunk}`;

		return { added, removed, unified };
	}
}

;// CONCATENATED MODULE: ./src/BatchGetter.js




function uniq(array) {
	return [...new Set(array)];
}

function rvsort(list) {
	list.sort((a, b) => a.timestamp == b.timstamp ?
			  b.revid - a.revid :
			  parseTS(b.timestamp) - parseTS(a.timestamp));
}
function getTitle(fulltitle, ns) {
	return ns == 0 ? fulltitle : fulltitle.replace(/^.*?:/, "");
}

function getOAuthID(tags) {
	for (let tag of tags) {
		let m = tag.match(/^OAuth CID: (\d+)$/);

		if (m)
			return parseInt(m[1], 10);
	}

	return null;
}

function parseTS(ts) {
	return Math.floor(Date.parse(ts) / 1000);
}

function getRestrictions(protection) {
	let restrictions = {
		edit: [],
		move: [],
		create: [],
		upload: []
	};

	for (let p of protection)
		if (p.type in restrictions && !restrictions[p.type].includes(p.level))
			restrictions[p.type].push(p.level);

	return restrictions;
}

function getLinks(oldp, newp) {
	if (!oldp || !newp)
		return null;

	return {
		all: newp.externallinks,
		old: oldp.externallinks,
		added: newp.externallinks.filter(link => !oldp.externallinks.includes(link)),
		removed: oldp.externallinks.filter(link => !newp.externallinks.includes(link)),
	};
}

function getFirst(revisions) {
	if (!revisions || revisions[revisions.length - 1].parentid !== 0)
		return null;

	return revisions[revisions.length - 1];
}

function getRecentContributors(revisions) {
	if (!revisions)
		return;

	return [...new Set(revisions.slice(0, 100).map(r => r.user))].slice(0, 10);
}

function getDiff(vars) {
	let diff = Diff.diffLines(vars.old_wikitext, vars.new_wikitext, 2);

	vars.added_lines = diff.added;
	vars.added_lines_pst = diff.added;
	vars.removed_lines = diff.removed;
	vars.removed_lines_pst = diff.removed;
	vars.edit_diff = diff.unified;
	vars.edit_diff_pst = diff.unified;
}

function buildEntry(page, user, rvnew, rvold, wikiId, wikiLang) {
	let restrictions = getRestrictions(page.protection);
	let links = getLinks(rvold?.parsed, rvnew?.parsed);
	let first = getFirst(page.revisions);
	let recent = getRecentContributors(page.revisions);

	return {
		action: "edit",
		id: "r" + rvnew.revid,
		filter_id: 0,
		revid: rvnew.revid,
		title: page.title,
		user: rvnew.user,
		ns: page.ns,
		timestamp: rvnew.timestamp,
		result: "",
		details: {
			action: "edit",
			timestamp: parseTS(rvnew.timestamp).toString(),
			wiki_name: wikiId,
			wiki_language: wikiLang,

			page_namespace: page.ns,
			page_id: rvnew.parentid > 0 ? page.pageid : 0,
			page_prefixedtitle: page.title,
			page_title: getTitle(page.title, page.ns),
			page_restrictions_edit: restrictions.edit,
			page_restrictions_move: restrictions.move,
			page_restrictions_upload: restrictions.upload,
			page_restrictions_create: restrictions.create,

			summary: rvnew.comment ?? "",

			new_wikitext: rvnew.slots?.main?.["*"] ?? "",
			new_pst: rvnew.slots?.main?.["*"] ?? "",
			new_content_model: rvnew.slots?.main?.contentmodel ?? null,
			new_size: rvnew.size,
			old_wikitext: rvold?.slots?.main?.["*"] ?? "",
			old_content_model: rvold?.slots?.main?.contentmodel ?? null,
			old_size: rvold?.size ?? 0,
			edit_delta: rvnew.size - (rvold?.size ?? 0),
			user_type: user.registration ? "named" : "ip",
			user_name: rvnew.user,
			user_editcount: user.editcount,
			user_groups: user.groups,
			user_rights: user.rights,
			user_age: user.registration ? parseTS(rvnew.timestamp) - parseTS(user.registration) : 0,
			user_blocked: !!user.blockid,
			user_emailconfirm: user.emailable ? parseTS(user.registration) : null,
			user_mobile: rvnew.tags?.includes('mobile edit') || false,
			user_app: rvnew.tags?.includes('mobile edit') && !rvnew.tags?.includes('mobile web edit'),

			new_html: rvnew.parsed ? rvnew.parsed?.text?.["*"] : null,
			new_text: rvnew.parsed ? rvnew.parsed?.text?.["*"]?.replace(/<[^>]*>/g, "") : null,
			all_links: links ? links.all : null,
			old_links: links ? links.old : null,
			added_links: links ? links.added : null,
			removed_links: links ? links.removed : null,

			page_recent_contributors: recent || null,
			page_first_contributor: first ? first.user : null,
			page_age: first ? parseTS(rvnew.timestamp) - parseTS(first.timestamp) : null,
			page_last_edit_age: rvold ? parseTS(rvnew.timestamp) - parseTS(rvold.timestamp) : null,
			global_user_editcount: user.global ? user.global.editcount : 0,
			global_user_groups: user.global ? user.global.groups : [],

			tor_exit_node: false,
			oauth_consumer: getOAuthID(rvnew.tags),
		}
	};
}

function validateVar(v) {
	switch (typeof v) {
	case "number":
	case "string":
	case "boolean":
		return true;
	case "object":
		if (Array.isArray(v))
			return !v.map(validateVar).includes(false);
		return v === null;
	default:
		return false;
	}
}

function validate(entry) {
	const props = {
		id: ["number", "string"],
		filter_id: ["string"],
		user: ["string"],
		ns: ["number"],
		title: ["string"],
		result: ["string"],
		revid: ["number"],
		timestamp: ["string"],
		hidden: ["boolean"],
		details: ["object"]
	};

	for (let prop of Object.keys(entry)) {
		if (!(props[prop] ?? []).includes(typeof entry[prop]))
			delete entry[prop];
	}

	if (entry.id === undefined || !entry.details)
		return false;

	for (let v of Object.keys(entry.details)) {
		if (!validateVar(entry.details[v]))
			return false;
	}

	return true;
}

class BatchGetter {
	constructor(baseURL, status) {
		this.baseURL = baseURL;
		this.abortables = [];
		this.status = status || (() => null);
	}

	async queryApi(params) {
		let request = {
			action: "query",
			format: "json"
		};

		for (let [key, value] of Object.entries(params))
			if (value !== undefined && value !== null)
				request[key] = value;

		let url = this.baseURL + '/w/api.php?' + new URLSearchParams(request);

		let controller = new AbortController();
		this.abortables.push(controller);

		let response = await fetch(url, {
			signal: controller.signal,
			headers: {
				"Api-User-Agent": "FilterDebugger/0.1 ([[w:User:Suffusion of Yellow]])"
			}
		});
		let json = await response.json();

		if (json.error)
			throw new Error(`${json.error.code}: ${json.error.info}`);

		return json;
	}

	async setupMetadata() {
		let result = await this.queryApi({
			meta: "siteinfo|userinfo",
			siprop: "general|usergroups",
			uiprop: "rights"
		});

		this.wikiId = result.query.general.wikiid;
		this.wikiLang = result.query.general.lang;
		this.highLimits = result.query.userinfo.rights.includes("apihighlimits");
		this.anonUser = {
			editcount: null,
			groups: ["*"],
			rights: result.query.usergroups.filter(g => g.name == "*")[0].rights
		};
	}
	abortAll() {
		for (let abortable of this.abortables) {
			abortable.abort();
		}
		this.abortables = [];
	}

	async getAbuseLogDetails(abuselog, query, cached) {
		let logById = {}, gaps = [], missing = 0, found = 0;

		for (let i = 0; i < abuselog.length; i++) {
			if (abuselog[i].id in cached) {
				abuselog[i] = cached[abuselog[i].id];
			} else {
				logById[abuselog[i].id] = abuselog[i];
				missing++;

				if (gaps.length == 0 || gaps[gaps.length - 1].end != i - 1) {
					gaps.push({
						start: i,
						end: i
					});
				} else {
					gaps[gaps.length - 1].end = i;
				}
			}
		}

		query.formatversion = 2;
		query.aflprop = "ids|details";
		query.afllimit = 100; // apihighlimits won't help here, log hits are too big

		for (let gap of gaps) {
			query.aflstart = abuselog[gap.start].timestamp;
			query.aflend = abuselog[gap.end].timestamp;

			for (;;) {
				this.status(`Fetching details... (${found}/${missing})`);
				let result = await this.queryApi(query);

				for (let entry of result.query.abuselog) {
					found++;

					if (entry.id in logById)
						logById[entry.id].details = entry.details;
				}
				if (!result.continue)
					break;

				Object.assign(query, result.continue);
			}
		}

		return abuselog;
	}


	async fetchByIds(type, ids, progress) {
		let result = {};

		if (type == "user")
			result[0] = this.anonUser;

		ids = new Set(ids);

		let total = ids.size;

		while (ids.size) {
			let query, group = [...ids].slice(0, this.highLimits ? 500 : 50);

			progress(total - ids.size);

			switch (type) {
			case "pages":
				query = {
					prop: "info",
					pageids: group.join("|"),
					inprop: "protection"
				};
				break;
			case "users":
				query = {
					list: "users",
					ususerids: group.join("|"),
					usprop: "blockinfo|groups|rights|editcount|registration|centralids|emailable",
					formatversion: 2
				};
				break;
			case "revisions":
				query = {
					prop: "revisions",
					revids: group.join("|"),
					rvprop: "ids|contentmodel|content|user|userid|size|timestamp|comment|tags",
					rvslots: "*"
				};
				break;
			}

			let r = await (this.queryApi(query));

			let size = ids.size;

			switch (type) {
			case "revisions":
				for (let page of Object.values(r.query.pages))
					for (let rev of page.revisions) {
						ids.delete(rev.revid);
						result[rev.revid] = rev;
					}
				break;
			case "pages":
				for (let pageid of Object.keys(r.query.pages)) {
					ids.delete(parseInt(pageid, 10));
					result[pageid] = r.query.pages[pageid];
				}
				break;
			case "users":
				for (let user of r.query.users) {
					ids.delete(user.userid);
					result[user.userid] = user;
				}
				break;
			}

			// Avoid infinite loop on error
			if (size == ids.size) {
				break;
			}
		}

		if (type == "users")
			result[0] = this.anonUser;

		return result;
	}

	async fetchSlow(type, ids, result, progress) {
		let query, cnt = 0;
		let pending = [];
		let maxConcurrent = 10;

		ids = [...new Set(ids)];

		progress(0);

		for (let id of ids) {
			switch (type) {
			case "firstrev":
				query = {
					prop: "revisions",
					rvprop: "timestamp|user|ids",
					rvlimit: 1,
					rvdir: "newer",
					pageids: id
				};
				break;
			case "lastrevs":
				query = {
					prop: "revisions",
					rvprop: "timestamp|user|ids",
					rvlimit: 100,
					pageids: id
				};
				break;
			case "parse":
				query = {
					action: "parse",
					prop: "text|externallinks",
					disablelimitreport: true,
					oldid: id
				};
				maxConcurrent = 2;
				break;
			case "global":
				query = {
					meta: "globaluserinfo",
					guiprop: "groups|editcount",
					guiid: id
				};
				break;
			}

			let idx = pending.length < maxConcurrent ? pending.length : await Promise.race(pending);

			if (idx === undefined)
				break; // Something went wrong with the last request

			pending[idx] = this.queryApi(query).then(response => {
				progress(++cnt);

				if (!result[id])
					return idx;

				switch (type) {
				case "firstrev":
				case "lastrevs":
					if (!result[id].revisions)
						result[id].revisions = response.query.pages[id].revisions;
					else
						result[id].revisions.push(...response.query.pages[id].revisions);
					break;
				case "parse":
					result[id].parsed = response.parse;
					break;
				case "global":
					result[id].global = response.query.globaluserinfo;
					break;
				}

				return idx;
			});
		}
		await Promise.all(pending);

		return result;
	}

	async getRevisionDetails(list, expensive, cached) {
		let uncached = list.filter(r => !(r.id in cached));

		let pageids = uniq(uncached.map(r => r.pageid));
		let userids = uniq(uncached.map(r => r.userid));
		let revisionids = uncached.map(r => r.revid);

		revisionids.push(...uncached.map(r => r.parentid ?? r.old_revid).filter(r => r));

		revisionids = uniq(revisionids);

		let pages = await this.fetchByIds("pages", pageids,
										  cnt => this.status(`Fetching page information... (${cnt}/${pageids.length})`));
		let users = await this.fetchByIds("users", userids,
									 cnt => this.status(`Fetching user information... (${cnt}/${userids.length})`));
		let revisions = await this.fetchByIds("revisions", revisionids,
										 cnt => this.status(`Fetching revision information.. (${cnt}/${revisionids.length})`));

		if (expensive) {
			await this.fetchSlow("lastrevs", pageids, pages,
				cnt => this.status(`Fetching recent contributors.. (${cnt}/${pageids.length})`));

			await this.fetchSlow("firstrev", pageids, pages,
				cnt => this.status(`Fetching first contributors and creation timestamps... (${cnt}/${pageids.length})`));

			let globalids = [], globalusers = {};

			for (let id of userids)
				if (users[id].centralids) {
					globalusers[users[id].centralids.CentralAuth] = { userid: id };
					globalids.push(users[id].centralids.CentralAuth);
				}

			globalids = uniq(globalids);

			await this.fetchSlow("global", globalids, globalusers,
								 cnt => this.status(`Fetching global user info... (${cnt}/${globalids.length})`));

			for (let id of globalids)
				users[globalusers[id].userid].global = globalusers[id].global;

			await this.fetchSlow("parse", revisionids, revisions,
								 cnt => this.status(`Parsing wikitext... (${cnt}/${revisionids.length})`));
		}

		this.status("Building entries and computing diffs...");

		let abuselog = [];
		for (let r of list) {
			if (r.id in cached)
				abuselog.push(cached[r.id]);
			else {
				let entry = await buildEntry(pages[r.pageid],
											 users[r.userid],
											 revisions[r.revid],
											 revisions[r.parentid ?? r.old_revid],
											 this.wikiId,
											 this.wikiLang);

				getDiff(entry.details);

				if (!expensive)
					entry.partial = true;

				abuselog.push(entry);
			}
		}

		this.status('Finished building variables');

		return abuselog;
	}

	async getBatchFromFile(params) {
		if (params.file instanceof File)
			this.status(`Reading from ${params.file.name}...`);
		else {
			this.status("No file specified");
			return [];
		}

		try {
			let batch = [], stream = params.file.stream();

			if (params.file.type == "application/gzip")
				stream = stream.pipeThrough(new DecompressionStream("gzip"));

			stream = stream.pipeThrough(new JSONStream());

			let reader = stream.getReader();

			for(;;) {
				let { value: entry, done } = await reader.read();

				if (done)
					break;

				if (!validate(entry))
					throw new Error(`Malformed entry at position ${batch.length}`);

				let timestamp = Date.parse(entry.timestamp);

				if (params.end !== undefined && timestamp < Date.parse(params.end))
					break;
				if (params.limit !== undefined && batch.length >= params.limit)
					break;

				if (params.user !== undefined && entry.user != params.user)
					continue;
				if (params.title !== undefined && entry.title != params.title)
					continue;
				if (params.start !== undefined && timestamp > Date.parse(params.start))
					continue;

				batch.push(entry);
			}

			this.status(`Found ${batch.length} entries in ${params.file.name}`);

			return batch;
		} catch (error) {
			this.status(`Error reading ${params.file.name}: ${error.message}`);

			return [];
		}
	}

	async getBatch(params) {
		if (params.mode == "file")
			return this.getBatchFromFile(params);

		if (this.wikiID === undefined)
			await this.setupMetadata();

		let queries = {
			recentchanges: {
				query: {
					list: "recentchanges",
					rctype: "edit",
					rcprop: "userid|ids|timestamp"
				},
				params: ["user", "title", "start", "end", "limit", "namespace", "tag", "show"],
				prefix: "rc"
			},
			usercontribs: {
				query: {
					list: "usercontribs",
					ucprop: "ids|timestamp"
				},
				params: ["start", "end", "limit", "namespace", "tag", "show"],
				prefix: "uc"
			},
			revisions: {
				query: {
					prop: "revisions",
					rvprop: "userid|ids|timestamp"
				},
				params: ["user", "start", "end", "limit", "tag"],
				prefix: "rv"
			},
			allrevisions: {
				query: {
					list: "allrevisions",
					arvprop: "userid|ids|timestamp"
				},
				params: ["start", "end", "limit", "namespace"],
				prefix: "arv"
			},
			abuselog: {
				query: {
					list: "abuselog",
					aflprop: "action|filter|hidden|ids|result|revid|timestamp|title|user"
				},
				params: ["filter", "user", "title", "start", "end", "limit"],
				prefix: "afl"
			}
		};

		this.abortAll();

		if (!params.mode)
			return [];

		let type;

		if (params.mode == "abuselog")
			type = "abuselog";
		else if (params.mode == "recentchanges")
			type = "recentchanges";
		else if (params.title || params.revids)
			type = "revisions";
		else if (params.user)
			type = "usercontribs";
		else
			type = "allrevisions";

		let query = queries[type].query;
		let prefix = queries[type].prefix;

		for (let param of Object.keys(params))
			if (queries[type].params.includes(param))
				query[prefix + param] = params[param];

		let limit = params.limit ?? 100;

		if (type == "usercontribs") {
			if (params.user.includes("/"))
				query.uciprange = params.user;
			else
				query.ucuser = params.user;
		} else if (type == "revisions") {
			query.titles = params.title;
			if (params.revids) {
				query.revids = params.revids;
				delete query.rvlimit;
				delete query.rvstart;
				delete query.rvend;
			}
		} else if (type == "abuselog") {
			query.afllogid = params.logid;
		}

		let list = [];

		this.status(`Fetching metadata from ${type}...`);

		while (list.length < limit) {
			let result, group = [];

			if (!query.revids && !query.afllogid)
				query[prefix + "limit"] = Math.min(limit - list.length, this.highLimits ? 5000 : 500);

			try {
				result = (await this.queryApi(query));
			} catch (error) {
				this.status(`API returned error: ${error}`);
				return [];
			}

			if (type == "revisions") {
				for (let page of Object.keys(result.query.pages)) {
					for (let rev of result.query.pages[page].revisions) {
						rev.pageid = parseInt(page, 10);
						group.push(rev);
					}
				}

				rvsort(list);
			} else if (type == "allrevisions") {
				for (let page of result.query.allrevisions) {
					for (let rev of page.revisions) {
						rev.pageid = page.pageid;
						group.push(rev);
					}
				}

				rvsort(list);
			} else {
				group = result.query[type];
			}

			list.push(...group);

			if (!result.continue)
				break;

			Object.assign(query, result.continue);
		}

		if (list.length === 0) {
			this.status("Nothing found");

			return [];
		}

		if (type != "abuselog")
			list.forEach(r => r.id = "r" + r.revid);

		let cached = {}, cache = (typeof process == 'undefined') ? VarCache : null;

		if (cache) {
			await cache.open();

			cached = await cache.getCachedVars(this.baseURL, list, params.expensive, found => {
				if (found % 50 == 0)
					this.status(`Looking for cached details... ${found}/${list.length}`);
			});
		}

		let result = (type == "abuselog") ?
			await this.getAbuseLogDetails(list, query, cached) :
			await this.getRevisionDetails(list, params.expensive, cached);

		if (cache) {
			let size = params.cacheSize ?? 0;
			let newItems = result.length - Object.keys(cached).length;

			await cache.clearIfBiggerThan(size - newItems);

			if (result.length <= size)
				cache.cacheVars(this.baseURL, result, cached);
		}

		return result;
	}
}



;// CONCATENATED MODULE: ./src/worker.js





let threads = 1;
let ports = [];
let vardumps = {};
let filters = {};
let bg = new BatchGetter(self.location.origin, worker_status);

function worker_status(text) {
	postMessage({ status: text });
}

function evaluate(response, event) {
	let filter, vardump;

	if (event.data.filter_id !== undefined)
		filter = filters[event.data.filter_id];
	else
		filter = new ParseTree("");

	if (event.data.vardump_id !== undefined)
		vardump = vardumps[event.data.vardump_id];
	else
		vardump = {};

	let evaluator = new Evaluator(vardump);

	let log = [];

	try {
		response.result = evaluator.evaluate(filter, log, event.data.scmode || 'allpaths');
	} catch (error) {
		response.error = error.message;
		response.stack = error.stack;
	}

	response.log = log;
}

self.onmessage = function(event) {
	handleMessage(event, self);
};

async function handleMessage(event, replyTo) {
	let response = {
		uid: event.data.uid,
		id: event.data.id
	};

	switch (event.data.action) {
	case 'setsecondaries':
		threads = event.data.ports.length + 1;
		ports = event.data.ports;
		return;
	case 'setprimary':
		threads = 1;
		event.data.port.onmessage = (event) => self.onmessage(event, event.data.port);
		return;
	case 'evaluate':
		evaluate(response, event);
		break;
	case 'setfilter':
		try {
			filters[event.data.filter_id] = new ParseTree(event.data.filter);
		} catch (error) {
			filters[event.data.filter_id] = new ParseTree("");

			response.error = error.message;
			response.start = error.start;
			response.end = error.end;
		}
		break;
	case 'clearfilter':
		delete filters[event.data.filter_id];
		break;
	case 'clearallfilters':
		filters = {};
		break;
	case 'setvardump':
		vardumps[event.data.vardump_id] = event.data.vardump;
		break;
	case 'clearvardump':
		delete vardumps[event.data.vardump_id];
		break;
	case 'clearallvardumps':
		vardumps = {};
		break;
	case 'getvar':
		if (event.data.name == "*")
			response.vardump = vardumps[event.data.vardump_id];
		else
			response.vardump = {
				[event.data.name]: vardumps[event.data.vardump_id][event.data.name]
			};
		break;
	case 'diff':
		response.diff = Diff.diffChars(vardumps[event.data.vardump_id].old_wikitext ?? "",
			vardumps[event.data.vardump_id].new_wikitext ?? "");
		break;
	case 'getbatch': {
		let batch = await bg.getBatch(event.data.params);

		if (event.data.stash) {
			response.owners = {};
			for (let i = 0; i < batch.length; i++) {
				let owner = i % threads;
				if (owner == 0)
					vardumps[batch[i].id] = batch[i].details;
				else
					ports[owner - 1].postMessage({
						action: "setvardump",
						vardump_id: batch[i].id,
						vardump: batch[i].details
					});
				response.owners[batch[i].id] = owner;
				delete batch[i].details;
			}
		}
		response.batch = batch;
		break;
	}
	default:
		response.error = "unknown action";
		break;
	}

	replyTo.postMessage(response);
}

/******/ })()
;//</nowiki>