@borgar/fx 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/fx.js +2 -0
- package/dist/package.json +1 -0
- package/{src → lib}/a1-test.js +0 -0
- package/{src → lib}/a1.js +0 -0
- package/lib/addMeta-test.js +77 -0
- package/{src → lib}/addMeta.js +4 -2
- package/{src → lib}/constants.js +2 -2
- package/{src → lib}/index.js +0 -0
- package/{src → lib}/lexer-test.js +289 -5
- package/{src → lib}/lexer.js +39 -5
- package/lib/package.json +1 -0
- package/{src → lib}/parseRef.js +4 -1
- package/{src → lib}/quickVerify.js +0 -0
- package/{src → lib}/rc-test.js +0 -0
- package/{src → lib}/rc.js +0 -0
- package/{src → lib}/translate-toA1-test.js +0 -0
- package/{src → lib}/translate-toRC-test.js +0 -0
- package/{src → lib}/translate.js +0 -0
- package/package.json +31 -16
- package/rollup.config.js +21 -0
- package/src/addMeta-test.js +0 -77
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ The library is also provided as an ES6 module in an NPM package:
|
|
|
22
22
|
|- | - | -
|
|
23
23
|
| `emitRanges` | `false` | Adds offset ranges on the tokens: `{ range: [ start, end ] }`
|
|
24
24
|
| `mergeRanges` | `true` | Should ranges be returned as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`).
|
|
25
|
+
| `negativeNumbers` | `false` | Merges all unary minuses with their immediately following number tokens (`-`,`1`) => `-1`
|
|
25
26
|
| `r1c1` | `false` | Ranges are expected to be in the R1C1 style format rather than the more popular A1 style.
|
|
26
27
|
|
|
27
28
|
The returned output will be an array of objects representing the tokens:
|
|
@@ -106,13 +107,13 @@ The returned output will be the same array of tokens but the following propertie
|
|
|
106
107
|
|
|
107
108
|
Matching parens will be tagged with `.groupId` string identifier as well as a `.depth` number value (indicating the level of nesting).
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
Closing parens without a counterpart will be tagged with `.error` (boolean true).
|
|
110
111
|
|
|
111
112
|
#### Curly brackets { }
|
|
112
113
|
|
|
113
114
|
Matching curly brackets will be tagged with `.groupId` string identifier. These may not be nested in Excel.
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
Closing curly brackets without a counterpart will be tagged with `.error` (boolean `true`).
|
|
116
117
|
|
|
117
118
|
#### Ranges (`RANGE` or `RANGE_BEAM` type tokens)
|
|
118
119
|
|
package/dist/fx.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";function t(t){return t.split(/(\d+|[a-zA-Z]+)/).every((t=>{const e=parseInt(t,36);return!!isNaN(e)||(isFinite(t)?e<=2183880786:e<=43321)}))}Object.defineProperty(exports,"__esModule",{value:!0});const e={R:1048577,"R[":1048576,C:16385,"C[":16384};function r(t){const r=/([RC]\[?)(-?\d+)/gi;let n;for(;null!==(n=r.exec(t));){const t=e[n[1]],r=parseInt(n[2],10);if(r>=t||r<=-t)return!1}return!0}const n="range",o="range-beam",a=/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!)/i,i=/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/,l=/^(TRUE|FALSE)\b/i,c=/^[A-Z_]+[A-Z\d_.]+(?=\s*\()/i,u=/^\n+/,p=/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,s=/^"(?:""|[^"])*("|$)/,f=/^'(?:''|[^'])*('|$)/,$=/^\[(?:[^\]])+(\]|$)/,g=/^([^ \t\n$!"`'#%&(){}<>,;:^@|~=*+-]+)(?=!)/,h=/^\$?[A-Z]{1,3}:\$?[A-Z]{1,3}/i,m=/^\$?[1-9][0-9]{0,6}:\$?[1-9][0-9]{0,6}/i,b=/^\$?[A-Z]{1,3}\$?[1-9][0-9]{0,6}/i,d="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",v="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",R=new RegExp("^".concat(v,"(:").concat(v,")?(?=\\W|$)"),"i"),x=new RegExp("^".concat(d,"(:").concat(d,")?(?=\\W|$)"),"i"),N=new RegExp("^(?:(?=[RC])".concat(d).concat(v,")"),"i"),A=/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/,E=/^[A-Z\d\\_.?]+/i,y=[["error",a],["operator",i],["bool",l],["function",c],["newline",u],["whitespace",p],["string",s],["path-quote",f],["path-brace",$],["path-prefix",g],[n,b,t],[o,h,t],[o,m,t],["number",A],["range-named",E]],C=[["error",a],["operator",i],["bool",l],["function",c],["newline",u],["whitespace",p],["string",s],["path-quote",f],["path-brace",$],["path-prefix",g],[n,N,r],[o,x,r],[o,R,r],["number",A],["range-named",E]],I=[["operator",/^[!:]/],["path-quote",f],["path-brace",$],["path-prefix",g],[n,b,t],[o,h,t],[o,m,t],["range-named",E]],w=[["operator",/^!/],["path-quote",f],["path-brace",$],["path-prefix",g],[n,N,r],[o,x,r],[o,R,r],["range-named",E]],k=(t,e)=>t&&t.type===e,T=t=>t&&":"===t.value,O=t=>t&&"!"===t.value,L={emitRanges:!1,mergeRanges:!0,negativeNumbers:!1,r1c1:!1};function M(t,e){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{emitRanges:a,mergeRanges:i,negativeNumbers:l}=Object.assign({},L,r),c=[];let u=0;const p=t=>c[c.length-t],s=t=>{const e=c.filter((t=>!k(t,"whitespace")&&!k(t,"newline")));return e[e.length-t]};if(/^=/.test(t)){const t={type:"fx-prefix",value:"=",...a?{range:[0,1]}:{}};u++,c.push(t)}for(;u<t.length;){const r=u,f=t.slice(u);let $="",g="";for(let t=0;t<e.length;t++){const[r,n,o]=e[t],a=n.exec(f);if(a&&(!o||o(a[0]))){$=r,g=a[0],u+=a[0].length;break}}$||($="unknown",g=t[u],u++);let h={type:$,value:g,...a?{range:[r,u]}:{}};if("string"!==$||g.endsWith('"')||(h.unterminated=!0),l&&"number"===$){const t=p(1);if(t&&k(t,"operator")&&"-"===t.value){const t=s(2);(!t||k(t,"fx-prefix")||k(t,"operator")&&!["%","}",")","#"].includes(t.value))&&(c.pop(),h.value="-"+g)}}if(i&&($===n||"range-named"===$||$===o)){const t=[];if(T(p(1))&&k(p(2),n)&&$===n&&t.unshift(...c.splice(-2,2)),O(p(1)))if(k(p(2),"path-quote")||k(p(2),"path-brace"))t.unshift(...c.splice(-2,2));else if(k(p(2),"path-prefix")){const e=k(p(3),"path-brace")?3:2;t.unshift(...c.splice(-e,e))}t.length&&(h={type:$,value:t.map((t=>t.value)).join("")+g,...a?{range:[t[0].range[0],u]}:{}})}c.push(h)}return c}function _(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=e.r1c1?C:y;return M(t,r,e)}const Z=t=>t.slice(1,-1).replace(/''/g,"'"),S=t=>t&&":"===t.value&&{},U=t=>t&&t.type===n&&{r0:t.value},F=t=>t&&t.type===n&&{r1:t.value},P=t=>t&&"!"===t.value&&{},q=t=>t&&t.type===o&&{r0:t.value},W=t=>t&&"path-prefix"===t.type&&/^[^:\\/?*[\]]{0,31}$/.test(t.value)&&{sheetName:t.value},j=t=>t&&"path-brace"===t.type&&{workbookName:t.value.slice(1,-1)},G=t=>t&&"range-named"===t.type&&{name:t.value},X=t=>{if(t&&"path-quote"===t.type){const e=/(?:\[(.+?)\])?([^[\]]+?)$/.exec(Z(t.value));if(e){const[,t,r]=e;if(!r||/^[^:\\/?*[\]]{0,31}$/.test(r))return{workbookName:t||"",sheetName:r||""}}}},D=[[U],[U,S,F],[q],[X,P,U],[X,P,U,S,F],[X,P,q],[W,P,U],[W,P,U,S,F],[W,P,q],[j,W,P,U],[j,W,P,U,S,F],[j,W,P,q]],B=D.concat([[G],[t=>t&&"path-prefix"===t.type&&{workbookName:t.value},P,G],[t=>t&&"path-quote"===t.type&&{workbookName:Z(t.value)},P,G]]);function H(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];const n=M(t,r,{emitRanges:!1,mergeRanges:!1}),o={sheetName:"",workbookName:"",r0:"",r1:"",name:""};n.length&&"fx-prefix"===n[0].type&&n.shift();const a=e?B:D;for(let t=0;t<a.length;t++){const e={...o};if(a[t].length===n.length){if(a[t].every(((t,r)=>{const o=t(n[r]);return Object.assign(e,o),o})))return e}}return null}function z(t){const e=(t||"").toUpperCase();let r=0,n=0;for(;n!==e.length;++n){const t=e.charCodeAt(n);t>=65&&t<=90&&(r=26*r+t-64)}return r-1}function K(t){let e=t,r="";for(;e>=0;)r=String.fromCharCode(e%26+65)+r,e=Math.floor(e/26)-1;return r}function V(t){return+t-1}function Q(t){return String(t+1)}function Y(t){const{top:e,left:r,bottom:n,right:o}=t;return{top:e,left:r,bottom:n,right:o,$left:!1,$right:!1,$top:!1,$bottom:!1}}function J(t){const e=t=>t?"$":"",{top:r,left:n,bottom:o,right:a,$left:i,$right:l,$top:c,$bottom:u}=t;return 0===r&&1048575===o?e(i)+K(n)+":"+e(l)+K(a):0===n&&16383===a?e(c)+Q(r)+":"+e(u)+Q(o):null==a||null==o||a===n&&o===r?e(i)+K(n)+e(c)+Q(r):e(i)+K(n)+e(c)+Q(r)+":"+e(l)+K(a)+e(u)+Q(o)}function tt(t){let e,r=0,n=0,o=1048575,a=16383,i=!1,l=!1,c=!1,u=!1;if(e=/^(\$?)([A-Z]{1,3}):(\$?)([A-Z]{1,3})$/.exec(t)){const t=z(e[2]),p=z(e[4]);return n=Math.min(t,p),a=Math.max(t,p),l=!!e[t<=p?1:3],u=!!e[t<=p?3:1],i=!0,c=!0,{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}if(e=/^(\$?)([1-9]\d{0,6}):(\$?)([1-9]\d{0,6})$/.exec(t)){const t=V(e[2]),p=V(e[4]);return r=Math.min(t,p),o=Math.max(t,p),i=!!e[t<=p?1:3],c=!!e[t<=p?3:1],l=!0,u=!0,{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}{const[p,s]=t.split(":");if(e=/^(\$?)([A-Z]{1,3})(\$?)([1-9]\d{0,6})$/i.exec(p))return n=z(e[2]),r=V(e[4]),l=!!e[1],i=!!e[3],s&&(e=/^(\$?)([A-Z]{1,3})(\$?)([1-9]\d{0,6})$/i.exec(s))?(a=z(e[2]),o=V(e[4]),u=!!e[1],c=!!e[3],o<r&&([r,o,i,c]=[o,r,c,i]),a<n&&([n,a,l,u]=[a,n,u,l])):(o=r,a=n,c=i,u=l),{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}return null}function et(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];const r=H(t,e,I);if(r&&(r.r0||r.name)){let t=null;return r.r0&&(t=r.r1?tt(r.r0+":"+r.r1):tt(r.r0)),r.name||t?(r.range=t,delete r.r0,delete r.r1,r):null}return null}var rt={fromCol:z,toCol:K,toRelative:Y,toAbsolute:function(t){const{top:e,left:r,bottom:n,right:o}=t;return{top:e,left:r,bottom:n,right:o,$left:!0,$right:!0,$top:!0,$bottom:!0}},to:J,from:tt,parse:et};function nt(){let t=1;return()=>"fxg"+t++}function ot(t,e){return e?String(t+1):t?"["+t+"]":""}function at(t){const{r0:e,c0:r,r1:n,c1:o,$c0:a,$c1:i,$r0:l,$r1:c}=t;if(0===e&&1048575===n){const t=ot(r,a),e=ot(o,i);return"C"+(t===e?t:t+":C"+e)}if(0===r&&16383===o){const t=ot(e,l),r=ot(n,c);return"R"+(t===r?t:t+":R"+r)}const u=ot(e,l),p=ot(n,c),s=ot(r,a),f=ot(o,i);return u!==p||s!==f?"R"+u+"C"+s+":R"+p+"C"+f:"R"+u+"C"+s}function it(t){let e=0,r=0,n=1048575,o=16383,a=!1,i=!1,l=!1,c=!1;const u=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(t);u?(u[1]?e=parseInt(u[1],10):u[2]&&(e=parseInt(u[2],10)-1,a=!0),n=e,l=a,t=t.slice(u[0].length)):(a=!0,l=!0);const p=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(t);return p?(p[1]?r=parseInt(p[1],10):p[2]&&(r=parseInt(p[2],10)-1,i=!0),o=r,c=i,t=t.slice(p[0].length)):(i=!0,c=!0),!u&&!p||t.length?null:{r0:e,c0:r,r1:n,c1:o,$r0:a,$c0:i,$r1:l,$c1:c}}function lt(t){const[e,r]=t.split(":",2),n=it(e);if(!n)return null;if(n&&r){const t=it(r);if(!t)return null;n.r1=t.r1,n.c1=t.c1,n.$r1=t.$r1,n.$c1=t.$c1}return n}var ct={to:at,from:lt,parse:function(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];const r=H(t,e,w);if(r&&(r.r0||r.name)){const t=r.r1?lt(r.r0+":"+r.r1):lt(r.r0);return r.name||t?(r.range=t,delete r.r0,delete r.r1,r):null}return null}};function ut(t,e,r,n){let o=t;return e||(o=r+t,o<0&&(o=n+o+1),o>n&&(o-=n+1)),o}const pt={OPERATOR:"operator",BOOLEAN:"bool",ERROR:"error",NUMBER:"number",FUNCTION:"function",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",PATH_QUOTE:"path-quote",PATH_BRACE:"path-brace",PATH_PREFIX:"path-prefix",RANGE:n,RANGE_BEAM:o,RANGE_NAMED:"range-named",FX_PREFIX:"fx-prefix",UNKNOWN:"unknown"};exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.a1=rt,exports.addMeta=function(t){let{sheetName:e="",workbookName:r=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const a=[];let i=null;const l={},c=nt();return t.forEach(((t,u)=>{if(t.index=u,t.depth=a.length,"("===t.value)t.depth=a.length+1,a.push(t);else if(")"===t.value){const e=a.pop();if(e){const r=c();t.groupId=r,t.depth=e.depth,e.groupId=r}else t.error=!0}else if("{"===t.value)i?t.error=!0:i=t;else if("}"===t.value){if(i){const e=c();t.groupId=e,i.groupId=e}else t.error=!0;i=null}else if(t.type===n||t.type===o){const n=et(t.value,!1),o=n&&"[".concat(n.workbookName||r,"]").concat(n.sheetName||e,"!").concat(n.range?J(Y(n.range)):n.name).toLowerCase();o&&(o in l?t.groupId=l[o]:(t.groupId=c(),l[o]=t.groupId))}else"unknown"===t.type&&(t.error=!0)})),t},exports.rc=ct,exports.tokenTypes=pt,exports.tokenize=_,exports.translateToA1=function(t,e){const r=tt(e),a="string"==typeof t,i=a?_(t,{emitRanges:!1,mergeRanges:!1,r1c1:!0}):t;return i.forEach((t=>{if(t.type===n||t.type===o){const e={},n=lt(t.value),o=ut(n.r0,n.$r0,r.top,1048575),a=ut(n.r1,n.$r1,r.top,1048575);o>a?(e.top=a,e.$top=n.$r1,e.bottom=o,e.$bottom=n.$r0):(e.top=o,e.$top=n.$r0,e.bottom=a,e.$bottom=n.$r1);const i=ut(n.c0,n.$c0,r.left,16383),l=ut(n.c1,n.$c1,r.left,16383);i>l?(e.left=l,e.$left=n.$c1,e.right=i,e.$right=n.$c0):(e.left=i,e.$left=n.$c0,e.right=l,e.$right=n.$c1),t.value=J(e)}})),a?i.map((t=>t.value)).join(""):i},exports.translateToRC=function(t,e){const{top:r,left:a}=tt(e),i="string"==typeof t,l=i?_(t,{emitRanges:!1,mergeRanges:!1,r1c2:!1}):t;return l.forEach((t=>{if(t.type===n){const e={},n=tt(t.value);e.r0=n.$top?n.top:n.top-r,e.$r0=n.$top,e.r1=n.$bottom?n.bottom:n.bottom-r,e.$r1=n.$bottom,e.c0=n.$left?n.left:n.left-a,e.$c0=n.$left,e.c1=n.$right?n.right:n.right-a,e.$c1=n.$right,t.value=at(e)}else if(t.type===o){const e={},n=tt(t.value);e.r0=n.$top?n.top:n.top-r,e.$r0=n.$top,e.r1=n.$bottom?n.bottom:n.bottom-r,e.$r1=n.$bottom,e.c0=n.$left?n.left:n.left-a,e.$c0=n.$left,e.c1=n.$right?n.right:n.right-a,e.$c1=n.$right,t.value=at(e)}})),i?l.map((t=>t.value)).join(""):l};
|
|
2
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnguanMiLCJzb3VyY2VzIjpbIi4uL2xpYi9xdWlja1ZlcmlmeS5qcyIsIi4uL2xpYi9jb25zdGFudHMuanMiLCIuLi9saWIvbGV4ZXIuanMiLCIuLi9saWIvcGFyc2VSZWYuanMiLCIuLi9saWIvYTEuanMiLCIuLi9saWIvYWRkTWV0YS5qcyIsIi4uL2xpYi9yYy5qcyIsIi4uL2xpYi90cmFuc2xhdGUuanMiLCIuLi9saWIvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHF1aWNrVmVyaWZ5UmFuZ2VBMSAodG9rZW5WYWx1ZSkge1xuICAvLyBRdWlja2x5IGRldGVybWluZSBpZiByYW5nZSB2YWx1cyBhcmUgb3V0IG9mIGJvdW5kczogU3BsaXQgdGhlIHN0cmluZyBpbnRvXG4gIC8vIG51bWVyaWMsIGFscGhhYmV0aWNhbCwgYW5kIFwib3RoZXJcIiBjaHVua3MgYW5kIHBhcnNlIHRoZW0gYXMgYmFzZSAzNiBudW1iZXJzLlxuICAvLyBCb3RoIHJvd3MgYW5kIGNvbHMgY2FuIGJlIHJlcHJlc2VudGVkIGluIGJhc2UgMzYgYW5kIHdlIGNhbiBkZWNpZGUgd2hpY2ggd2VcbiAgLy8gaG9sZCBieSBjaGVja2luZyBpZiB0aGUgY2h1bmsgd2FzIGFscmVhZHkgYSBmaW5pdGUgbnVtYmVyLiBTbyB3ZSBjYW4gc2ltcGx5XG4gIC8vIGNvbXBhcmUgYWdhaW5zdCB0aGUgYmFzZSAzNiBwYXJzZWQgdmVyc2lvbnMgb2YgWEZEIGFuZCAxMDQ4NTc2LlxuICByZXR1cm4gdG9rZW5WYWx1ZS5zcGxpdCgvKFxcZCt8W2EtekEtWl0rKS8pLmV2ZXJ5KGQgPT4ge1xuICAgIGNvbnN0IG4gPSBwYXJzZUludChkLCAzNik7XG4gICAgaWYgKCFpc05hTihuKSkge1xuICAgICAgcmV0dXJuIGlzRmluaXRlKGQpXG4gICAgICAgID8gbiA8PSAyMTgzODgwNzg2IC8vIG1heCByb3dzXG4gICAgICAgIDogbiA8PSA0MzMyMTsgICAgIC8vIG1heCBjb2xzXG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuY29uc3QgYm91bmRzID0ge1xuICAnUic6IDEwNDg1NzcsXG4gICdSWyc6IDEwNDg1NzYsXG4gICdDJzogMTYzODUsXG4gICdDWyc6IDE2Mzg0XG59O1xuZXhwb3J0IGZ1bmN0aW9uIHF1aWNrVmVyaWZ5UmFuZ2VSQyAodG9rZW5WYWx1ZSkge1xuICBjb25zdCByZU51bXMgPSAvKFtSQ11cXFs/KSgtP1xcZCspL2dpO1xuICBsZXQgbTtcbiAgd2hpbGUgKChtID0gcmVOdW1zLmV4ZWModG9rZW5WYWx1ZSkpICE9PSBudWxsKSB7XG4gICAgY29uc3QgeCA9IGJvdW5kc1ttWzFdXTtcbiAgICBjb25zdCB2YWwgPSBwYXJzZUludChtWzJdLCAxMCk7XG4gICAgaWYgKHZhbCA+PSB4IHx8IHZhbCA8PSAteCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cbiIsImltcG9ydCB7IHF1aWNrVmVyaWZ5UmFuZ2VBMSwgcXVpY2tWZXJpZnlSYW5nZVJDIH0gZnJvbSAnLi9xdWlja1ZlcmlmeS5qcyc7XG5cbmV4cG9ydCBjb25zdCBPUEVSQVRPUiA9ICdvcGVyYXRvcic7XG5leHBvcnQgY29uc3QgQk9PTEVBTiA9ICdib29sJztcbmV4cG9ydCBjb25zdCBFUlJPUiA9ICdlcnJvcic7XG5leHBvcnQgY29uc3QgTlVNQkVSID0gJ251bWJlcic7XG5leHBvcnQgY29uc3QgRlVOQ1RJT04gPSAnZnVuY3Rpb24nO1xuZXhwb3J0IGNvbnN0IE5FV0xJTkUgPSAnbmV3bGluZSc7XG5leHBvcnQgY29uc3QgV0hJVEVTUEFDRSA9ICd3aGl0ZXNwYWNlJztcbmV4cG9ydCBjb25zdCBTVFJJTkcgPSAnc3RyaW5nJztcbmV4cG9ydCBjb25zdCBQQVRIX1FVT1RFID0gJ3BhdGgtcXVvdGUnO1xuZXhwb3J0IGNvbnN0IFBBVEhfQlJBQ0UgPSAncGF0aC1icmFjZSc7XG5leHBvcnQgY29uc3QgUEFUSF9QUkVGSVggPSAncGF0aC1wcmVmaXgnO1xuZXhwb3J0IGNvbnN0IFJBTkdFID0gJ3JhbmdlJztcbmV4cG9ydCBjb25zdCBSQU5HRV9CRUFNID0gJ3JhbmdlLWJlYW0nO1xuZXhwb3J0IGNvbnN0IFJBTkdFX05BTUVEID0gJ3JhbmdlLW5hbWVkJztcbmV4cG9ydCBjb25zdCBGWF9QUkVGSVggPSAnZngtcHJlZml4JztcbmV4cG9ydCBjb25zdCBVTktOT1dOID0gJ3Vua25vd24nO1xuXG5leHBvcnQgY29uc3QgTUFYX0NPTFMgPSAyICoqIDE0IC0gMTsgLy8gMTYzODNcbmV4cG9ydCBjb25zdCBNQVhfUk9XUyA9IDIgKiogMjAgLSAxOyAvLyAxMDQ4NTc1XG5cbmNvbnN0IHJlX0VSUk9SID0gL14jKE5BTUVcXD98RklFTEQhfENBTEMhfFZBTFVFIXxSRUYhfERJVlxcLzAhfE5VTEwhfE5VTSF8TlxcL0F8R0VUVElOR19EQVRBXFxifFNQSUxMIXxVTktOT1dOIXxGSUVMRFxcYnxDQUxDXFxifFNZTlRBWFxcP3xFUlJPUiEpL2k7XG5jb25zdCByZV9PUEVSQVRPUiA9IC9eKDw9fD49fDw+fFstKy8qXiUmPD49XXxbe30sO118WygpXXxAfDp8IXwjKS87XG5jb25zdCByZV9CT09MRUFOID0gL14oVFJVRXxGQUxTRSlcXGIvaTtcbmNvbnN0IHJlX0ZVTkNUSU9OID0gL15bQS1aX10rW0EtWlxcZF8uXSsoPz1cXHMqXFwoKS9pO1xuY29uc3QgcmVfTkVXTElORSA9IC9eXFxuKy87XG5jb25zdCByZV9XSElURVNQQUNFID0gL15bIFxcZlxcclxcdFxcdlxcdTAwYTBcXHUxNjgwXFx1MjAwMC1cXHUyMDBhXFx1MjAyOFxcdTIwMjlcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHVmZWZmXSsvO1xuY29uc3QgcmVfU1RSSU5HID0gL15cIig/OlwiXCJ8W15cIl0pKihcInwkKS87XG5jb25zdCByZV9QQVRIX1FVT1RFID0gL14nKD86Jyd8W14nXSkqKCd8JCkvO1xuY29uc3QgcmVfUEFUSF9CUkFDRSA9IC9eXFxbKD86W15cXF1dKSsoXFxdfCQpLztcbmNvbnN0IHJlX1BBVEhfUFJFRklYID0gL14oW14gXFx0XFxuJCFcImAnIyUmKCl7fTw+LDs6XkB8fj0qKy1dKykoPz0hKS87IC8vIFNoZWV0czogW146XFxcXC8/KltcXF1dezAsMzF9IChidXQgV0IgbmFtZXM/KVxuY29uc3QgcmVfQTFDT0wgPSAvXlxcJD9bQS1aXXsxLDN9OlxcJD9bQS1aXXsxLDN9L2k7XG5jb25zdCByZV9BMVJPVyA9IC9eXFwkP1sxLTldWzAtOV17MCw2fTpcXCQ/WzEtOV1bMC05XXswLDZ9L2k7XG5jb25zdCByZV9BMVJBTkdFID0gL15cXCQ/W0EtWl17MSwzfVxcJD9bMS05XVswLTldezAsNn0vaTtcbmNvbnN0IHJQYXJ0ID0gJyg/OlIoPzpcXFxcW1srLV0/XFxcXGQrXFxcXF18WzEtOV1bMC05XXswLDZ9KT8pJztcbmNvbnN0IGNQYXJ0ID0gJyg/OkMoPzpcXFxcW1srLV0/XFxcXGQrXFxcXF18WzEtOV1bMC05XXswLDR9KT8pJztcbmNvbnN0IHJlX1JDQ09MID0gbmV3IFJlZ0V4cChgXiR7Y1BhcnR9KDoke2NQYXJ0fSk/KD89XFxcXFd8JClgLCAnaScpO1xuY29uc3QgcmVfUkNST1cgPSBuZXcgUmVnRXhwKGBeJHtyUGFydH0oOiR7clBhcnR9KT8oPz1cXFxcV3wkKWAsICdpJyk7XG5jb25zdCByZV9SQ1JBTkdFID0gbmV3IFJlZ0V4cChgXig/Oig/PVtSQ10pJHtyUGFydH0ke2NQYXJ0fSlgLCAnaScpO1xuY29uc3QgcmVfTlVNQkVSID0gL14oPzpcXGQrKFxcLlxcZCspPyg/OltlRV1bKy1dP1xcZCspP3xcXGQrKS87XG5jb25zdCByZV9OQU1FRCA9IC9eW0EtWlxcZFxcXFxfLj9dKy9pOyAvLyBGSVhNRSB0aGVyZSBhcmUgc3RyaWN0ZXIgcnVsZXMgZm9yIHRoaXMhXG4vLyBjb25zdCByZV9OQU1FRCA9IC9eKD8hW1JDXSQpW0EtWsOALcizX1xcXFxdW1xcXFw/XFx3w4AtyLMuXXswLDI1NX0kL2k7XG5cbmV4cG9ydCBjb25zdCB0b2tlbkhhbmRsZXJzQTEgPSBbXG4gIFsgRVJST1IsICAgICAgIHJlX0VSUk9SIF0sXG4gIFsgT1BFUkFUT1IsICAgIHJlX09QRVJBVE9SIF0sXG4gIFsgQk9PTEVBTiwgICAgIHJlX0JPT0xFQU4gXSxcbiAgWyBGVU5DVElPTiwgICAgcmVfRlVOQ1RJT04gXSxcbiAgWyBORVdMSU5FLCAgICAgcmVfTkVXTElORSBdLFxuICBbIFdISVRFU1BBQ0UsICByZV9XSElURVNQQUNFIF0sXG4gIFsgU1RSSU5HLCAgICAgIHJlX1NUUklORyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfQTFSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZUExIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX0ExQ09MLCBxdWlja1ZlcmlmeVJhbmdlQTEgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfQTFST1csIHF1aWNrVmVyaWZ5UmFuZ2VBMSBdLFxuICBbIE5VTUJFUiwgICAgICByZV9OVU1CRVIgXSxcbiAgWyBSQU5HRV9OQU1FRCwgcmVfTkFNRUQgXVxuXTtcblxuZXhwb3J0IGNvbnN0IHRva2VuSGFuZGxlcnNSQyA9IFtcbiAgWyBFUlJPUiwgICAgICAgcmVfRVJST1IgXSxcbiAgWyBPUEVSQVRPUiwgICAgcmVfT1BFUkFUT1IgXSxcbiAgWyBCT09MRUFOLCAgICAgcmVfQk9PTEVBTiBdLFxuICBbIEZVTkNUSU9OLCAgICByZV9GVU5DVElPTiBdLFxuICBbIE5FV0xJTkUsICAgICByZV9ORVdMSU5FIF0sXG4gIFsgV0hJVEVTUEFDRSwgIHJlX1dISVRFU1BBQ0UgXSxcbiAgWyBTVFJJTkcsICAgICAgcmVfU1RSSU5HIF0sXG4gIFsgUEFUSF9RVU9URSwgIHJlX1BBVEhfUVVPVEUgXSxcbiAgWyBQQVRIX0JSQUNFLCAgcmVfUEFUSF9CUkFDRSBdLFxuICBbIFBBVEhfUFJFRklYLCByZV9QQVRIX1BSRUZJWCBdLFxuICBbIFJBTkdFLCAgICAgICByZV9SQ1JBTkdFLCBxdWlja1ZlcmlmeVJhbmdlUkMgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfUkNST1csIHF1aWNrVmVyaWZ5UmFuZ2VSQyBdLFxuICBbIFJBTkdFX0JFQU0sICByZV9SQ0NPTCwgcXVpY2tWZXJpZnlSYW5nZVJDIF0sXG4gIFsgTlVNQkVSLCAgICAgIHJlX05VTUJFUiBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuXG5leHBvcnQgY29uc3QgdG9rZW5IYW5kbGVyc1JlZnNBMSA9IFtcbiAgWyBPUEVSQVRPUiwgICAgL15bITpdLyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfQTFSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZUExIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX0ExQ09MLCBxdWlja1ZlcmlmeVJhbmdlQTEgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfQTFST1csIHF1aWNrVmVyaWZ5UmFuZ2VBMSBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuXG5leHBvcnQgY29uc3QgdG9rZW5IYW5kbGVyc1JlZnNSQyA9IFtcbiAgWyBPUEVSQVRPUiwgICAgL14hLyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfUkNSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZVJDIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX1JDUk9XLCBxdWlja1ZlcmlmeVJhbmdlUkMgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfUkNDT0wsIHF1aWNrVmVyaWZ5UmFuZ2VSQyBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuIiwiaW1wb3J0IHtcbiAgRlhfUFJFRklYLFxuICBORVdMSU5FLFxuICBOVU1CRVIsXG4gIE9QRVJBVE9SLFxuICBQQVRIX0JSQUNFLFxuICBQQVRIX1BSRUZJWCxcbiAgUEFUSF9RVU9URSxcbiAgUkFOR0UsXG4gIFJBTkdFX0JFQU0sXG4gIFJBTkdFX05BTUVELFxuICBTVFJJTkcsXG4gIFVOS05PV04sXG4gIFdISVRFU1BBQ0UsXG4gIHRva2VuSGFuZGxlcnNBMSxcbiAgdG9rZW5IYW5kbGVyc1JDXG59IGZyb20gJy4vY29uc3RhbnRzLmpzJztcblxuY29uc3QgaXNUeXBlID0gKHQsIHR5cGUpID0+IHQgJiYgdC50eXBlID09PSB0eXBlO1xuY29uc3QgaXNSYW5nZU9wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICc6JztcbmNvbnN0IGlzQmFuZ09wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICchJztcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIGVtaXRSYW5nZXM6IGZhbHNlLFxuICBtZXJnZVJhbmdlczogdHJ1ZSxcbiAgbmVnYXRpdmVOdW1iZXJzOiBmYWxzZSxcbiAgcjFjMTogZmFsc2Vcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb2tlbnMgKGZ4LCB0b2tlbkhhbmRsZXJzLCBvcHRpb25zID0ge30pIHtcbiAgY29uc3QgeyBlbWl0UmFuZ2VzLCBtZXJnZVJhbmdlcywgbmVnYXRpdmVOdW1iZXJzIH0gPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XG4gIGNvbnN0IHRva2VucyA9IFtdO1xuICBsZXQgcG9zID0gMDtcbiAgY29uc3QgbG9va0JlaGluZCA9IG4gPT4gdG9rZW5zW3Rva2Vucy5sZW5ndGggLSBuXTtcbiAgY29uc3QgbG9va0JlaGluZElnbm9yZVdTID0gbiA9PiB7XG4gICAgY29uc3Qgbm9XcyA9IHRva2Vucy5maWx0ZXIodCA9PiAhaXNUeXBlKHQsIFdISVRFU1BBQ0UpICYmICFpc1R5cGUodCwgTkVXTElORSkpO1xuICAgIHJldHVybiBub1dzW25vV3MubGVuZ3RoIC0gbl07XG4gIH07XG5cbiAgaWYgKC9ePS8udGVzdChmeCkpIHtcbiAgICBjb25zdCB0b2tlbiA9IHtcbiAgICAgIHR5cGU6IEZYX1BSRUZJWCxcbiAgICAgIHZhbHVlOiAnPScsXG4gICAgICAuLi4oZW1pdFJhbmdlcyA/IHsgcmFuZ2U6IFsgMCwgMSBdIH0gOiB7fSlcbiAgICB9O1xuICAgIHBvcysrO1xuICAgIHRva2Vucy5wdXNoKHRva2VuKTtcbiAgfVxuXG4gIHdoaWxlIChwb3MgPCBmeC5sZW5ndGgpIHtcbiAgICBjb25zdCBzdGFydFBvcyA9IHBvcztcbiAgICBjb25zdCBzID0gZnguc2xpY2UocG9zKTtcbiAgICBsZXQgdG9rZW5UeXBlID0gJyc7XG4gICAgbGV0IHRva2VuVmFsdWUgPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRva2VuSGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IFsgdHlwZSwgcmVUZXN0LCBmblRlc3QgXSA9IHRva2VuSGFuZGxlcnNbaV07XG4gICAgICBjb25zdCBtID0gcmVUZXN0LmV4ZWMocyk7XG4gICAgICBpZiAobSAmJiAoIWZuVGVzdCB8fCBmblRlc3QobVswXSkpKSB7XG4gICAgICAgIHRva2VuVHlwZSA9IHR5cGU7XG4gICAgICAgIHRva2VuVmFsdWUgPSBtWzBdO1xuICAgICAgICBwb3MgKz0gbVswXS5sZW5ndGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghdG9rZW5UeXBlKSB7XG4gICAgICB0b2tlblR5cGUgPSBVTktOT1dOO1xuICAgICAgdG9rZW5WYWx1ZSA9IGZ4W3Bvc107XG4gICAgICBwb3MrKztcbiAgICB9XG5cbiAgICBsZXQgdG9rZW4gPSB7XG4gICAgICB0eXBlOiB0b2tlblR5cGUsXG4gICAgICB2YWx1ZTogdG9rZW5WYWx1ZSxcbiAgICAgIC4uLihlbWl0UmFuZ2VzID8geyByYW5nZTogWyBzdGFydFBvcywgcG9zIF0gfSA6IHt9KVxuICAgIH07XG5cbiAgICBpZiAodG9rZW5UeXBlID09PSBTVFJJTkcgJiYgIXRva2VuVmFsdWUuZW5kc1dpdGgoJ1wiJykpIHtcbiAgICAgIHRva2VuLnVudGVybWluYXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG5lZ2F0aXZlTnVtYmVycyAmJiB0b2tlblR5cGUgPT09IE5VTUJFUikge1xuICAgICAgY29uc3QgbGFzdDEgPSBsb29rQmVoaW5kKDEpO1xuICAgICAgaWYgKGxhc3QxICYmIGlzVHlwZShsYXN0MSwgT1BFUkFUT1IpICYmIGxhc3QxLnZhbHVlID09PSAnLScpIHtcbiAgICAgICAgLy8gd2UgaGF2ZSBhIG51bWJlciBwcmVjZWRlZCBieSBhIG1pbnVzXG4gICAgICAgIGNvbnN0IGxhc3QyID0gbG9va0JlaGluZElnbm9yZVdTKDIpO1xuICAgICAgICAvLyBtaXNzaW5nIGxhc3QyIG1lYW5zIHdlIGFyZSBhdCB0aGUgc3RhcnQgb2YgdGhlIHN0cmVhbVxuICAgICAgICBpZiAoIWxhc3QyIHx8IGlzVHlwZShsYXN0MiwgRlhfUFJFRklYKSB8fCAoaXNUeXBlKGxhc3QyLCBPUEVSQVRPUikgJiYgIVsgJyUnLCAnfScsICcpJywgJyMnIF0uaW5jbHVkZXMobGFzdDIudmFsdWUpKSkge1xuICAgICAgICAgIHRva2Vucy5wb3AoKTtcbiAgICAgICAgICB0b2tlbi52YWx1ZSA9ICctJyArIHRva2VuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWVyZ2VSYW5nZXMpIHtcbiAgICAgIGlmICh0b2tlblR5cGUgPT09IFJBTkdFIHx8IHRva2VuVHlwZSA9PT0gUkFOR0VfTkFNRUQgfHwgdG9rZW5UeXBlID09PSBSQU5HRV9CRUFNKSB7XG4gICAgICAgIGNvbnN0IG1lcmdlID0gW107XG4gICAgICAgIC8vIGpvaW4gQTE6QTEgb3IgUkM6UkMtXG4gICAgICAgIGlmIChpc1JhbmdlT3AobG9va0JlaGluZCgxKSkgJiYgaXNUeXBlKGxvb2tCZWhpbmQoMiksIFJBTkdFKSAmJiB0b2tlblR5cGUgPT09IFJBTkdFKSB7XG4gICAgICAgICAgLy8gc2hvdWxkIG5vdCBiZSBkb25lIHRoaXMgaWYgY3VycmVudCBvciBsYXN0IHJhbmdlcyBhcmUgQTpBIG9yIDE6MSwgb3IgUiBvciBDKVxuICAgICAgICAgIG1lcmdlLnVuc2hpZnQoLi4udG9rZW5zLnNwbGljZSgtMiwgMikpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGpvaW4gcHJlZml4ZXNcbiAgICAgICAgaWYgKGlzQmFuZ09wKGxvb2tCZWhpbmQoMSkpKSB7XG4gICAgICAgICAgaWYgKGlzVHlwZShsb29rQmVoaW5kKDIpLCBQQVRIX1FVT1RFKSB8fCBpc1R5cGUobG9va0JlaGluZCgyKSwgUEFUSF9CUkFDRSkpIHtcbiAgICAgICAgICAgIG1lcmdlLnVuc2hpZnQoLi4udG9rZW5zLnNwbGljZSgtMiwgMikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpc1R5cGUobG9va0JlaGluZCgyKSwgUEFUSF9QUkVGSVgpKSB7XG4gICAgICAgICAgICBjb25zdCBuID0gaXNUeXBlKGxvb2tCZWhpbmQoMyksIFBBVEhfQlJBQ0UpID8gMyA6IDI7XG4gICAgICAgICAgICBtZXJnZS51bnNoaWZ0KC4uLnRva2Vucy5zcGxpY2UoLW4sIG4pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2FudCB0byBtZXJnZT9cbiAgICAgICAgaWYgKG1lcmdlLmxlbmd0aCkge1xuICAgICAgICAgIHRva2VuID0ge1xuICAgICAgICAgICAgdHlwZTogdG9rZW5UeXBlLFxuICAgICAgICAgICAgdmFsdWU6IG1lcmdlLm1hcChkID0+IGQudmFsdWUpLmpvaW4oJycpICsgdG9rZW5WYWx1ZSxcbiAgICAgICAgICAgIC4uLihlbWl0UmFuZ2VzID8geyByYW5nZTogWyBtZXJnZVswXS5yYW5nZVswXSwgcG9zIF0gfSA6IHt9KVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdG9rZW5zLnB1c2godG9rZW4pO1xuICB9XG5cbiAgcmV0dXJuIHRva2Vucztcbn1cblxuLy8gRm9ybXVsYXMgY2FuIGVpdGhlciBoYXZlIFJDIG9yIEExIHN0eWxlIHJlZnMsIG5vdCBib3RoOiBiZWNhdXNlIEMxIGFuZCBSMSBhcmUgYm90aCFcbi8vIFJlZm1vZGU6IEExIHwgUkMgfCBBbm9zdGljIGVtaXQgcmFuZ2VzIHdpdGggUkFOR0VcbmV4cG9ydCBmdW5jdGlvbiB0b2tlbml6ZSAoZngsIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB0b2tlbkhhbmRsZXJzID0gb3B0aW9ucy5yMWMxID8gdG9rZW5IYW5kbGVyc1JDIDogdG9rZW5IYW5kbGVyc0ExO1xuICByZXR1cm4gZ2V0VG9rZW5zKGZ4LCB0b2tlbkhhbmRsZXJzLCBvcHRpb25zKTtcbn1cbiIsImltcG9ydCB7IEZYX1BSRUZJWCwgUEFUSF9CUkFDRSwgUEFUSF9QUkVGSVgsIFBBVEhfUVVPVEUsIFJBTkdFLCBSQU5HRV9OQU1FRCwgUkFOR0VfQkVBTSB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGdldFRva2VucyB9IGZyb20gJy4vbGV4ZXIuanMnO1xuXG5jb25zdCB1bnF1b3RlID0gZCA9PiBkLnNsaWNlKDEsIC0xKS5yZXBsYWNlKC8nJy9nLCBcIidcIik7XG5cbmNvbnN0IHBSYW5nZU9wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICc6JyAmJiB7fTtcbmNvbnN0IHBSYW5nZSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFJBTkdFICYmIHsgcjA6IHQudmFsdWUgfTtcbmNvbnN0IHBSYW5nZTIgPSB0ID0+IHQgJiYgdC50eXBlID09PSBSQU5HRSAmJiB7IHIxOiB0LnZhbHVlIH07XG5jb25zdCBwQmFuZyA9IHQgPT4gdCAmJiB0LnZhbHVlID09PSAnIScgJiYge307XG5jb25zdCBwQmVhbSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFJBTkdFX0JFQU0gJiYgeyByMDogdC52YWx1ZSB9O1xuY29uc3QgcFNoZWV0ID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUEFUSF9QUkVGSVggJiYgL15bXjpcXFxcLz8qW1xcXV17MCwzMX0kLy50ZXN0KHQudmFsdWUpICYmIHsgc2hlZXROYW1lOiB0LnZhbHVlIH07XG5jb25zdCBwRmlsZSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFBBVEhfQlJBQ0UgJiYgeyB3b3JrYm9va05hbWU6IHQudmFsdWUuc2xpY2UoMSwgLTEpIH07XG5jb25zdCBwRmlsZTIgPSB0ID0+IHQgJiYgdC50eXBlID09PSBQQVRIX1BSRUZJWCAmJiB7IHdvcmtib29rTmFtZTogdC52YWx1ZSB9O1xuY29uc3QgcE5hbWVkID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUkFOR0VfTkFNRUQgJiYgeyBuYW1lOiB0LnZhbHVlIH07XG5cbmNvbnN0IHBRdW90ZWQgPSB0ID0+IHtcbiAgaWYgKHQgJiYgdC50eXBlID09PSBQQVRIX1FVT1RFKSB7XG4gICAgY29uc3QgbSA9IC8oPzpcXFsoLis/KVxcXSk/KFteW1xcXV0rPykkLy5leGVjKHVucXVvdGUodC52YWx1ZSkpO1xuICAgIGlmIChtKSB7XG4gICAgICBjb25zdCBbICwgZmlsZSwgc2hlZXQgXSA9IG07XG4gICAgICBpZiAoIXNoZWV0IHx8IC9eW146XFxcXC8/KltcXF1dezAsMzF9JC8udGVzdChzaGVldCkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB3b3JrYm9va05hbWU6IGZpbGUgfHwgJycsXG4gICAgICAgICAgc2hlZXROYW1lOiBzaGVldCB8fCAnJ1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcbmNvbnN0IHBRdW90ZWQyID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUEFUSF9RVU9URSAmJiB7IHdvcmtib29rTmFtZTogdW5xdW90ZSh0LnZhbHVlKSB9O1xuXG5jb25zdCB2YWxpZFJ1bnMgPSBbXG4gIFsgcFJhbmdlIF0sXG4gIFsgcFJhbmdlLCBwUmFuZ2VPcCwgcFJhbmdlMiBdLFxuICBbIHBCZWFtIF0sXG4gIFsgcFF1b3RlZCwgcEJhbmcsIHBSYW5nZSBdLFxuICBbIHBRdW90ZWQsIHBCYW5nLCBwUmFuZ2UsIHBSYW5nZU9wLCBwUmFuZ2UyIF0sXG4gIFsgcFF1b3RlZCwgcEJhbmcsIHBCZWFtIF0sXG4gIFsgcFNoZWV0LCBwQmFuZywgcFJhbmdlIF0sXG4gIFsgcFNoZWV0LCBwQmFuZywgcFJhbmdlLCBwUmFuZ2VPcCwgcFJhbmdlMiBdLFxuICBbIHBTaGVldCwgcEJhbmcsIHBCZWFtIF0sXG4gIFsgcEZpbGUsIHBTaGVldCwgcEJhbmcsIHBSYW5nZSBdLFxuICBbIHBGaWxlLCBwU2hlZXQsIHBCYW5nLCBwUmFuZ2UsIHBSYW5nZU9wLCBwUmFuZ2UyIF0sXG4gIFsgcEZpbGUsIHBTaGVldCwgcEJhbmcsIHBCZWFtIF1cbl07XG5cbmNvbnN0IHZhbGlkUnVuc05hbWVkID0gdmFsaWRSdW5zLmNvbmNhdChbXG4gIFsgcE5hbWVkIF0sXG4gIFsgcEZpbGUyLCBwQmFuZywgcE5hbWVkIF0sXG4gIFsgcFF1b3RlZDIsIHBCYW5nLCBwTmFtZWQgXVxuXSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJlZiAocmVmLCBhbGxvd19uYW1lZCA9IHRydWUsIHRva2VuSGFuZGxlcnMgPSBbXSkge1xuICBjb25zdCB0b2tlbnMgPSBnZXRUb2tlbnMocmVmLCB0b2tlbkhhbmRsZXJzLCB7XG4gICAgZW1pdFJhbmdlczogZmFsc2UsXG4gICAgbWVyZ2VSYW5nZXM6IGZhbHNlXG4gIH0pO1xuICBjb25zdCByZWZEYXRhID0ge1xuICAgIHNoZWV0TmFtZTogJycsXG4gICAgd29ya2Jvb2tOYW1lOiAnJyxcbiAgICByMDogJycsXG4gICAgcjE6ICcnLFxuICAgIG5hbWU6ICcnXG4gIH07XG4gIC8vIGRpc2NhcmQgdGhlIFwiPVwiLXByZWZpeCBpZiBpdCBpcyB0aGVyZVxuICBpZiAodG9rZW5zLmxlbmd0aCAmJiB0b2tlbnNbMF0udHlwZSA9PT0gRlhfUFJFRklYKSB7XG4gICAgdG9rZW5zLnNoaWZ0KCk7XG4gIH1cbiAgY29uc3QgcnVucyA9IGFsbG93X25hbWVkID8gdmFsaWRSdW5zTmFtZWQgOiB2YWxpZFJ1bnM7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcnVucy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGRhdGEgPSB7IC4uLnJlZkRhdGEgfTtcbiAgICBpZiAocnVuc1tpXS5sZW5ndGggPT09IHRva2Vucy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHZhbGlkID0gcnVuc1tpXS5ldmVyeSgocGFyc2UsIGopID0+IHtcbiAgICAgICAgY29uc3QgZCA9IHBhcnNlKHRva2Vuc1tqXSk7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZGF0YSwgZCk7XG4gICAgICAgIHJldHVybiBkO1xuICAgICAgfSk7XG4gICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuIiwiaW1wb3J0IHsgTUFYX1JPV1MsIE1BWF9DT0xTLCB0b2tlbkhhbmRsZXJzUmVmc0ExIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgcGFyc2VSZWYgfSBmcm9tICcuL3BhcnNlUmVmLmpzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Db2wgKGNvbFN0cikge1xuICBjb25zdCBjID0gKGNvbFN0ciB8fCAnJykudG9VcHBlckNhc2UoKTtcbiAgbGV0IGQgPSAwO1xuICBsZXQgaSA9IDA7XG4gIGZvciAoOyBpICE9PSBjLmxlbmd0aDsgKytpKSB7XG4gICAgY29uc3QgY2hyID0gYy5jaGFyQ29kZUF0KGkpO1xuICAgIGlmIChjaHIgPj0gNjUgJiYgY2hyIDw9IDkwKSB7IC8vIG9taXRzIGFueSBub24gQS1aIGNoYXJhY3RlclxuICAgICAgZCA9IDI2ICogZCArIGNociAtIDY0O1xuICAgIH1cbiAgfVxuICByZXR1cm4gZCAtIDE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0NvbCAobGVmdCkge1xuICBsZXQgbiA9IGxlZnQ7XG4gIGxldCBjID0gJyc7XG4gIHdoaWxlIChuID49IDApIHtcbiAgICBjID0gU3RyaW5nLmZyb21DaGFyQ29kZShuICUgMjYgKyA2NSkgKyBjO1xuICAgIG4gPSBNYXRoLmZsb29yKG4gLyAyNikgLSAxO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvdyAocm93U3RyKSB7XG4gIHJldHVybiArcm93U3RyIC0gMTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUm93ICh0b3ApIHtcbiAgcmV0dXJuIFN0cmluZyh0b3AgKyAxKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUmVsYXRpdmUgKHJhbmdlKSB7XG4gIGNvbnN0IHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0IH0gPSByYW5nZTtcbiAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkbGVmdDogZmFsc2UsICRyaWdodDogZmFsc2UsICR0b3A6IGZhbHNlLCAkYm90dG9tOiBmYWxzZSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9BYnNvbHV0ZSAocmFuZ2UpIHtcbiAgY29uc3QgeyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQgfSA9IHJhbmdlO1xuICByZXR1cm4geyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsICRsZWZ0OiB0cnVlLCAkcmlnaHQ6IHRydWUsICR0b3A6IHRydWUsICRib3R0b206IHRydWUgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvQTEgKHJhbmdlKSB7XG4gIGNvbnN0IHRvQWJzID0gZCA9PiAoZCA/ICckJyA6ICcnKTtcbiAgY29uc3QgeyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsICRsZWZ0LCAkcmlnaHQsICR0b3AsICRib3R0b20gfSA9IHJhbmdlO1xuICAvLyBBOkFcbiAgaWYgKHRvcCA9PT0gMCAmJiBib3R0b20gPT09IE1BWF9ST1dTKSB7XG4gICAgcmV0dXJuIHRvQWJzKCRsZWZ0KSArIHRvQ29sKGxlZnQpICsgJzonICsgdG9BYnMoJHJpZ2h0KSArIHRvQ29sKHJpZ2h0KTtcbiAgfVxuICAvLyAxOjFcbiAgaWYgKGxlZnQgPT09IDAgJiYgcmlnaHQgPT09IE1BWF9DT0xTKSB7XG4gICAgcmV0dXJuIHRvQWJzKCR0b3ApICsgdG9Sb3codG9wKSArICc6JyArIHRvQWJzKCRib3R0b20pICsgdG9Sb3coYm90dG9tKTtcbiAgfVxuICAvLyBBMTpBMVxuICBpZiAocmlnaHQgIT0gbnVsbCAmJiBib3R0b20gIT0gbnVsbCAmJiAocmlnaHQgIT09IGxlZnQgfHwgYm90dG9tICE9PSB0b3ApKSB7XG4gICAgcmV0dXJuIHRvQWJzKCRsZWZ0KSArIHRvQ29sKGxlZnQpICsgdG9BYnMoJHRvcCkgKyB0b1Jvdyh0b3ApICsgJzonICsgdG9BYnMoJHJpZ2h0KSArIHRvQ29sKHJpZ2h0KSArIHRvQWJzKCRib3R0b20pICsgdG9Sb3coYm90dG9tKTtcbiAgfVxuICAvLyBBMVxuICByZXR1cm4gdG9BYnMoJGxlZnQpICsgdG9Db2wobGVmdCkgKyB0b0FicygkdG9wKSArIHRvUm93KHRvcCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tQTEgKHJhbmdlU3RyKSB7XG4gIGxldCBtO1xuICBsZXQgdG9wID0gMDtcbiAgbGV0IGxlZnQgPSAwO1xuICBsZXQgYm90dG9tID0gTUFYX1JPV1M7XG4gIGxldCByaWdodCA9IE1BWF9DT0xTO1xuICBsZXQgJHRvcCA9IGZhbHNlO1xuICBsZXQgJGxlZnQgPSBmYWxzZTtcbiAgbGV0ICRib3R0b20gPSBmYWxzZTtcbiAgbGV0ICRyaWdodCA9IGZhbHNlO1xuICAvLyBBOkFcbiAgaWYgKChtID0gL14oXFwkPykoW0EtWl17MSwzfSk6KFxcJD8pKFtBLVpdezEsM30pJC8uZXhlYyhyYW5nZVN0cikpKSB7XG4gICAgY29uc3QgYSA9IGZyb21Db2wobVsyXSk7XG4gICAgY29uc3QgYiA9IGZyb21Db2wobVs0XSk7XG4gICAgbGVmdCA9IE1hdGgubWluKGEsIGIpO1xuICAgIHJpZ2h0ID0gTWF0aC5tYXgoYSwgYik7XG4gICAgJGxlZnQgPSAhIW1bYSA8PSBiID8gMSA6IDNdO1xuICAgICRyaWdodCA9ICEhbVthIDw9IGIgPyAzIDogMV07XG4gICAgJHRvcCA9IHRydWU7XG4gICAgJGJvdHRvbSA9IHRydWU7XG4gICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gIH1cbiAgLy8gMToxXG4gIGVsc2UgaWYgKChtID0gL14oXFwkPykoWzEtOV1cXGR7MCw2fSk6KFxcJD8pKFsxLTldXFxkezAsNn0pJC8uZXhlYyhyYW5nZVN0cikpKSB7XG4gICAgY29uc3QgYSA9IGZyb21Sb3cobVsyXSk7XG4gICAgY29uc3QgYiA9IGZyb21Sb3cobVs0XSk7XG4gICAgdG9wID0gTWF0aC5taW4oYSwgYik7XG4gICAgYm90dG9tID0gTWF0aC5tYXgoYSwgYik7XG4gICAgJHRvcCA9ICEhbVthIDw9IGIgPyAxIDogM107XG4gICAgJGJvdHRvbSA9ICEhbVthIDw9IGIgPyAzIDogMV07XG4gICAgJGxlZnQgPSB0cnVlO1xuICAgICRyaWdodCA9IHRydWU7XG4gICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gIH1cbiAgLy8gQTEgfCBBMTpCMlxuICBlbHNlIHtcbiAgICBjb25zdCBbIHBhcnQxLCBwYXJ0MiBdID0gcmFuZ2VTdHIuc3BsaXQoJzonKTtcbiAgICBpZiAoKG0gPSAvXihcXCQ/KShbQS1aXXsxLDN9KShcXCQ/KShbMS05XVxcZHswLDZ9KSQvaS5leGVjKHBhcnQxKSkpIHtcbiAgICAgIGxlZnQgPSBmcm9tQ29sKG1bMl0pO1xuICAgICAgdG9wID0gZnJvbVJvdyhtWzRdKTtcbiAgICAgICRsZWZ0ID0gISFtWzFdO1xuICAgICAgJHRvcCA9ICEhbVszXTtcbiAgICAgIGlmIChwYXJ0MiAmJiAobSA9IC9eKFxcJD8pKFtBLVpdezEsM30pKFxcJD8pKFsxLTldXFxkezAsNn0pJC9pLmV4ZWMocGFydDIpKSkge1xuICAgICAgICByaWdodCA9IGZyb21Db2wobVsyXSk7XG4gICAgICAgIGJvdHRvbSA9IGZyb21Sb3cobVs0XSk7XG4gICAgICAgICRyaWdodCA9ICEhbVsxXTtcbiAgICAgICAgJGJvdHRvbSA9ICEhbVszXTtcbiAgICAgICAgLy8gbmVlZCB0byBmbGlwP1xuICAgICAgICBpZiAoYm90dG9tIDwgdG9wKSB7XG4gICAgICAgICAgWyB0b3AsIGJvdHRvbSwgJHRvcCwgJGJvdHRvbSBdID0gWyBib3R0b20sIHRvcCwgJGJvdHRvbSwgJHRvcCBdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaWdodCA8IGxlZnQpIHtcbiAgICAgICAgICBbIGxlZnQsIHJpZ2h0LCAkbGVmdCwgJHJpZ2h0IF0gPSBbIHJpZ2h0LCBsZWZ0LCAkcmlnaHQsICRsZWZ0IF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBib3R0b20gPSB0b3A7XG4gICAgICAgIHJpZ2h0ID0gbGVmdDtcbiAgICAgICAgJGJvdHRvbSA9ICR0b3A7XG4gICAgICAgICRyaWdodCA9ICRsZWZ0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBMVJlZiAocmVmLCBhbGxvd19uYW1lZCA9IHRydWUpIHtcbiAgY29uc3QgZCA9IHBhcnNlUmVmKHJlZiwgYWxsb3dfbmFtZWQsIHRva2VuSGFuZGxlcnNSZWZzQTEpO1xuICBpZiAoZCAmJiAoZC5yMCB8fCBkLm5hbWUpKSB7XG4gICAgbGV0IHJhbmdlID0gbnVsbDtcbiAgICBpZiAoZC5yMCkge1xuICAgICAgcmFuZ2UgPSBkLnIxID8gZnJvbUExKGQucjAgKyAnOicgKyBkLnIxKSA6IGZyb21BMShkLnIwKTtcbiAgICB9XG4gICAgaWYgKGQubmFtZSB8fCByYW5nZSkge1xuICAgICAgZC5yYW5nZSA9IHJhbmdlO1xuICAgICAgZGVsZXRlIGQucjA7XG4gICAgICBkZWxldGUgZC5yMTtcbiAgICAgIHJldHVybiBkO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBmcm9tQ29sLFxuICB0b0NvbCxcbiAgdG9SZWxhdGl2ZSxcbiAgdG9BYnNvbHV0ZSxcbiAgdG86IHRvQTEsXG4gIGZyb206IGZyb21BMSxcbiAgcGFyc2U6IHBhcnNlQTFSZWZcbn07XG4iLCJpbXBvcnQgeyBSQU5HRSwgUkFOR0VfQkVBTSwgVU5LTk9XTiB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHBhcnNlQTFSZWYsIHRvUmVsYXRpdmUsIHRvQTEgfSBmcm9tICcuL2ExLmpzJztcblxuZnVuY3Rpb24gZ2V0SURlciAoKSB7XG4gIGxldCBpID0gMTtcbiAgcmV0dXJuICgpID0+ICdmeGcnICsgKGkrKyk7XG59XG5cbi8vIHdoZW4gY29udGV4dCBpcyBTaGVldDEsIHdlIHNob3VsZCBjb25zaWRlciBTaGVldCFBMSA9PSBBMVxuZXhwb3J0IGZ1bmN0aW9uIGFkZE1ldGEgKHRva2VucywgeyBzaGVldE5hbWUgPSAnJywgd29ya2Jvb2tOYW1lID0gJycgfSA9IHt9KSB7XG4gIGNvbnN0IHBhcmVuU3RhY2sgPSBbXTtcbiAgbGV0IGFycmF5U3RhcnQgPSBudWxsO1xuICBjb25zdCBhMU1hcCA9IHt9O1xuICBjb25zdCB1aWQgPSBnZXRJRGVyKCk7XG5cbiAgdG9rZW5zLmZvckVhY2goKHRva2VuLCBpKSA9PiB7XG4gICAgdG9rZW4uaW5kZXggPSBpO1xuICAgIHRva2VuLmRlcHRoID0gcGFyZW5TdGFjay5sZW5ndGg7XG4gICAgaWYgKHRva2VuLnZhbHVlID09PSAnKCcpIHtcbiAgICAgIHRva2VuLmRlcHRoID0gcGFyZW5TdGFjay5sZW5ndGggKyAxO1xuICAgICAgcGFyZW5TdGFjay5wdXNoKHRva2VuKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udmFsdWUgPT09ICcpJykge1xuICAgICAgY29uc3QgY291bnRlciA9IHBhcmVuU3RhY2sucG9wKCk7XG4gICAgICBpZiAoY291bnRlcikge1xuICAgICAgICBjb25zdCBwYWlySWQgPSB1aWQoKTtcbiAgICAgICAgdG9rZW4uZ3JvdXBJZCA9IHBhaXJJZDtcbiAgICAgICAgdG9rZW4uZGVwdGggPSBjb3VudGVyLmRlcHRoO1xuICAgICAgICBjb3VudGVyLmdyb3VwSWQgPSBwYWlySWQ7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdG9rZW4uZXJyb3IgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh0b2tlbi52YWx1ZSA9PT0gJ3snKSB7XG4gICAgICBpZiAoIWFycmF5U3RhcnQpIHtcbiAgICAgICAgYXJyYXlTdGFydCA9IHRva2VuO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRva2VuLmVycm9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udmFsdWUgPT09ICd9Jykge1xuICAgICAgaWYgKGFycmF5U3RhcnQpIHtcbiAgICAgICAgY29uc3QgcGFpcklkID0gdWlkKCk7XG4gICAgICAgIHRva2VuLmdyb3VwSWQgPSBwYWlySWQ7XG4gICAgICAgIGFycmF5U3RhcnQuZ3JvdXBJZCA9IHBhaXJJZDtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0b2tlbi5lcnJvciA9IHRydWU7XG4gICAgICB9XG4gICAgICBhcnJheVN0YXJ0ID0gbnVsbDtcbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udHlwZSA9PT0gUkFOR0UgfHwgdG9rZW4udHlwZSA9PT0gUkFOR0VfQkVBTSkge1xuICAgICAgY29uc3QgcmVmID0gcGFyc2VBMVJlZih0b2tlbi52YWx1ZSwgZmFsc2UpO1xuICAgICAgY29uc3QgYTEgPSByZWYgJiYgKGBbJHtyZWYud29ya2Jvb2tOYW1lIHx8IHdvcmtib29rTmFtZX1dJHtyZWYuc2hlZXROYW1lIHx8IHNoZWV0TmFtZX0hJHtyZWYucmFuZ2UgPyB0b0ExKHRvUmVsYXRpdmUocmVmLnJhbmdlKSkgOiByZWYubmFtZX1gKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKGExKSB7XG4gICAgICAgIGlmIChhMSBpbiBhMU1hcCkge1xuICAgICAgICAgIHRva2VuLmdyb3VwSWQgPSBhMU1hcFthMV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdG9rZW4uZ3JvdXBJZCA9IHVpZCgpO1xuICAgICAgICAgIGExTWFwW2ExXSA9IHRva2VuLmdyb3VwSWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udHlwZSA9PT0gVU5LTk9XTikge1xuICAgICAgdG9rZW4uZXJyb3IgPSB0cnVlO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiB0b2tlbnM7XG59XG4iLCIvKlxuICBSQyBub3RhdGlvbiB3b3JrcyBkaWZmZXJlbnRseSBmcm9tIEExIGluIHRoYXQgd2UgY2FuJ3QgbWVyZ2Ugc3RhdGljIHJlZmVyZW5jZXMgam9pbmVkIGJ5IGA6YC5cbiAgTWVyZ2luZyBjYW4gb25seSB3b3JrIGJldHdlZW4gcmVmZXJlbmNlcyB0aGF0IGFyZSByZWxhdGl2ZS9hYnNvbHV0ZSBvbiB0aGUgc2FtZSBheGVzLCBzbzpcbiAgUjFDMTpSMkMyIHdpbGwgd29yaywgUlsxXUMxOlJbMl1DMiB3aWxsIGFsc28gd29yaywgYnV0IFJbMV1DWzFdOlIyQzIgY2Fubm90IGJlIHJlcHJlc2VudGVkXG4gIHNpbXBseSBieSBhIHJlY3RhbmdsZSBhcyB3aXRob3V0IGtub3dpbmcgdGhlIGNlbGwgY29udGV4dC5cbiovXG5cbmltcG9ydCB7IE1BWF9ST1dTLCBNQVhfQ09MUywgdG9rZW5IYW5kbGVyc1JlZnNSQyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHBhcnNlUmVmIH0gZnJvbSAnLi9wYXJzZVJlZi5qcyc7XG5cbmZ1bmN0aW9uIHRvQ29vcmQgKHZhbHVlLCBpc0Ficykge1xuICBpZiAoaXNBYnMpIHtcbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlICsgMSk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlID8gJ1snICsgdmFsdWUgKyAnXScgOiAnJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUkMgKHJhbmdlKSB7XG4gIGNvbnN0IHsgcjAsIGMwLCByMSwgYzEsICRjMCwgJGMxLCAkcjAsICRyMSB9ID0gcmFuZ2U7XG4gIC8vIEM6Q1xuICBpZiAocjAgPT09IDAgJiYgcjEgPT09IE1BWF9ST1dTKSB7XG4gICAgY29uc3QgYSA9IHRvQ29vcmQoYzAsICRjMCk7XG4gICAgY29uc3QgYiA9IHRvQ29vcmQoYzEsICRjMSk7XG4gICAgcmV0dXJuICdDJyArIChhID09PSBiID8gYSA6IGEgKyAnOkMnICsgYik7XG4gIH1cbiAgLy8gUjpSXG4gIGlmIChjMCA9PT0gMCAmJiBjMSA9PT0gTUFYX0NPTFMpIHtcbiAgICBjb25zdCBhID0gdG9Db29yZChyMCwgJHIwKTtcbiAgICBjb25zdCBiID0gdG9Db29yZChyMSwgJHIxKTtcbiAgICByZXR1cm4gJ1InICsgKGEgPT09IGIgPyBhIDogYSArICc6UicgKyBiKTtcbiAgfVxuICAvLyBSQzpSQ1xuICBjb25zdCBzX3IwID0gdG9Db29yZChyMCwgJHIwKTtcbiAgY29uc3Qgc19yMSA9IHRvQ29vcmQocjEsICRyMSk7XG4gIGNvbnN0IHNfYzAgPSB0b0Nvb3JkKGMwLCAkYzApO1xuICBjb25zdCBzX2MxID0gdG9Db29yZChjMSwgJGMxKTtcbiAgaWYgKHNfcjAgIT09IHNfcjEgfHwgc19jMCAhPT0gc19jMSkge1xuICAgIHJldHVybiAnUicgKyBzX3IwICsgJ0MnICsgc19jMCArICc6UicgKyBzX3IxICsgJ0MnICsgc19jMTtcbiAgfVxuICAvLyBSQ1xuICByZXR1cm4gJ1InICsgc19yMCArICdDJyArIHNfYzA7XG59XG5cbmZ1bmN0aW9uIHBhcnNlUkNQYXJ0IChyZWYpIHtcbiAgbGV0IHIwID0gMDtcbiAgbGV0IGMwID0gMDtcbiAgbGV0IHIxID0gTUFYX1JPV1M7XG4gIGxldCBjMSA9IE1BWF9DT0xTO1xuICBsZXQgJHIwID0gZmFsc2U7XG4gIGxldCAkYzAgPSBmYWxzZTtcbiAgbGV0ICRyMSA9IGZhbHNlO1xuICBsZXQgJGMxID0gZmFsc2U7XG4gIC8vIFIgcGFydFxuICBjb25zdCBybSA9IC9eUig/OlxcWyhbKy1dP1xcZCspXFxdfChcXGQrKSk/Ly5leGVjKHJlZik7XG4gIGlmIChybSkge1xuICAgIGlmIChybVsxXSkge1xuICAgICAgcjAgPSBwYXJzZUludChybVsxXSwgMTApO1xuICAgIH1cbiAgICBlbHNlIGlmIChybVsyXSkge1xuICAgICAgcjAgPSBwYXJzZUludChybVsyXSwgMTApIC0gMTtcbiAgICAgICRyMCA9IHRydWU7XG4gICAgfVxuICAgIHIxID0gcjA7XG4gICAgJHIxID0gJHIwO1xuICAgIHJlZiA9IHJlZi5zbGljZShybVswXS5sZW5ndGgpO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIHIwID0gMCwgcjEgPSBNQVhfUk9XU1xuICAgICRyMCA9IHRydWU7XG4gICAgJHIxID0gdHJ1ZTtcbiAgfVxuICAvLyBDIHBhcnRcbiAgY29uc3QgY20gPSAvXkMoPzpcXFsoWystXT9cXGQrKVxcXXwoXFxkKykpPy8uZXhlYyhyZWYpO1xuICBpZiAoY20pIHtcbiAgICBpZiAoY21bMV0pIHtcbiAgICAgIGMwID0gcGFyc2VJbnQoY21bMV0sIDEwKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoY21bMl0pIHtcbiAgICAgIGMwID0gcGFyc2VJbnQoY21bMl0sIDEwKSAtIDE7XG4gICAgICAkYzAgPSB0cnVlO1xuICAgIH1cbiAgICBjMSA9IGMwO1xuICAgICRjMSA9ICRjMDtcbiAgICByZWYgPSByZWYuc2xpY2UoY21bMF0ubGVuZ3RoKTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBjMCA9IDAsIGMxID0gTUFYX0NPTFNcbiAgICAkYzAgPSB0cnVlO1xuICAgICRjMSA9IHRydWU7XG4gIH1cbiAgLy8gbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBwYXJ0IChhbmQgbm90aGluZyBtb3JlKVxuICBpZiAoKCFybSAmJiAhY20pIHx8IHJlZi5sZW5ndGgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4geyByMCwgYzAsIHIxLCBjMSwgJHIwLCAkYzAsICRyMSwgJGMxIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUkMgKHJlZikge1xuICBjb25zdCBbIHBhcnQxLCBwYXJ0MiBdID0gcmVmLnNwbGl0KCc6JywgMik7XG4gIGNvbnN0IHJhbmdlID0gcGFyc2VSQ1BhcnQocGFydDEpO1xuICBpZiAoIXJhbmdlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKHJhbmdlICYmIHBhcnQyKSB7XG4gICAgY29uc3QgZXh0ZW5kVG8gPSBwYXJzZVJDUGFydChwYXJ0Mik7XG4gICAgaWYgKGV4dGVuZFRvKSB7XG4gICAgICAvLyBOb3RlOiBSWy0xXUNbLTFdOlIxQzEgaXMgb25seSBtZWFuaW5nZnVsIG9uY2Ugd2UgaGF2ZSBhbiBhbmNob3JcbiAgICAgIHJhbmdlLnIxID0gZXh0ZW5kVG8ucjE7XG4gICAgICByYW5nZS5jMSA9IGV4dGVuZFRvLmMxO1xuICAgICAgcmFuZ2UuJHIxID0gZXh0ZW5kVG8uJHIxO1xuICAgICAgcmFuZ2UuJGMxID0gZXh0ZW5kVG8uJGMxO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmFuZ2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJDUmVmIChyZWYsIGFsbG93X25hbWVkID0gdHJ1ZSkge1xuICBjb25zdCBkID0gcGFyc2VSZWYocmVmLCBhbGxvd19uYW1lZCwgdG9rZW5IYW5kbGVyc1JlZnNSQyk7XG4gIGlmIChkICYmIChkLnIwIHx8IGQubmFtZSkpIHtcbiAgICBjb25zdCByYW5nZSA9IGQucjEgPyBmcm9tUkMoZC5yMCArICc6JyArIGQucjEpIDogZnJvbVJDKGQucjApO1xuICAgIGlmIChkLm5hbWUgfHwgcmFuZ2UpIHtcbiAgICAgIGQucmFuZ2UgPSByYW5nZTtcbiAgICAgIGRlbGV0ZSBkLnIwO1xuICAgICAgZGVsZXRlIGQucjE7XG4gICAgICByZXR1cm4gZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgdG86IHRvUkMsXG4gIGZyb206IGZyb21SQyxcbiAgcGFyc2U6IHBhcnNlUkNSZWZcbn07XG4iLCJpbXBvcnQgeyBSQU5HRSwgUkFOR0VfQkVBTSwgTUFYX1JPV1MsIE1BWF9DT0xTIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgZnJvbUExLCB0b0ExIH0gZnJvbSAnLi9hMS5qcyc7XG5pbXBvcnQgeyBmcm9tUkMsIHRvUkMgfSBmcm9tICcuL3JjLmpzJztcbmltcG9ydCB7IHRva2VuaXplIH0gZnJvbSAnLi9sZXhlci5qcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGVUb1JDIChmeCwgYW5jaG9yQ2VsbCkge1xuICBjb25zdCB7IHRvcCwgbGVmdCB9ID0gZnJvbUExKGFuY2hvckNlbGwpO1xuICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBmeCA9PT0gJ3N0cmluZyc7XG5cbiAgY29uc3QgdG9rZW5zID0gaXNTdHJpbmdcbiAgICA/IHRva2VuaXplKGZ4LCB7IGVtaXRSYW5nZXM6IGZhbHNlLCBtZXJnZVJhbmdlczogZmFsc2UsIHIxYzI6IGZhbHNlIH0pXG4gICAgOiBmeDtcblxuICB0b2tlbnMuZm9yRWFjaCh0b2tlbiA9PiB7XG4gICAgaWYgKHRva2VuLnR5cGUgPT09IFJBTkdFKSB7XG4gICAgICBjb25zdCByYW5nZSA9IHt9O1xuICAgICAgY29uc3QgZCA9IGZyb21BMSh0b2tlbi52YWx1ZSk7XG5cbiAgICAgIHJhbmdlLnIwID0gZC4kdG9wID8gZC50b3AgOiBkLnRvcCAtIHRvcDtcbiAgICAgIHJhbmdlLiRyMCA9IGQuJHRvcDtcbiAgICAgIHJhbmdlLnIxID0gZC4kYm90dG9tID8gZC5ib3R0b20gOiBkLmJvdHRvbSAtIHRvcDtcbiAgICAgIHJhbmdlLiRyMSA9IGQuJGJvdHRvbTtcblxuICAgICAgcmFuZ2UuYzAgPSBkLiRsZWZ0ID8gZC5sZWZ0IDogZC5sZWZ0IC0gbGVmdDtcbiAgICAgIHJhbmdlLiRjMCA9IGQuJGxlZnQ7XG4gICAgICByYW5nZS5jMSA9IGQuJHJpZ2h0ID8gZC5yaWdodCA6IGQucmlnaHQgLSBsZWZ0O1xuICAgICAgcmFuZ2UuJGMxID0gZC4kcmlnaHQ7XG5cbiAgICAgIC8vIGNvbnNvbGUuZXJyb3IodG9rZW4udmFsdWUsIGQsIHJhbmdlLCBbIHRvcCwgbGVmdCBdKTtcbiAgICAgIHRva2VuLnZhbHVlID0gdG9SQyhyYW5nZSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRva2VuLnR5cGUgPT09IFJBTkdFX0JFQU0pIHtcbiAgICAgIGNvbnN0IHJhbmdlID0ge307XG4gICAgICBjb25zdCBkID0gZnJvbUExKHRva2VuLnZhbHVlKTtcblxuICAgICAgcmFuZ2UucjAgPSBkLiR0b3AgPyBkLnRvcCA6IGQudG9wIC0gdG9wO1xuICAgICAgcmFuZ2UuJHIwID0gZC4kdG9wO1xuICAgICAgcmFuZ2UucjEgPSBkLiRib3R0b20gPyBkLmJvdHRvbSA6IGQuYm90dG9tIC0gdG9wO1xuICAgICAgcmFuZ2UuJHIxID0gZC4kYm90dG9tO1xuXG4gICAgICByYW5nZS5jMCA9IGQuJGxlZnQgPyBkLmxlZnQgOiBkLmxlZnQgLSBsZWZ0O1xuICAgICAgcmFuZ2UuJGMwID0gZC4kbGVmdDtcbiAgICAgIHJhbmdlLmMxID0gZC4kcmlnaHQgPyBkLnJpZ2h0IDogZC5yaWdodCAtIGxlZnQ7XG4gICAgICByYW5nZS4kYzEgPSBkLiRyaWdodDtcblxuICAgICAgdG9rZW4udmFsdWUgPSB0b1JDKHJhbmdlKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBpc1N0cmluZ1xuICAgID8gdG9rZW5zLm1hcChkID0+IGQudmFsdWUpLmpvaW4oJycpXG4gICAgOiB0b2tlbnM7XG59XG5cbmZ1bmN0aW9uIHRvRml4ZWQgKHZhbCwgYWJzLCBiYXNlLCBtYXgpIHtcbiAgbGV0IHYgPSB2YWw7XG4gIGlmICghYWJzKSB7XG4gICAgdiA9IGJhc2UgKyB2YWw7XG4gICAgLy8gRXhjZWwgXCJ3cmFwcyBhcm91bmRcIiB3aGVuIHZhbHVlIGdvZXMgb3V0IG9mIGxvd2VyIGJvdW5kcy5cbiAgICAvLyBJdCdzIGEgYml0IHF1aXJreSBvbiBlbnRyeSBhcyBFeGNlbCB3YW50cyB0byByZS1yZXdpdGUgdGhlXG4gICAgLy8gcmVmZXJlbmNlcyBidXQgYmVoYXZpb3VyIGlzIGNvbnNpc3RlbnQgd2l0aCBJTkRJUkVDVDpcbiAgICAvLyAuLi4gSW4gQTE6IFJDWy0xXSA9PiBSMUNbMTYzODNdLlxuICAgIGlmICh2IDwgMCkge1xuICAgICAgdiA9IG1heCArIHYgKyAxO1xuICAgIH1cbiAgICAvLyAuLi4gSW4gQjE6ID1SQ1sxNjM4M10gPT4gPVJDWy0xXVxuICAgIGlmICh2ID4gbWF4KSB7XG4gICAgICB2IC09IG1heCArIDE7XG4gICAgfVxuICB9XG4gIHJldHVybiB2O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNsYXRlVG9BMSAoZngsIGFuY2hvckNlbGwpIHtcbiAgY29uc3QgYW5jaG9yID0gZnJvbUExKGFuY2hvckNlbGwpO1xuICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBmeCA9PT0gJ3N0cmluZyc7XG5cbiAgY29uc3QgdG9rZW5zID0gaXNTdHJpbmdcbiAgICA/IHRva2VuaXplKGZ4LCB7IGVtaXRSYW5nZXM6IGZhbHNlLCBtZXJnZVJhbmdlczogZmFsc2UsIHIxYzE6IHRydWUgfSlcbiAgICA6IGZ4O1xuXG4gIHRva2Vucy5mb3JFYWNoKHRva2VuID0+IHtcbiAgICBpZiAodG9rZW4udHlwZSA9PT0gUkFOR0UgfHwgdG9rZW4udHlwZSA9PT0gUkFOR0VfQkVBTSkge1xuICAgICAgY29uc3QgcmFuZ2UgPSB7fTtcbiAgICAgIGNvbnN0IGQgPSBmcm9tUkModG9rZW4udmFsdWUpO1xuICAgICAgY29uc3QgcjAgPSB0b0ZpeGVkKGQucjAsIGQuJHIwLCBhbmNob3IudG9wLCBNQVhfUk9XUyk7XG4gICAgICBjb25zdCByMSA9IHRvRml4ZWQoZC5yMSwgZC4kcjEsIGFuY2hvci50b3AsIE1BWF9ST1dTKTtcbiAgICAgIGlmIChyMCA+IHIxKSB7XG4gICAgICAgIHJhbmdlLnRvcCA9IHIxO1xuICAgICAgICByYW5nZS4kdG9wID0gZC4kcjE7XG4gICAgICAgIHJhbmdlLmJvdHRvbSA9IHIwO1xuICAgICAgICByYW5nZS4kYm90dG9tID0gZC4kcjA7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmFuZ2UudG9wID0gcjA7XG4gICAgICAgIHJhbmdlLiR0b3AgPSBkLiRyMDtcbiAgICAgICAgcmFuZ2UuYm90dG9tID0gcjE7XG4gICAgICAgIHJhbmdlLiRib3R0b20gPSBkLiRyMTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGMwID0gdG9GaXhlZChkLmMwLCBkLiRjMCwgYW5jaG9yLmxlZnQsIE1BWF9DT0xTKTtcbiAgICAgIGNvbnN0IGMxID0gdG9GaXhlZChkLmMxLCBkLiRjMSwgYW5jaG9yLmxlZnQsIE1BWF9DT0xTKTtcbiAgICAgIGlmIChjMCA+IGMxKSB7XG4gICAgICAgIHJhbmdlLmxlZnQgPSBjMTtcbiAgICAgICAgcmFuZ2UuJGxlZnQgPSBkLiRjMTtcbiAgICAgICAgcmFuZ2UucmlnaHQgPSBjMDtcbiAgICAgICAgcmFuZ2UuJHJpZ2h0ID0gZC4kYzA7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmFuZ2UubGVmdCA9IGMwO1xuICAgICAgICByYW5nZS4kbGVmdCA9IGQuJGMwO1xuICAgICAgICByYW5nZS5yaWdodCA9IGMxO1xuICAgICAgICByYW5nZS4kcmlnaHQgPSBkLiRjMTtcbiAgICAgIH1cbiAgICAgIHRva2VuLnZhbHVlID0gdG9BMShyYW5nZSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gaXNTdHJpbmdcbiAgICA/IHRva2Vucy5tYXAoZCA9PiBkLnZhbHVlKS5qb2luKCcnKVxuICAgIDogdG9rZW5zO1xufVxuIiwiZXhwb3J0IHsgdG9rZW5pemUgfSBmcm9tICcuL2xleGVyLmpzJztcbmV4cG9ydCB7IGFkZE1ldGEgfSBmcm9tICcuL2FkZE1ldGEuanMnO1xuZXhwb3J0IHsgdHJhbnNsYXRlVG9SQywgdHJhbnNsYXRlVG9BMSB9IGZyb20gJy4vdHJhbnNsYXRlLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgYTEgfSBmcm9tICcuL2ExLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgcmMgfSBmcm9tICcuL3JjLmpzJztcbmV4cG9ydCB7IE1BWF9DT0xTLCBNQVhfUk9XUyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcblxuaW1wb3J0IHtcbiAgT1BFUkFUT1IsXG4gIEJPT0xFQU4sXG4gIEVSUk9SLFxuICBOVU1CRVIsXG4gIEZVTkNUSU9OLFxuICBORVdMSU5FLFxuICBXSElURVNQQUNFLFxuICBTVFJJTkcsXG4gIFBBVEhfUVVPVEUsXG4gIFBBVEhfQlJBQ0UsXG4gIFBBVEhfUFJFRklYLFxuICBSQU5HRSxcbiAgUkFOR0VfQkVBTSxcbiAgUkFOR0VfTkFNRUQsXG4gIEZYX1BSRUZJWCxcbiAgVU5LTk9XTlxufSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5cbmV4cG9ydCBjb25zdCB0b2tlblR5cGVzID0ge1xuICBPUEVSQVRPUixcbiAgQk9PTEVBTixcbiAgRVJST1IsXG4gIE5VTUJFUixcbiAgRlVOQ1RJT04sXG4gIE5FV0xJTkUsXG4gIFdISVRFU1BBQ0UsXG4gIFNUUklORyxcbiAgUEFUSF9RVU9URSxcbiAgUEFUSF9CUkFDRSxcbiAgUEFUSF9QUkVGSVgsXG4gIFJBTkdFLFxuICBSQU5HRV9CRUFNLFxuICBSQU5HRV9OQU1FRCxcbiAgRlhfUFJFRklYLFxuICBVTktOT1dOXG59O1xuIl0sIm5hbWVzIjpbInF1aWNrVmVyaWZ5UmFuZ2VBMSIsInRva2VuVmFsdWUiLCJzcGxpdCIsImV2ZXJ5IiwiZCIsIm4iLCJwYXJzZUludCIsImlzTmFOIiwiaXNGaW5pdGUiLCJib3VuZHMiLCJSIiwiQyIsInF1aWNrVmVyaWZ5UmFuZ2VSQyIsInJlTnVtcyIsIm0iLCJleGVjIiwieCIsInZhbCIsIlJBTkdFIiwiUkFOR0VfQkVBTSIsInJlX0VSUk9SIiwicmVfT1BFUkFUT1IiLCJyZV9CT09MRUFOIiwicmVfRlVOQ1RJT04iLCJyZV9ORVdMSU5FIiwicmVfV0hJVEVTUEFDRSIsInJlX1NUUklORyIsInJlX1BBVEhfUVVPVEUiLCJyZV9QQVRIX0JSQUNFIiwicmVfUEFUSF9QUkVGSVgiLCJyZV9BMUNPTCIsInJlX0ExUk9XIiwicmVfQTFSQU5HRSIsInJQYXJ0IiwiY1BhcnQiLCJyZV9SQ0NPTCIsIlJlZ0V4cCIsImNvbmNhdCIsInJlX1JDUk9XIiwicmVfUkNSQU5HRSIsInJlX05VTUJFUiIsInJlX05BTUVEIiwidG9rZW5IYW5kbGVyc0ExIiwidG9rZW5IYW5kbGVyc1JDIiwidG9rZW5IYW5kbGVyc1JlZnNBMSIsInRva2VuSGFuZGxlcnNSZWZzUkMiLCJpc1R5cGUiLCJ0IiwidHlwZSIsImlzUmFuZ2VPcCIsInZhbHVlIiwiaXNCYW5nT3AiLCJkZWZhdWx0T3B0aW9ucyIsImVtaXRSYW5nZXMiLCJtZXJnZVJhbmdlcyIsIm5lZ2F0aXZlTnVtYmVycyIsInIxYzEiLCJnZXRUb2tlbnMiLCJmeCIsInRva2VuSGFuZGxlcnMiLCJvcHRpb25zIiwiT2JqZWN0IiwiYXNzaWduIiwidG9rZW5zIiwicG9zIiwibG9va0JlaGluZCIsImxlbmd0aCIsImxvb2tCZWhpbmRJZ25vcmVXUyIsIm5vV3MiLCJmaWx0ZXIiLCJ0ZXN0IiwidG9rZW4iLCJyYW5nZSIsInB1c2giLCJzdGFydFBvcyIsInMiLCJzbGljZSIsInRva2VuVHlwZSIsImkiLCJyZVRlc3QiLCJmblRlc3QiLCJlbmRzV2l0aCIsInVudGVybWluYXRlZCIsImxhc3QxIiwibGFzdDIiLCJpbmNsdWRlcyIsInBvcCIsIm1lcmdlIiwidW5zaGlmdCIsInNwbGljZSIsIm1hcCIsImpvaW4iLCJ0b2tlbml6ZSIsInVucXVvdGUiLCJyZXBsYWNlIiwicFJhbmdlT3AiLCJwUmFuZ2UiLCJyMCIsInBSYW5nZTIiLCJyMSIsInBCYW5nIiwicEJlYW0iLCJwU2hlZXQiLCJzaGVldE5hbWUiLCJwRmlsZSIsIndvcmtib29rTmFtZSIsInBOYW1lZCIsIm5hbWUiLCJwUXVvdGVkIiwiZmlsZSIsInNoZWV0IiwidmFsaWRSdW5zIiwidmFsaWRSdW5zTmFtZWQiLCJwYXJzZVJlZiIsInJlZiIsImFsbG93X25hbWVkIiwicmVmRGF0YSIsInNoaWZ0IiwicnVucyIsImRhdGEiLCJwYXJzZSIsImoiLCJmcm9tQ29sIiwiY29sU3RyIiwiYyIsInRvVXBwZXJDYXNlIiwiY2hyIiwiY2hhckNvZGVBdCIsInRvQ29sIiwibGVmdCIsIlN0cmluZyIsImZyb21DaGFyQ29kZSIsIk1hdGgiLCJmbG9vciIsImZyb21Sb3ciLCJyb3dTdHIiLCJ0b1JvdyIsInRvcCIsInRvUmVsYXRpdmUiLCJib3R0b20iLCJyaWdodCIsIiRsZWZ0IiwiJHJpZ2h0IiwiJHRvcCIsIiRib3R0b20iLCJ0b0ExIiwidG9BYnMiLCJmcm9tQTEiLCJyYW5nZVN0ciIsImEiLCJiIiwibWluIiwibWF4IiwicGFydDEiLCJwYXJ0MiIsInBhcnNlQTFSZWYiLCJhMSIsInRvQWJzb2x1dGUiLCJ0byIsImZyb20iLCJnZXRJRGVyIiwidG9Db29yZCIsImlzQWJzIiwidG9SQyIsImMwIiwiYzEiLCIkYzAiLCIkYzEiLCIkcjAiLCIkcjEiLCJzX3IwIiwic19yMSIsInNfYzAiLCJzX2MxIiwicGFyc2VSQ1BhcnQiLCJybSIsImNtIiwiZnJvbVJDIiwiZXh0ZW5kVG8iLCJyYyIsInRvRml4ZWQiLCJhYnMiLCJiYXNlIiwidiIsInRva2VuVHlwZXMiLCJPUEVSQVRPUiIsIkJPT0xFQU4iLCJFUlJPUiIsIk5VTUJFUiIsIkZVTkNUSU9OIiwiTkVXTElORSIsIldISVRFU1BBQ0UiLCJTVFJJTkciLCJQQVRIX1FVT1RFIiwiUEFUSF9CUkFDRSIsIlBBVEhfUFJFRklYIiwiUkFOR0VfTkFNRUQiLCJGWF9QUkVGSVgiLCJVTktOT1dOIiwicGFyZW5TdGFjayIsImFycmF5U3RhcnQiLCJhMU1hcCIsInVpZCIsImZvckVhY2giLCJpbmRleCIsImRlcHRoIiwiY291bnRlciIsInBhaXJJZCIsImdyb3VwSWQiLCJlcnJvciIsInRvTG93ZXJDYXNlIiwiYW5jaG9yQ2VsbCIsImFuY2hvciIsImlzU3RyaW5nIiwicjFjMiJdLCJtYXBwaW5ncyI6ImFBQU8sU0FBU0EsRUFBb0JDLEdBTWxDLE9BQU9BLEVBQVdDLE1BQU0sbUJBQW1CQyxPQUFNQyxJQUMvQyxNQUFNQyxFQUFJQyxTQUFTRixFQUFHLElBQ3RCLFFBQUtHLE1BQU1GLEtBQ0ZHLFNBQVNKLEdBQ1pDLEdBQUssV0FDTEEsR0FBSyxNQUVYLEdBRUgsd0RBRUQsTUFBTUksRUFBUyxDQUNiQyxFQUFLLFFBQ0wsS0FBTSxRQUNOQyxFQUFLLE1BQ0wsS0FBTSxPQUVELFNBQVNDLEVBQW9CWCxHQUNsQyxNQUFNWSxFQUFTLHFCQUNmLElBQUlDLEVBQ0osS0FBeUMsUUFBakNBLEVBQUlELEVBQU9FLEtBQUtkLEtBQXVCLENBQzdDLE1BQU1lLEVBQUlQLEVBQU9LLEVBQUUsSUFDYkcsRUFBTVgsU0FBU1EsRUFBRSxHQUFJLElBQzNCLEdBQUlHLEdBQU9ELEdBQUtDLElBQVFELEVBQ3RCLE9BQU8sQ0FFVixDQUNELE9BQU8sQ0FDUixDQ2hDTSxNQVdNRSxFQUFRLFFBQ1JDLEVBQWEsYUFRcEJDLEVBQVcsNkhBQ1hDLEVBQWMsK0NBQ2RDLEVBQWEsbUJBQ2JDLEVBQWMsK0JBQ2RDLEVBQWEsT0FDYkMsRUFBZ0IsNkVBQ2hCQyxFQUFZLHNCQUNaQyxFQUFnQixzQkFDaEJDLEVBQWdCLHNCQUNoQkMsRUFBaUIsNkNBQ2pCQyxFQUFXLGdDQUNYQyxFQUFXLDBDQUNYQyxFQUFhLG9DQUNiQyxFQUFRLDRDQUNSQyxFQUFRLDRDQUNSQyxFQUFXLElBQUlDLE9BQUosSUFBQUMsT0FBZUgsRUFBVUEsTUFBQUEsT0FBQUEsRUFBb0IsZUFBQSxLQUN4REksRUFBVyxJQUFJRixPQUFKLElBQUFDLE9BQWVKLEVBQVVBLE1BQUFBLE9BQUFBLEVBQW9CLGVBQUEsS0FDeERNLEVBQWEsSUFBSUgsT0FBSixlQUFBQyxPQUEwQkosR0FBUUMsT0FBQUEsRUFBVSxLQUFBLEtBQ3pETSxFQUFZLHdDQUNaQyxFQUFXLGtCQUdKQyxFQUFrQixDQUM3QixDQXpDbUIsUUF5Q0p0QixHQUNmLENBNUNzQixXQTRDUEMsR0FDZixDQTVDcUIsT0E0Q05DLEdBQ2YsQ0ExQ3NCLFdBMENQQyxHQUNmLENBMUNxQixVQTBDTkMsR0FDZixDQTFDd0IsYUEwQ1RDLEdBQ2YsQ0ExQ29CLFNBMENMQyxHQUNmLENBMUN3QixhQTBDVEMsR0FDZixDQTFDd0IsYUEwQ1RDLEdBQ2YsQ0ExQ3lCLGNBMENWQyxHQUNmLENBQUVYLEVBQWFjLEVBQVloQyxHQUMzQixDQUFFbUIsRUFBYVcsRUFBVTlCLEdBQ3pCLENBQUVtQixFQUFhWSxFQUFVL0IsR0FDekIsQ0FyRG9CLFNBcURMd0MsR0FDZixDQTVDeUIsY0E0Q1ZDLElBR0pFLEVBQWtCLENBQzdCLENBM0RtQixRQTJESnZCLEdBQ2YsQ0E5RHNCLFdBOERQQyxHQUNmLENBOURxQixPQThETkMsR0FDZixDQTVEc0IsV0E0RFBDLEdBQ2YsQ0E1RHFCLFVBNEROQyxHQUNmLENBNUR3QixhQTREVEMsR0FDZixDQTVEb0IsU0E0RExDLEdBQ2YsQ0E1RHdCLGFBNERUQyxHQUNmLENBNUR3QixhQTREVEMsR0FDZixDQTVEeUIsY0E0RFZDLEdBQ2YsQ0FBRVgsRUFBYXFCLEVBQVkzQixHQUMzQixDQUFFTyxFQUFhbUIsRUFBVTFCLEdBQ3pCLENBQUVPLEVBQWFnQixFQUFVdkIsR0FDekIsQ0F2RW9CLFNBdUVMNEIsR0FDZixDQTlEeUIsY0E4RFZDLElBR0pHLEVBQXNCLENBQ2pDLENBL0VzQixXQStFUCxTQUNmLENBeEV3QixhQXdFVGpCLEdBQ2YsQ0F4RXdCLGFBd0VUQyxHQUNmLENBeEV5QixjQXdFVkMsR0FDZixDQUFFWCxFQUFhYyxFQUFZaEMsR0FDM0IsQ0FBRW1CLEVBQWFXLEVBQVU5QixHQUN6QixDQUFFbUIsRUFBYVksRUFBVS9CLEdBQ3pCLENBekV5QixjQXlFVnlDLElBR0pJLEVBQXNCLENBQ2pDLENBMUZzQixXQTBGUCxNQUNmLENBbkZ3QixhQW1GVGxCLEdBQ2YsQ0FuRndCLGFBbUZUQyxHQUNmLENBbkZ5QixjQW1GVkMsR0FDZixDQUFFWCxFQUFhcUIsRUFBWTNCLEdBQzNCLENBQUVPLEVBQWFtQixFQUFVMUIsR0FDekIsQ0FBRU8sRUFBYWdCLEVBQVV2QixHQUN6QixDQXBGeUIsY0FvRlY2QixJQ2pGWEssRUFBUyxDQUFDQyxFQUFHQyxJQUFTRCxHQUFLQSxFQUFFQyxPQUFTQSxFQUN0Q0MsRUFBWUYsR0FBS0EsR0FBaUIsTUFBWkEsRUFBRUcsTUFDeEJDLEVBQVdKLEdBQUtBLEdBQWlCLE1BQVpBLEVBQUVHLE1BRXZCRSxFQUFpQixDQUNyQkMsWUFBWSxFQUNaQyxhQUFhLEVBQ2JDLGlCQUFpQixFQUNqQkMsTUFBTSxHQUdELFNBQVNDLEVBQVdDLEVBQUlDLEdBQTZCLElBQWRDLHlEQUFVLENBQUEsRUFDdEQsTUFBTVAsV0FBRUEsRUFBRkMsWUFBY0EsRUFBZEMsZ0JBQTJCQSxHQUFvQk0sT0FBT0MsT0FBTyxDQUFkLEVBQWtCVixFQUFnQlEsR0FDakZHLEVBQVMsR0FDZixJQUFJQyxFQUFNLEVBQ1YsTUFBTUMsRUFBYTVELEdBQUswRCxFQUFPQSxFQUFPRyxPQUFTN0QsR0FDekM4RCxFQUFxQjlELElBQ3pCLE1BQU0rRCxFQUFPTCxFQUFPTSxRQUFPdEIsSUFBTUQsRUFBT0MsRUQzQmxCLGdCQzJCcUNELEVBQU9DLEVENUIvQyxhQzZCbkIsT0FBT3FCLEVBQUtBLEVBQUtGLE9BQVM3RCxFQUExQixFQUdGLEdBQUksS0FBS2lFLEtBQUtaLEdBQUssQ0FDakIsTUFBTWEsRUFBUSxDQUNadkIsS0R6Qm1CLFlDMEJuQkUsTUFBTyxPQUNIRyxFQUFhLENBQUVtQixNQUFPLENBQUUsRUFBRyxJQUFRLElBRXpDUixJQUNBRCxFQUFPVSxLQUFLRixFQUNiLENBRUQsS0FBT1AsRUFBTU4sRUFBR1EsUUFBUSxDQUN0QixNQUFNUSxFQUFXVixFQUNYVyxFQUFJakIsRUFBR2tCLE1BQU1aLEdBQ25CLElBQUlhLEVBQVksR0FDWjVFLEVBQWEsR0FDakIsSUFBSyxJQUFJNkUsRUFBSSxFQUFHQSxFQUFJbkIsRUFBY08sT0FBUVksSUFBSyxDQUM3QyxNQUFROUIsRUFBTStCLEVBQVFDLEdBQVdyQixFQUFjbUIsR0FDekNoRSxFQUFJaUUsRUFBT2hFLEtBQUs0RCxHQUN0QixHQUFJN0QsS0FBT2tFLEdBQVVBLEVBQU9sRSxFQUFFLEtBQU0sQ0FDbEMrRCxFQUFZN0IsRUFDWi9DLEVBQWFhLEVBQUUsR0FDZmtELEdBQU9sRCxFQUFFLEdBQUdvRCxPQUNaLEtBQ0QsQ0FDRixDQUVJVyxJQUNIQSxFRGpEaUIsVUNrRGpCNUUsRUFBYXlELEVBQUdNLEdBQ2hCQSxLQUdGLElBQUlPLEVBQVEsQ0FDVnZCLEtBQU02QixFQUNOM0IsTUFBT2pELEtBQ0hvRCxFQUFhLENBQUVtQixNQUFPLENBQUVFLEVBQVVWLElBQVUsSUFPbEQsR0R4RWtCLFdDb0VkYSxHQUF5QjVFLEVBQVdnRixTQUFTLE9BQy9DVixFQUFNVyxjQUFlLEdBR25CM0IsR0Q1RWMsV0M0RUtzQixFQUFzQixDQUMzQyxNQUFNTSxFQUFRbEIsRUFBVyxHQUN6QixHQUFJa0IsR0FBU3JDLEVBQU9xQyxFRGpGRixhQ2lGc0MsTUFBaEJBLEVBQU1qQyxNQUFlLENBRTNELE1BQU1rQyxFQUFRakIsRUFBbUIsS0FFNUJpQixHQUFTdEMsRUFBT3NDLEVEdkVKLGNDdUUwQnRDLEVBQU9zQyxFRHJGbEMsY0NxRnVELENBQUUsSUFBSyxJQUFLLElBQUssS0FBTUMsU0FBU0QsRUFBTWxDLFVBQzNHYSxFQUFPdUIsTUFDUGYsRUFBTXJCLE1BQVEsSUFBTWpELEVBRXZCLENBQ0YsQ0FFRCxHQUFJcUQsSUFDRXVCLElBQWMzRCxHRGhGRyxnQkNnRk0yRCxHQUE2QkEsSUFBYzFELEdBQVksQ0FDaEYsTUFBTW9FLEVBQVEsR0FPZCxHQUxJdEMsRUFBVWdCLEVBQVcsS0FBT25CLEVBQU9tQixFQUFXLEdBQUkvQyxJQUFVMkQsSUFBYzNELEdBRTVFcUUsRUFBTUMsV0FBV3pCLEVBQU8wQixRQUFRLEVBQUcsSUFHakN0QyxFQUFTYyxFQUFXLElBQ3RCLEdBQUluQixFQUFPbUIsRUFBVyxHRDlGTixlQzhGeUJuQixFQUFPbUIsRUFBVyxHRDdGM0MsY0M4RmRzQixFQUFNQyxXQUFXekIsRUFBTzBCLFFBQVEsRUFBRyxTQUVoQyxHQUFJM0MsRUFBT21CLEVBQVcsR0QvRlYsZUMrRjRCLENBQzNDLE1BQU01RCxFQUFJeUMsRUFBT21CLEVBQVcsR0RqR2QsY0NpR2dDLEVBQUksRUFDbERzQixFQUFNQyxXQUFXekIsRUFBTzBCLFFBQVFwRixFQUFHQSxHQUNwQyxDQUdDa0YsRUFBTXJCLFNBQ1JLLEVBQVEsQ0FDTnZCLEtBQU02QixFQUNOM0IsTUFBT3FDLEVBQU1HLEtBQUl0RixHQUFLQSxFQUFFOEMsUUFBT3lDLEtBQUssSUFBTTFGLEtBQ3RDb0QsRUFBYSxDQUFFbUIsTUFBTyxDQUFFZSxFQUFNLEdBQUdmLE1BQU0sR0FBSVIsSUFBVSxJQUc5RCxDQUVIRCxFQUFPVSxLQUFLRixFQUNiLENBRUQsT0FBT1IsQ0FDUixDQUlNLFNBQVM2QixFQUFVbEMsR0FBa0IsSUFBZEUseURBQVUsQ0FBQSxFQUN0QyxNQUFNRCxFQUFnQkMsRUFBUUosS0FBT2IsRUFBa0JELEVBQ3ZELE9BQU9lLEVBQVVDLEVBQUlDLEVBQWVDLEVBQ3JDLENDbElELE1BQU1pQyxFQUFVekYsR0FBS0EsRUFBRXdFLE1BQU0sR0FBSSxHQUFHa0IsUUFBUSxNQUFPLEtBRTdDQyxFQUFXaEQsR0FBS0EsR0FBaUIsTUFBWkEsRUFBRUcsT0FBaUIsR0FDeEM4QyxFQUFTakQsR0FBS0EsR0FBS0EsRUFBRUMsT0FBUzlCLEdBQVMsQ0FBRStFLEdBQUlsRCxFQUFFRyxPQUMvQ2dELEVBQVVuRCxHQUFLQSxHQUFLQSxFQUFFQyxPQUFTOUIsR0FBUyxDQUFFaUYsR0FBSXBELEVBQUVHLE9BQ2hEa0QsRUFBUXJELEdBQUtBLEdBQWlCLE1BQVpBLEVBQUVHLE9BQWlCLEdBQ3JDbUQsRUFBUXRELEdBQUtBLEdBQUtBLEVBQUVDLE9BQVM3QixHQUFjLENBQUU4RSxHQUFJbEQsRUFBRUcsT0FDbkRvRCxFQUFTdkQsR0FBS0EsR0ZFTyxnQkVGRkEsRUFBRUMsTUFBd0IsdUJBQXVCc0IsS0FBS3ZCLEVBQUVHLFFBQVUsQ0FBRXFELFVBQVd4RCxFQUFFRyxPQUNwR3NELEVBQVF6RCxHQUFLQSxHRkFPLGVFQUZBLEVBQUVDLE1BQXVCLENBQUV5RCxhQUFjMUQsRUFBRUcsTUFBTTBCLE1BQU0sR0FBSSxJQUU3RThCLEVBQVMzRCxHQUFLQSxHRkVPLGdCRUZGQSxFQUFFQyxNQUF3QixDQUFFMkQsS0FBTTVELEVBQUVHLE9BRXZEMEQsRUFBVTdELElBQ2QsR0FBSUEsR0ZOb0IsZUVNZkEsRUFBRUMsS0FBcUIsQ0FDOUIsTUFBTWxDLEVBQUksNEJBQTRCQyxLQUFLOEUsRUFBUTlDLEVBQUVHLFFBQ3JELEdBQUlwQyxFQUFHLENBQ0wsT0FBVStGLEVBQU1DLEdBQVVoRyxFQUMxQixJQUFLZ0csR0FBUyx1QkFBdUJ4QyxLQUFLd0MsR0FDeEMsTUFBTyxDQUNMTCxhQUFjSSxHQUFRLEdBQ3RCTixVQUFXTyxHQUFTLEdBR3pCLENBQ0YsR0FJR0MsRUFBWSxDQUNoQixDQUFFZixHQUNGLENBQUVBLEVBQVFELEVBQVVHLEdBQ3BCLENBQUVHLEdBQ0YsQ0FBRU8sRUFBU1IsRUFBT0osR0FDbEIsQ0FBRVksRUFBU1IsRUFBT0osRUFBUUQsRUFBVUcsR0FDcEMsQ0FBRVUsRUFBU1IsRUFBT0MsR0FDbEIsQ0FBRUMsRUFBUUYsRUFBT0osR0FDakIsQ0FBRU0sRUFBUUYsRUFBT0osRUFBUUQsRUFBVUcsR0FDbkMsQ0FBRUksRUFBUUYsRUFBT0MsR0FDakIsQ0FBRUcsRUFBT0YsRUFBUUYsRUFBT0osR0FDeEIsQ0FBRVEsRUFBT0YsRUFBUUYsRUFBT0osRUFBUUQsRUFBVUcsR0FDMUMsQ0FBRU0sRUFBT0YsRUFBUUYsRUFBT0MsSUFHcEJXLEVBQWlCRCxFQUFVMUUsT0FBTyxDQUN0QyxDQUFFcUUsR0FDRixDQXBDYTNELEdBQUtBLEdGQU8sZ0JFQUZBLEVBQUVDLE1BQXdCLENBQUV5RCxhQUFjMUQsRUFBRUcsT0FvQ3pEa0QsRUFBT00sR0FDakIsQ0FwQmUzRCxHQUFLQSxHRm5CSSxlRW1CQ0EsRUFBRUMsTUFBdUIsQ0FBRXlELGFBQWNaLEVBQVE5QyxFQUFFRyxRQW9CaEVrRCxFQUFPTSxLQUdkLFNBQVNPLEVBQVVDLEdBQTZDLElBQXhDQyw2REFBb0J4RCx5REFBZ0IsR0FDakUsTUFBTUksRUFBU04sRUFBVXlELEVBQUt2RCxFQUFlLENBQzNDTixZQUFZLEVBQ1pDLGFBQWEsSUFFVDhELEVBQVUsQ0FDZGIsVUFBVyxHQUNYRSxhQUFjLEdBQ2RSLEdBQUksR0FDSkUsR0FBSSxHQUNKUSxLQUFNLElBR0o1QyxFQUFPRyxRRmpEWSxjRWlERkgsRUFBTyxHQUFHZixNQUM3QmUsRUFBT3NELFFBRVQsTUFBTUMsRUFBT0gsRUFBY0gsRUFBaUJELEVBQzVDLElBQUssSUFBSWpDLEVBQUksRUFBR0EsRUFBSXdDLEVBQUtwRCxPQUFRWSxJQUFLLENBQ3BDLE1BQU15QyxFQUFPLElBQUtILEdBQ2xCLEdBQUlFLEVBQUt4QyxHQUFHWixTQUFXSCxFQUFPRyxPQUFRLENBTXBDLEdBTGNvRCxFQUFLeEMsR0FBRzNFLE9BQU0sQ0FBQ3FILEVBQU9DLEtBQ2xDLE1BQU1ySCxFQUFJb0gsRUFBTXpELEVBQU8wRCxJQUV2QixPQURBNUQsT0FBT0MsT0FBT3lELEVBQU1uSCxHQUNiQSxDQUFQLElBR0EsT0FBT21ILENBRVYsQ0FDRixDQUNELE9BQU8sSUFDUixDQ2hGTSxTQUFTRyxFQUFTQyxHQUN2QixNQUFNQyxHQUFLRCxHQUFVLElBQUlFLGNBQ3pCLElBQUl6SCxFQUFJLEVBQ0owRSxFQUFJLEVBQ1IsS0FBT0EsSUFBTThDLEVBQUUxRCxTQUFVWSxFQUFHLENBQzFCLE1BQU1nRCxFQUFNRixFQUFFRyxXQUFXakQsR0FDckJnRCxHQUFPLElBQU1BLEdBQU8sS0FDdEIxSCxFQUFJLEdBQUtBLEVBQUkwSCxFQUFNLEdBRXRCLENBQ0QsT0FBTzFILEVBQUksQ0FDWixDQUVNLFNBQVM0SCxFQUFPQyxHQUNyQixJQUFJNUgsRUFBSTRILEVBQ0pMLEVBQUksR0FDUixLQUFPdkgsR0FBSyxHQUNWdUgsRUFBSU0sT0FBT0MsYUFBYTlILEVBQUksR0FBSyxJQUFNdUgsRUFDdkN2SCxFQUFJK0gsS0FBS0MsTUFBTWhJLEVBQUksSUFBTSxFQUUzQixPQUFPdUgsQ0FDUixDQUVNLFNBQVNVLEVBQVNDLEdBQ3ZCLE9BQVFBLEVBQVMsQ0FDbEIsQ0FFTSxTQUFTQyxFQUFPQyxHQUNyQixPQUFPUCxPQUFPTyxFQUFNLEVBQ3JCLENBRU0sU0FBU0MsRUFBWWxFLEdBQzFCLE1BQU1pRSxJQUFFQSxFQUFGUixLQUFPQSxFQUFQVSxPQUFhQSxFQUFiQyxNQUFxQkEsR0FBVXBFLEVBQ3JDLE1BQU8sQ0FBRWlFLE1BQUtSLE9BQU1VLFNBQVFDLFFBQU9DLE9BQU8sRUFBT0MsUUFBUSxFQUFPQyxNQUFNLEVBQU9DLFNBQVMsRUFDdkYsQ0FPTSxTQUFTQyxFQUFNekUsR0FDcEIsTUFBTTBFLEVBQVE5SSxHQUFNQSxFQUFJLElBQU0sSUFDeEJxSSxJQUFFQSxFQUFGUixLQUFPQSxFQUFQVSxPQUFhQSxFQUFiQyxNQUFxQkEsRUFBckJDLE1BQTRCQSxFQUE1QkMsT0FBbUNBLEVBQW5DQyxLQUEyQ0EsRUFBM0NDLFFBQWlEQSxHQUFZeEUsRUFFbkUsT0FBWSxJQUFSaUUsR0g1QmtCLFVHNEJMRSxFQUNSTyxFQUFNTCxHQUFTYixFQUFNQyxHQUFRLElBQU1pQixFQUFNSixHQUFVZCxFQUFNWSxHQUdyRCxJQUFUWCxHSGpDa0IsUUdpQ0pXLEVBQ1RNLEVBQU1ILEdBQVFQLEVBQU1DLEdBQU8sSUFBTVMsRUFBTUYsR0FBV1IsRUFBTUcsR0FHcEQsTUFBVEMsR0FBMkIsTUFBVkQsR0FBbUJDLElBQVVYLEdBQVFVLElBQVdGLEVBSTlEUyxFQUFNTCxHQUFTYixFQUFNQyxHQUFRaUIsRUFBTUgsR0FBUVAsRUFBTUMsR0FIL0NTLEVBQU1MLEdBQVNiLEVBQU1DLEdBQVFpQixFQUFNSCxHQUFRUCxFQUFNQyxHQUFPLElBQU1TLEVBQU1KLEdBQVVkLEVBQU1ZLEdBQVNNLEVBQU1GLEdBQVdSLEVBQU1HLEVBSTlILENBRU0sU0FBU1EsR0FBUUMsR0FDdEIsSUFBSXRJLEVBQ0EySCxFQUFNLEVBQ05SLEVBQU8sRUFDUFUsRUgvQ2tCLFFHZ0RsQkMsRUhqRGtCLE1Ha0RsQkcsR0FBTyxFQUNQRixHQUFRLEVBQ1JHLEdBQVUsRUFDVkYsR0FBUyxFQUViLEdBQUtoSSxFQUFJLHdDQUF3Q0MsS0FBS3FJLEdBQVksQ0FDaEUsTUFBTUMsRUFBSTNCLEVBQVE1RyxFQUFFLElBQ2R3SSxFQUFJNUIsRUFBUTVHLEVBQUUsSUFPcEIsT0FOQW1ILEVBQU9HLEtBQUttQixJQUFJRixFQUFHQyxHQUNuQlYsRUFBUVIsS0FBS29CLElBQUlILEVBQUdDLEdBQ3BCVCxJQUFVL0gsRUFBRXVJLEdBQUtDLEVBQUksRUFBSSxHQUN6QlIsSUFBV2hJLEVBQUV1SSxHQUFLQyxFQUFJLEVBQUksR0FDMUJQLEdBQU8sRUFDUEMsR0FBVSxFQUNILENBQUVQLE1BQUtSLE9BQU1VLFNBQVFDLFFBQU9HLE9BQU1GLFFBQU9HLFVBQVNGLFNBVDNELENBWUssR0FBS2hJLEVBQUksNENBQTRDQyxLQUFLcUksR0FBWSxDQUN6RSxNQUFNQyxFQUFJZixFQUFReEgsRUFBRSxJQUNkd0ksRUFBSWhCLEVBQVF4SCxFQUFFLElBT3BCLE9BTkEySCxFQUFNTCxLQUFLbUIsSUFBSUYsRUFBR0MsR0FDbEJYLEVBQVNQLEtBQUtvQixJQUFJSCxFQUFHQyxHQUNyQlAsSUFBU2pJLEVBQUV1SSxHQUFLQyxFQUFJLEVBQUksR0FDeEJOLElBQVlsSSxFQUFFdUksR0FBS0MsRUFBSSxFQUFJLEdBQzNCVCxHQUFRLEVBQ1JDLEdBQVMsRUFDRixDQUFFTCxNQUFLUixPQUFNVSxTQUFRQyxRQUFPRyxPQUFNRixRQUFPRyxVQUFTRixTQVR0RCxDQVlBLENBQ0gsTUFBUVcsRUFBT0MsR0FBVU4sRUFBU2xKLE1BQU0sS0FDeEMsR0FBS1ksRUFBSSwwQ0FBMENDLEtBQUswSSxHQXdCdEQsT0F2QkF4QixFQUFPUCxFQUFRNUcsRUFBRSxJQUNqQjJILEVBQU1ILEVBQVF4SCxFQUFFLElBQ2hCK0gsSUFBVS9ILEVBQUUsR0FDWmlJLElBQVNqSSxFQUFFLEdBQ1A0SSxJQUFVNUksRUFBSSwwQ0FBMENDLEtBQUsySSxLQUMvRGQsRUFBUWxCLEVBQVE1RyxFQUFFLElBQ2xCNkgsRUFBU0wsRUFBUXhILEVBQUUsSUFDbkJnSSxJQUFXaEksRUFBRSxHQUNia0ksSUFBWWxJLEVBQUUsR0FFVjZILEVBQVNGLEtBQ1RBLEVBQUtFLEVBQVFJLEVBQU1DLEdBQVksQ0FBRUwsRUFBUUYsRUFBS08sRUFBU0QsSUFFdkRILEVBQVFYLEtBQ1JBLEVBQU1XLEVBQU9DLEVBQU9DLEdBQVcsQ0FBRUYsRUFBT1gsRUFBTWEsRUFBUUQsTUFJMURGLEVBQVNGLEVBQ1RHLEVBQVFYLEVBQ1JlLEVBQVVELEVBQ1ZELEVBQVNELEdBRUosQ0FBRUosTUFBS1IsT0FBTVUsU0FBUUMsUUFBT0csT0FBTUYsUUFBT0csVUFBU0YsU0FFNUQsQ0FDRCxPQUFPLElBQ1IsQ0FFTSxTQUFTYSxHQUFZekMsR0FBeUIsSUFBcEJDLDZEQUMvQixNQUFNL0csRUFBSTZHLEVBQVNDLEVBQUtDLEVBQWF2RSxHQUNyQyxHQUFJeEMsSUFBTUEsRUFBRTZGLElBQU03RixFQUFFdUcsTUFBTyxDQUN6QixJQUFJbkMsRUFBUSxLQUlaLE9BSElwRSxFQUFFNkYsS0FDSnpCLEVBQVFwRSxFQUFFK0YsR0FBS2dELEdBQU8vSSxFQUFFNkYsR0FBSyxJQUFNN0YsRUFBRStGLElBQU1nRCxHQUFPL0ksRUFBRTZGLEtBRWxEN0YsRUFBRXVHLE1BQVFuQyxHQUNacEUsRUFBRW9FLE1BQVFBLFNBQ0hwRSxFQUFFNkYsVUFDRjdGLEVBQUUrRixHQUNGL0YsR0FHQSxJQUVWLENBQ0QsT0FBTyxJQUNSLENBRUQsSUFBZXdKLEdBQUEsQ0FDYmxDLFVBQ0FNLFFBQ0FVLGFBQ0FtQixXQW5ISyxTQUFxQnJGLEdBQzFCLE1BQU1pRSxJQUFFQSxFQUFGUixLQUFPQSxFQUFQVSxPQUFhQSxFQUFiQyxNQUFxQkEsR0FBVXBFLEVBQ3JDLE1BQU8sQ0FBRWlFLE1BQUtSLE9BQU1VLFNBQVFDLFFBQU9DLE9BQU8sRUFBTUMsUUFBUSxFQUFNQyxNQUFNLEVBQU1DLFNBQVMsRUFDcEYsRUFpSENjLEdBQUliLEVBQ0pjLEtBQU1aLEdBQ04zQixNQUFPbUMsSUMxSlQsU0FBU0ssS0FDUCxJQUFJbEYsRUFBSSxFQUNSLE1BQU8sSUFBTSxNQUFTQSxHQUN2QixDQ0lELFNBQVNtRixHQUFTL0csRUFBT2dILEdBQ3ZCLE9BQUlBLEVBQ0toQyxPQUFPaEYsRUFBUSxHQUVqQkEsRUFBUSxJQUFNQSxFQUFRLElBQU0sRUFDcEMsQ0FFTSxTQUFTaUgsR0FBTTNGLEdBQ3BCLE1BQU15QixHQUFFQSxFQUFGbUUsR0FBTUEsRUFBTmpFLEdBQVVBLEVBQVZrRSxHQUFjQSxFQUFkQyxJQUFrQkEsRUFBbEJDLElBQXVCQSxFQUF2QkMsSUFBNEJBLEVBQTVCQyxJQUFpQ0EsR0FBUWpHLEVBRS9DLEdBQVcsSUFBUHlCLEdMQWtCLFVLQU5FLEVBQWlCLENBQy9CLE1BQU1rRCxFQUFJWSxHQUFRRyxFQUFJRSxHQUNoQmhCLEVBQUlXLEdBQVFJLEVBQUlFLEdBQ3RCLE1BQU8sS0FBT2xCLElBQU1DLEVBQUlELEVBQUlBLEVBQUksS0FBT0MsRUFOZCxDQVMzQixHQUFXLElBQVBjLEdMUGtCLFFLT05DLEVBQWlCLENBQy9CLE1BQU1oQixFQUFJWSxHQUFRaEUsRUFBSXVFLEdBQ2hCbEIsRUFBSVcsR0FBUTlELEVBQUlzRSxHQUN0QixNQUFPLEtBQU9wQixJQUFNQyxFQUFJRCxFQUFJQSxFQUFJLEtBQU9DLEVBWmQsQ0FlM0IsTUFBTW9CLEVBQU9ULEdBQVFoRSxFQUFJdUUsR0FDbkJHLEVBQU9WLEdBQVE5RCxFQUFJc0UsR0FDbkJHLEVBQU9YLEdBQVFHLEVBQUlFLEdBQ25CTyxFQUFPWixHQUFRSSxFQUFJRSxHQUN6QixPQUFJRyxJQUFTQyxHQUFRQyxJQUFTQyxFQUNyQixJQUFNSCxFQUFPLElBQU1FLEVBQU8sS0FBT0QsRUFBTyxJQUFNRSxFQUdoRCxJQUFNSCxFQUFPLElBQU1FLENBQzNCLENBRUQsU0FBU0UsR0FBYTVELEdBQ3BCLElBQUlqQixFQUFLLEVBQ0xtRSxFQUFLLEVBQ0xqRSxFTDFCa0IsUUsyQmxCa0UsRUw1QmtCLE1LNkJsQkcsR0FBTSxFQUNORixHQUFNLEVBQ05HLEdBQU0sRUFDTkYsR0FBTSxFQUVWLE1BQU1RLEVBQUssOEJBQThCaEssS0FBS21HLEdBQzFDNkQsR0FDRUEsRUFBRyxHQUNMOUUsRUFBSzNGLFNBQVN5SyxFQUFHLEdBQUksSUFFZEEsRUFBRyxLQUNWOUUsRUFBSzNGLFNBQVN5SyxFQUFHLEdBQUksSUFBTSxFQUMzQlAsR0FBTSxHQUVSckUsRUFBS0YsRUFDTHdFLEVBQU1ELEVBQ050RCxFQUFNQSxFQUFJdEMsTUFBTW1HLEVBQUcsR0FBRzdHLFVBSXRCc0csR0FBTSxFQUNOQyxHQUFNLEdBR1IsTUFBTU8sRUFBSyw4QkFBOEJqSyxLQUFLbUcsR0FtQjlDLE9BbEJJOEQsR0FDRUEsRUFBRyxHQUNMWixFQUFLOUosU0FBUzBLLEVBQUcsR0FBSSxJQUVkQSxFQUFHLEtBQ1ZaLEVBQUs5SixTQUFTMEssRUFBRyxHQUFJLElBQU0sRUFDM0JWLEdBQU0sR0FFUkQsRUFBS0QsRUFDTEcsRUFBTUQsRUFDTnBELEVBQU1BLEVBQUl0QyxNQUFNb0csRUFBRyxHQUFHOUcsVUFJdEJvRyxHQUFNLEVBQ05DLEdBQU0sSUFHRlEsSUFBT0MsR0FBTzlELEVBQUloRCxPQUNmLEtBRUYsQ0FBRStCLEtBQUltRSxLQUFJakUsS0FBSWtFLEtBQUlHLE1BQUtGLE1BQUtHLE1BQUtGLE1BQ3pDLENBRU0sU0FBU1UsR0FBUS9ELEdBQ3RCLE1BQVF1QyxFQUFPQyxHQUFVeEMsRUFBSWhILE1BQU0sSUFBSyxHQUNsQ3NFLEVBQVFzRyxHQUFZckIsR0FDMUIsSUFBS2pGLEVBQ0gsT0FBTyxLQUVULEdBQUlBLEdBQVNrRixFQUFPLENBQ2xCLE1BQU13QixFQUFXSixHQUFZcEIsR0FDN0IsSUFBSXdCLEVBUUYsT0FBTyxLQU5QMUcsRUFBTTJCLEdBQUsrRSxFQUFTL0UsR0FDcEIzQixFQUFNNkYsR0FBS2EsRUFBU2IsR0FDcEI3RixFQUFNaUcsSUFBTVMsRUFBU1QsSUFDckJqRyxFQUFNK0YsSUFBTVcsRUFBU1gsR0FLeEIsQ0FDRCxPQUFPL0YsQ0FDUixDQW1CRCxJQUFlMkcsR0FBQSxDQUNickIsR0FBSUssR0FDSkosS0FBTWtCLEdBQ056RCxNQXBCSyxTQUFxQk4sR0FBeUIsSUFBcEJDLDZEQUMvQixNQUFNL0csRUFBSTZHLEVBQVNDLEVBQUtDLEVBQWF0RSxHQUNyQyxHQUFJekMsSUFBTUEsRUFBRTZGLElBQU03RixFQUFFdUcsTUFBTyxDQUN6QixNQUFNbkMsRUFBUXBFLEVBQUUrRixHQUFLOEUsR0FBTzdLLEVBQUU2RixHQUFLLElBQU03RixFQUFFK0YsSUFBTThFLEdBQU83SyxFQUFFNkYsSUFDMUQsT0FBSTdGLEVBQUV1RyxNQUFRbkMsR0FDWnBFLEVBQUVvRSxNQUFRQSxTQUNIcEUsRUFBRTZGLFVBQ0Y3RixFQUFFK0YsR0FDRi9GLEdBR0EsSUFFVixDQUNELE9BQU8sSUFDUixHQ2hGRCxTQUFTZ0wsR0FBU25LLEVBQUtvSyxFQUFLQyxFQUFNOUIsR0FDaEMsSUFBSStCLEVBQUl0SyxFQWVSLE9BZEtvSyxJQUNIRSxFQUFJRCxFQUFPckssRUFLUHNLLEVBQUksSUFDTkEsRUFBSS9CLEVBQU0rQixFQUFJLEdBR1pBLEVBQUkvQixJQUNOK0IsR0FBSy9CLEVBQU0sSUFHUitCLENBQ1IsQ0M3Q00sTUFBTUMsR0FBYSxDQUN4QkMsU1B6QnNCLFdPMEJ0QkMsUVB6QnFCLE9PMEJyQkMsTVB6Qm1CLFFPMEJuQkMsT1B6Qm9CLFNPMEJwQkMsU1B6QnNCLFdPMEJ0QkMsUVB6QnFCLFVPMEJyQkMsV1B6QndCLGFPMEJ4QkMsT1B6Qm9CLFNPMEJwQkMsV1B6QndCLGFPMEJ4QkMsV1B6QndCLGFPMEJ4QkMsWVB6QnlCLGNPMEJ6QmpMLFFBQ0FDLGFBQ0FpTCxZUHpCeUIsY08wQnpCQyxVUHpCdUIsWU8wQnZCQyxRUHpCcUIsNEJBRUMsdUJBQ0Esc0NJWGpCLFNBQWtCdkksR0FBb0QsSUFBNUN3QyxVQUFFQSxFQUFZLEdBQWRFLGFBQWtCQSxFQUFlLDJEQUFPLEdBQ3ZFLE1BQU04RixFQUFhLEdBQ25CLElBQUlDLEVBQWEsS0FDakIsTUFBTUMsRUFBUSxDQUFBLEVBQ1JDLEVBQU0xQyxLQXlEWixPQXZEQWpHLEVBQU80SSxTQUFRLENBQUNwSSxFQUFPTyxLQUdyQixHQUZBUCxFQUFNcUksTUFBUTlILEVBQ2RQLEVBQU1zSSxNQUFRTixFQUFXckksT0FDTCxNQUFoQkssRUFBTXJCLE1BQ1JxQixFQUFNc0ksTUFBUU4sRUFBV3JJLE9BQVMsRUFDbENxSSxFQUFXOUgsS0FBS0YsUUFFYixHQUFvQixNQUFoQkEsRUFBTXJCLE1BQWUsQ0FDNUIsTUFBTTRKLEVBQVVQLEVBQVdqSCxNQUMzQixHQUFJd0gsRUFBUyxDQUNYLE1BQU1DLEVBQVNMLElBQ2ZuSSxFQUFNeUksUUFBVUQsRUFDaEJ4SSxFQUFNc0ksTUFBUUMsRUFBUUQsTUFDdEJDLEVBQVFFLFFBQVVELENBQ25CLE1BRUN4SSxFQUFNMEksT0FBUSxDQUVqQixNQUNJLEdBQW9CLE1BQWhCMUksRUFBTXJCLE1BQ1JzSixFQUlIakksRUFBTTBJLE9BQVEsRUFIZFQsRUFBYWpJLE9BTVosR0FBb0IsTUFBaEJBLEVBQU1yQixNQUFlLENBQzVCLEdBQUlzSixFQUFZLENBQ2QsTUFBTU8sRUFBU0wsSUFDZm5JLEVBQU15SSxRQUFVRCxFQUNoQlAsRUFBV1EsUUFBVUQsQ0FDdEIsTUFFQ3hJLEVBQU0wSSxPQUFRLEVBRWhCVCxFQUFhLElBQ2QsTUFDSSxHQUFJakksRUFBTXZCLE9BQVM5QixHQUFTcUQsRUFBTXZCLE9BQVM3QixFQUFZLENBQzFELE1BQU0rRixFQUFNeUMsR0FBV3BGLEVBQU1yQixPQUFPLEdBQzlCMEcsRUFBSzFDLEdBQU8sSUFBQTdFLE9BQUs2RSxFQUFJVCxjQUFnQkEsY0FBZ0JTLEVBQUlYLFdBQWFBLEVBQWFXLEtBQUFBLE9BQUFBLEVBQUkxQyxNQUFReUUsRUFBS1AsRUFBV3hCLEVBQUkxQyxRQUFVMEMsRUFBSVAsTUFBUXVHLGNBQzNJdEQsSUFDRUEsS0FBTTZDLEVBQ1JsSSxFQUFNeUksUUFBVVAsRUFBTTdDLElBR3RCckYsRUFBTXlJLFFBQVVOLElBQ2hCRCxFQUFNN0MsR0FBTXJGLEVBQU15SSxTQUd2QixLSmhEa0IsWUlpRFZ6SSxFQUFNdkIsT0FDYnVCLEVBQU0wSSxPQUFRLEVBQ2YsSUFFSWxKLENBQ1IsK0VFRU0sU0FBd0JMLEVBQUl5SixHQUNqQyxNQUFNQyxFQUFTakUsR0FBT2dFLEdBQ2hCRSxFQUF5QixpQkFBUDNKLEVBRWxCSyxFQUFTc0osRUFDWHpILEVBQVNsQyxFQUFJLENBQUVMLFlBQVksRUFBT0MsYUFBYSxFQUFPRSxNQUFNLElBQzVERSxFQXNDSixPQXBDQUssRUFBTzRJLFNBQVFwSSxJQUNiLEdBQUlBLEVBQU12QixPQUFTOUIsR0FBU3FELEVBQU12QixPQUFTN0IsRUFBWSxDQUNyRCxNQUFNcUQsRUFBUSxDQUFBLEVBQ1JwRSxFQUFJNkssR0FBTzFHLEVBQU1yQixPQUNqQitDLEVBQUttRixHQUFRaEwsRUFBRTZGLEdBQUk3RixFQUFFb0ssSUFBSzRDLEVBQU8zRSxJTmpFckIsU01rRVp0QyxFQUFLaUYsR0FBUWhMLEVBQUUrRixHQUFJL0YsRUFBRXFLLElBQUsyQyxFQUFPM0UsSU5sRXJCLFNNbUVkeEMsRUFBS0UsR0FDUDNCLEVBQU1pRSxJQUFNdEMsRUFDWjNCLEVBQU11RSxLQUFPM0ksRUFBRXFLLElBQ2ZqRyxFQUFNbUUsT0FBUzFDLEVBQ2Z6QixFQUFNd0UsUUFBVTVJLEVBQUVvSyxNQUdsQmhHLEVBQU1pRSxJQUFNeEMsRUFDWnpCLEVBQU11RSxLQUFPM0ksRUFBRW9LLElBQ2ZoRyxFQUFNbUUsT0FBU3hDLEVBQ2YzQixFQUFNd0UsUUFBVTVJLEVBQUVxSyxLQUVwQixNQUFNTCxFQUFLZ0IsR0FBUWhMLEVBQUVnSyxHQUFJaEssRUFBRWtLLElBQUs4QyxFQUFPbkYsS05oRnJCLE9NaUZab0MsRUFBS2UsR0FBUWhMLEVBQUVpSyxHQUFJakssRUFBRW1LLElBQUs2QyxFQUFPbkYsS05qRnJCLE9Na0ZkbUMsRUFBS0MsR0FDUDdGLEVBQU15RCxLQUFPb0MsRUFDYjdGLEVBQU1xRSxNQUFRekksRUFBRW1LLElBQ2hCL0YsRUFBTW9FLE1BQVF3QixFQUNkNUYsRUFBTXNFLE9BQVMxSSxFQUFFa0ssTUFHakI5RixFQUFNeUQsS0FBT21DLEVBQ2I1RixFQUFNcUUsTUFBUXpJLEVBQUVrSyxJQUNoQjlGLEVBQU1vRSxNQUFReUIsRUFDZDdGLEVBQU1zRSxPQUFTMUksRUFBRW1LLEtBRW5CaEcsRUFBTXJCLE1BQVErRixFQUFLekUsRUFDcEIsS0FHSTZJLEVBQ0h0SixFQUFPMkIsS0FBSXRGLEdBQUtBLEVBQUU4QyxRQUFPeUMsS0FBSyxJQUM5QjVCLENBQ0wsd0JBbkhNLFNBQXdCTCxFQUFJeUosR0FDakMsTUFBTTFFLElBQUVBLEVBQUZSLEtBQU9BLEdBQVNrQixHQUFPZ0UsR0FDdkJFLEVBQXlCLGlCQUFQM0osRUFFbEJLLEVBQVNzSixFQUNYekgsRUFBU2xDLEVBQUksQ0FBRUwsWUFBWSxFQUFPQyxhQUFhLEVBQU9nSyxNQUFNLElBQzVENUosRUFzQ0osT0FwQ0FLLEVBQU80SSxTQUFRcEksSUFDYixHQUFJQSxFQUFNdkIsT0FBUzlCLEVBQU8sQ0FDeEIsTUFBTXNELEVBQVEsQ0FBQSxFQUNScEUsRUFBSStJLEdBQU81RSxFQUFNckIsT0FFdkJzQixFQUFNeUIsR0FBSzdGLEVBQUUySSxLQUFPM0ksRUFBRXFJLElBQU1ySSxFQUFFcUksSUFBTUEsRUFDcENqRSxFQUFNZ0csSUFBTXBLLEVBQUUySSxLQUNkdkUsRUFBTTJCLEdBQUsvRixFQUFFNEksUUFBVTVJLEVBQUV1SSxPQUFTdkksRUFBRXVJLE9BQVNGLEVBQzdDakUsRUFBTWlHLElBQU1ySyxFQUFFNEksUUFFZHhFLEVBQU00RixHQUFLaEssRUFBRXlJLE1BQVF6SSxFQUFFNkgsS0FBTzdILEVBQUU2SCxLQUFPQSxFQUN2Q3pELEVBQU04RixJQUFNbEssRUFBRXlJLE1BQ2RyRSxFQUFNNkYsR0FBS2pLLEVBQUUwSSxPQUFTMUksRUFBRXdJLE1BQVF4SSxFQUFFd0ksTUFBUVgsRUFDMUN6RCxFQUFNK0YsSUFBTW5LLEVBQUUwSSxPQUdkdkUsRUFBTXJCLE1BQVFpSCxHQUFLM0YsRUFDcEIsTUFDSSxHQUFJRCxFQUFNdkIsT0FBUzdCLEVBQVksQ0FDbEMsTUFBTXFELEVBQVEsQ0FBQSxFQUNScEUsRUFBSStJLEdBQU81RSxFQUFNckIsT0FFdkJzQixFQUFNeUIsR0FBSzdGLEVBQUUySSxLQUFPM0ksRUFBRXFJLElBQU1ySSxFQUFFcUksSUFBTUEsRUFDcENqRSxFQUFNZ0csSUFBTXBLLEVBQUUySSxLQUNkdkUsRUFBTTJCLEdBQUsvRixFQUFFNEksUUFBVTVJLEVBQUV1SSxPQUFTdkksRUFBRXVJLE9BQVNGLEVBQzdDakUsRUFBTWlHLElBQU1ySyxFQUFFNEksUUFFZHhFLEVBQU00RixHQUFLaEssRUFBRXlJLE1BQVF6SSxFQUFFNkgsS0FBTzdILEVBQUU2SCxLQUFPQSxFQUN2Q3pELEVBQU04RixJQUFNbEssRUFBRXlJLE1BQ2RyRSxFQUFNNkYsR0FBS2pLLEVBQUUwSSxPQUFTMUksRUFBRXdJLE1BQVF4SSxFQUFFd0ksTUFBUVgsRUFDMUN6RCxFQUFNK0YsSUFBTW5LLEVBQUUwSSxPQUVkdkUsRUFBTXJCLE1BQVFpSCxHQUFLM0YsRUFDcEIsS0FHSTZJLEVBQ0h0SixFQUFPMkIsS0FBSXRGLEdBQUtBLEVBQUU4QyxRQUFPeUMsS0FBSyxJQUM5QjVCLENBQ0wifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "commonjs" }
|
package/{src → lib}/a1-test.js
RENAMED
|
File without changes
|
package/{src → lib}/a1.js
RENAMED
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { test, Test } from 'tape';
|
|
2
|
+
import { FX_PREFIX, OPERATOR, NUMBER, RANGE, RANGE_BEAM } from './constants.js';
|
|
3
|
+
import { addMeta } from './addMeta.js';
|
|
4
|
+
import { tokenize } from './lexer.js';
|
|
5
|
+
|
|
6
|
+
Test.prototype.isMetaTokens = function isTokens (expr, result, opts) {
|
|
7
|
+
this.deepEqual(addMeta(tokenize(expr), opts), result, expr);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
test('add extra meta to operators', t => {
|
|
11
|
+
// parens should be grouped and tagged with depth
|
|
12
|
+
t.isMetaTokens('=((1)+(1))', [
|
|
13
|
+
{ index: 0, depth: 0, type: FX_PREFIX, value: '=' },
|
|
14
|
+
{ index: 1, depth: 1, type: OPERATOR, value: '(', groupId: 'fxg3' },
|
|
15
|
+
{ index: 2, depth: 2, type: OPERATOR, value: '(', groupId: 'fxg1' },
|
|
16
|
+
{ index: 3, depth: 2, type: NUMBER, value: '1' },
|
|
17
|
+
{ index: 4, depth: 2, type: OPERATOR, value: ')', groupId: 'fxg1' },
|
|
18
|
+
{ index: 5, depth: 1, type: OPERATOR, value: '+' },
|
|
19
|
+
{ index: 6, depth: 2, type: OPERATOR, value: '(', groupId: 'fxg2' },
|
|
20
|
+
{ index: 7, depth: 2, type: NUMBER, value: '1' },
|
|
21
|
+
{ index: 8, depth: 2, type: OPERATOR, value: ')', groupId: 'fxg2' },
|
|
22
|
+
{ index: 9, depth: 1, type: OPERATOR, value: ')', groupId: 'fxg3' }
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
// don't be fooled by imbalanced parens
|
|
26
|
+
t.isMetaTokens('=)())', [
|
|
27
|
+
{ index: 0, depth: 0, type: FX_PREFIX, value: '=' },
|
|
28
|
+
{ index: 1, depth: 0, type: OPERATOR, value: ')', error: true },
|
|
29
|
+
{ index: 2, depth: 1, type: OPERATOR, value: '(', groupId: 'fxg1' },
|
|
30
|
+
{ index: 3, depth: 1, type: OPERATOR, value: ')', groupId: 'fxg1' },
|
|
31
|
+
{ index: 4, depth: 0, type: OPERATOR, value: ')', error: true }
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
// don't be fooled by nested curlys
|
|
35
|
+
t.isMetaTokens('={{}}', [
|
|
36
|
+
{ index: 0, depth: 0, type: FX_PREFIX, value: '=' },
|
|
37
|
+
{ index: 1, depth: 0, type: OPERATOR, value: '{', groupId: 'fxg1' },
|
|
38
|
+
{ index: 2, depth: 0, type: OPERATOR, value: '{', error: true },
|
|
39
|
+
{ index: 3, depth: 0, type: OPERATOR, value: '}', groupId: 'fxg1' },
|
|
40
|
+
{ index: 4, depth: 0, type: OPERATOR, value: '}', error: true }
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
// group ranges if they are equivalent
|
|
44
|
+
t.isMetaTokens("=B11,B11:B12,'Sheet11'!B11,SHEET1!$B11,sheet1!$b$11,A1:B11,[foo]Sheet1!B11,'[foo]Sheet1'!B11", [
|
|
45
|
+
{ index: 0, depth: 0, type: FX_PREFIX, value: '=' },
|
|
46
|
+
{ index: 1, depth: 0, type: RANGE, value: 'B11', groupId: 'fxg1' },
|
|
47
|
+
{ index: 2, depth: 0, type: OPERATOR, value: ',' },
|
|
48
|
+
{ index: 3, depth: 0, type: RANGE, value: 'B11:B12', groupId: 'fxg2' },
|
|
49
|
+
{ index: 4, depth: 0, type: OPERATOR, value: ',' },
|
|
50
|
+
{ index: 5, depth: 0, type: RANGE, value: "'Sheet11'!B11", groupId: 'fxg3' },
|
|
51
|
+
{ index: 6, depth: 0, type: OPERATOR, value: ',' },
|
|
52
|
+
{ index: 7, depth: 0, type: RANGE, value: 'SHEET1!$B11', groupId: 'fxg1' },
|
|
53
|
+
{ index: 8, depth: 0, type: OPERATOR, value: ',' },
|
|
54
|
+
{ index: 9, depth: 0, type: RANGE, value: 'sheet1!$b$11', groupId: 'fxg1' },
|
|
55
|
+
{ index: 10, depth: 0, type: OPERATOR, value: ',' },
|
|
56
|
+
{ index: 11, depth: 0, type: RANGE, value: 'A1:B11', groupId: 'fxg4' },
|
|
57
|
+
{ index: 12, depth: 0, type: OPERATOR, value: ',' },
|
|
58
|
+
{ index: 13, depth: 0, type: RANGE, value: '[foo]Sheet1!B11', groupId: 'fxg1' },
|
|
59
|
+
{ index: 14, depth: 0, type: OPERATOR, value: ',' },
|
|
60
|
+
{ index: 15, depth: 0, type: RANGE, value: "'[foo]Sheet1'!B11", groupId: 'fxg1' }
|
|
61
|
+
], { sheetName: 'Sheet1', workbookName: 'foo' });
|
|
62
|
+
|
|
63
|
+
t.isMetaTokens('=A:A,1:1,Sheet1!A:A:1:1,[foo]Sheet1!1:1', [
|
|
64
|
+
{ index: 0, depth: 0, type: FX_PREFIX, value: '=' },
|
|
65
|
+
{ index: 1, depth: 0, type: RANGE_BEAM, value: 'A:A', groupId: 'fxg1' },
|
|
66
|
+
{ index: 2, depth: 0, type: OPERATOR, value: ',' },
|
|
67
|
+
{ index: 3, depth: 0, type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
|
|
68
|
+
{ index: 4, depth: 0, type: OPERATOR, value: ',' },
|
|
69
|
+
{ index: 5, depth: 0, type: RANGE_BEAM, value: 'Sheet1!A:A', groupId: 'fxg1' },
|
|
70
|
+
{ index: 6, depth: 0, type: OPERATOR, value: ':' },
|
|
71
|
+
{ index: 7, depth: 0, type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
|
|
72
|
+
{ index: 8, depth: 0, type: OPERATOR, value: ',' },
|
|
73
|
+
{ index: 9, depth: 0, type: RANGE_BEAM, value: '[foo]Sheet1!1:1', groupId: 'fxg2' }
|
|
74
|
+
], { sheetName: 'Sheet1', workbookName: 'foo' });
|
|
75
|
+
|
|
76
|
+
t.end();
|
|
77
|
+
});
|
package/{src → lib}/addMeta.js
RENAMED
|
@@ -13,9 +13,11 @@ export function addMeta (tokens, { sheetName = '', workbookName = '' } = {}) {
|
|
|
13
13
|
const a1Map = {};
|
|
14
14
|
const uid = getIDer();
|
|
15
15
|
|
|
16
|
-
tokens.forEach(token => {
|
|
16
|
+
tokens.forEach((token, i) => {
|
|
17
|
+
token.index = i;
|
|
18
|
+
token.depth = parenStack.length;
|
|
17
19
|
if (token.value === '(') {
|
|
18
|
-
token.depth = parenStack.length;
|
|
20
|
+
token.depth = parenStack.length + 1;
|
|
19
21
|
parenStack.push(token);
|
|
20
22
|
}
|
|
21
23
|
else if (token.value === ')') {
|
package/{src → lib}/constants.js
RENAMED
|
@@ -23,9 +23,9 @@ export const MAX_ROWS = 2 ** 20 - 1; // 1048575
|
|
|
23
23
|
const re_ERROR = /^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!)/i;
|
|
24
24
|
const re_OPERATOR = /^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/;
|
|
25
25
|
const re_BOOLEAN = /^(TRUE|FALSE)\b/i;
|
|
26
|
-
const re_FUNCTION = /^[A-Z]+(?=\s*\()/i;
|
|
26
|
+
const re_FUNCTION = /^[A-Z_]+[A-Z\d_.]+(?=\s*\()/i;
|
|
27
27
|
const re_NEWLINE = /^\n+/;
|
|
28
|
-
const re_WHITESPACE =
|
|
28
|
+
const re_WHITESPACE = /^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/;
|
|
29
29
|
const re_STRING = /^"(?:""|[^"])*("|$)/;
|
|
30
30
|
const re_PATH_QUOTE = /^'(?:''|[^'])*('|$)/;
|
|
31
31
|
const re_PATH_BRACE = /^\[(?:[^\]])+(\]|$)/;
|
package/{src → lib}/index.js
RENAMED
|
File without changes
|
|
@@ -5,6 +5,9 @@ import { tokenize } from './lexer.js';
|
|
|
5
5
|
Test.prototype.isTokens = function isTokens (expr, result, opts) {
|
|
6
6
|
this.deepEqual(tokenize(expr, (opts || {})), result, expr);
|
|
7
7
|
};
|
|
8
|
+
Test.prototype.isTokensNeg = function isTokensNeg (expr, result, opts) {
|
|
9
|
+
this.deepEqual(tokenize(expr, { ...opts, negativeNumbers: true }), result, expr);
|
|
10
|
+
};
|
|
8
11
|
|
|
9
12
|
test('tokenize operators', t => {
|
|
10
13
|
t.isTokens('=1>1', [
|
|
@@ -269,6 +272,56 @@ test('tokenize functions', t => {
|
|
|
269
272
|
{ type: BOOLEAN, value: 'TRUE' },
|
|
270
273
|
{ type: OPERATOR, value: ')' }
|
|
271
274
|
]);
|
|
275
|
+
t.isTokens('=BINOM.DIST.RANGE(1)', [
|
|
276
|
+
{ type: FX_PREFIX, value: '=' },
|
|
277
|
+
{ type: FUNCTION, value: 'BINOM.DIST.RANGE' },
|
|
278
|
+
{ type: OPERATOR, value: '(' },
|
|
279
|
+
{ type: NUMBER, value: '1' },
|
|
280
|
+
{ type: OPERATOR, value: ')' }
|
|
281
|
+
]);
|
|
282
|
+
t.isTokens('=OCT2BIN(1)', [
|
|
283
|
+
{ type: FX_PREFIX, value: '=' },
|
|
284
|
+
{ type: FUNCTION, value: 'OCT2BIN' },
|
|
285
|
+
{ type: OPERATOR, value: '(' },
|
|
286
|
+
{ type: NUMBER, value: '1' },
|
|
287
|
+
{ type: OPERATOR, value: ')' }
|
|
288
|
+
]);
|
|
289
|
+
t.isTokens('=TEST_FUNC(1)', [
|
|
290
|
+
{ type: FX_PREFIX, value: '=' },
|
|
291
|
+
{ type: FUNCTION, value: 'TEST_FUNC' },
|
|
292
|
+
{ type: OPERATOR, value: '(' },
|
|
293
|
+
{ type: NUMBER, value: '1' },
|
|
294
|
+
{ type: OPERATOR, value: ')' }
|
|
295
|
+
]);
|
|
296
|
+
t.isTokens('=_xlfn.FOO(1)', [
|
|
297
|
+
{ type: FX_PREFIX, value: '=' },
|
|
298
|
+
{ type: FUNCTION, value: '_xlfn.FOO' },
|
|
299
|
+
{ type: OPERATOR, value: '(' },
|
|
300
|
+
{ type: NUMBER, value: '1' },
|
|
301
|
+
{ type: OPERATOR, value: ')' }
|
|
302
|
+
]);
|
|
303
|
+
t.isTokens('=_FOO(1)', [
|
|
304
|
+
{ type: FX_PREFIX, value: '=' },
|
|
305
|
+
{ type: FUNCTION, value: '_FOO' },
|
|
306
|
+
{ type: OPERATOR, value: '(' },
|
|
307
|
+
{ type: NUMBER, value: '1' },
|
|
308
|
+
{ type: OPERATOR, value: ')' }
|
|
309
|
+
]);
|
|
310
|
+
t.isTokens('=.FOO(1)', [
|
|
311
|
+
{ type: FX_PREFIX, value: '=' },
|
|
312
|
+
{ type: RANGE_NAMED, value: '.FOO' },
|
|
313
|
+
{ type: OPERATOR, value: '(' },
|
|
314
|
+
{ type: NUMBER, value: '1' },
|
|
315
|
+
{ type: OPERATOR, value: ')' }
|
|
316
|
+
]);
|
|
317
|
+
t.isTokens('=9FOO(1)', [
|
|
318
|
+
{ type: FX_PREFIX, value: '=' },
|
|
319
|
+
{ type: NUMBER, value: '9' },
|
|
320
|
+
{ type: FUNCTION, value: 'FOO' },
|
|
321
|
+
{ type: OPERATOR, value: '(' },
|
|
322
|
+
{ type: NUMBER, value: '1' },
|
|
323
|
+
{ type: OPERATOR, value: ')' }
|
|
324
|
+
]);
|
|
272
325
|
t.end();
|
|
273
326
|
});
|
|
274
327
|
|
|
@@ -277,9 +330,9 @@ test('tokenize numbers', t => {
|
|
|
277
330
|
{ type: FX_PREFIX, value: '=' },
|
|
278
331
|
{ type: NUMBER, value: '0' }
|
|
279
332
|
]);
|
|
280
|
-
t.isTokens('
|
|
333
|
+
t.isTokens('=+0', [
|
|
281
334
|
{ type: FX_PREFIX, value: '=' },
|
|
282
|
-
{ type: OPERATOR, value: '
|
|
335
|
+
{ type: OPERATOR, value: '+' },
|
|
283
336
|
{ type: NUMBER, value: '0' }
|
|
284
337
|
]);
|
|
285
338
|
t.isTokens('=+1', [
|
|
@@ -338,6 +391,231 @@ test('tokenize numbers', t => {
|
|
|
338
391
|
t.end();
|
|
339
392
|
});
|
|
340
393
|
|
|
394
|
+
test('tokenize negative numbers', t => {
|
|
395
|
+
t.isTokensNeg('=-0', [
|
|
396
|
+
{ type: FX_PREFIX, value: '=' },
|
|
397
|
+
{ type: NUMBER, value: '-0' }
|
|
398
|
+
]);
|
|
399
|
+
t.isTokensNeg('=-1123', [
|
|
400
|
+
{ type: FX_PREFIX, value: '=' },
|
|
401
|
+
{ type: NUMBER, value: '-1123' }
|
|
402
|
+
]);
|
|
403
|
+
t.isTokensNeg('=-1.5', [
|
|
404
|
+
{ type: FX_PREFIX, value: '=' },
|
|
405
|
+
{ type: NUMBER, value: '-1.5' }
|
|
406
|
+
]);
|
|
407
|
+
t.isTokensNeg('=-1234.5678', [
|
|
408
|
+
{ type: FX_PREFIX, value: '=' },
|
|
409
|
+
{ type: NUMBER, value: '-1234.5678' }
|
|
410
|
+
]);
|
|
411
|
+
t.isTokensNeg('=1E-1', [
|
|
412
|
+
{ type: FX_PREFIX, value: '=' },
|
|
413
|
+
{ type: NUMBER, value: '1E-1' }
|
|
414
|
+
]);
|
|
415
|
+
t.isTokensNeg('=-1E-1', [
|
|
416
|
+
{ type: FX_PREFIX, value: '=' },
|
|
417
|
+
{ type: NUMBER, value: '-1E-1' }
|
|
418
|
+
]);
|
|
419
|
+
t.isTokensNeg('=1.5E-10', [
|
|
420
|
+
{ type: FX_PREFIX, value: '=' },
|
|
421
|
+
{ type: NUMBER, value: '1.5E-10' }
|
|
422
|
+
]);
|
|
423
|
+
t.isTokensNeg('=-1.5E-10', [
|
|
424
|
+
{ type: FX_PREFIX, value: '=' },
|
|
425
|
+
{ type: NUMBER, value: '-1.5E-10' }
|
|
426
|
+
]);
|
|
427
|
+
t.isTokensNeg('-1', [
|
|
428
|
+
{ type: 'number', value: '-1' }
|
|
429
|
+
]);
|
|
430
|
+
|
|
431
|
+
//
|
|
432
|
+
t.isTokensNeg('=1-1', [
|
|
433
|
+
{ type: FX_PREFIX, value: '=' },
|
|
434
|
+
{ type: NUMBER, value: '1' },
|
|
435
|
+
{ type: OPERATOR, value: '-' },
|
|
436
|
+
{ type: NUMBER, value: '1' }
|
|
437
|
+
]);
|
|
438
|
+
t.isTokensNeg('1--1', [
|
|
439
|
+
{ type: 'number', value: '1' },
|
|
440
|
+
{ type: 'operator', value: '-' },
|
|
441
|
+
{ type: 'number', value: '-1' }
|
|
442
|
+
]);
|
|
443
|
+
t.isTokensNeg('1 - -1', [
|
|
444
|
+
{ type: 'number', value: '1' },
|
|
445
|
+
{ type: 'whitespace', value: ' ' },
|
|
446
|
+
{ type: 'operator', value: '-' },
|
|
447
|
+
{ type: 'whitespace', value: ' ' },
|
|
448
|
+
{ type: 'number', value: '-1' }
|
|
449
|
+
]);
|
|
450
|
+
t.isTokensNeg('1 - - 1', [
|
|
451
|
+
{ type: 'number', value: '1' },
|
|
452
|
+
{ type: 'whitespace', value: ' ' },
|
|
453
|
+
{ type: 'operator', value: '-' },
|
|
454
|
+
{ type: 'whitespace', value: ' ' },
|
|
455
|
+
{ type: 'operator', value: '-' },
|
|
456
|
+
{ type: 'whitespace', value: ' ' },
|
|
457
|
+
{ type: 'number', value: '1' }
|
|
458
|
+
]);
|
|
459
|
+
t.isTokensNeg('1 \n - \n -1', [
|
|
460
|
+
{ type: 'number', value: '1' },
|
|
461
|
+
{ type: 'whitespace', value: ' ' },
|
|
462
|
+
{ type: 'newline', value: '\n' },
|
|
463
|
+
{ type: 'whitespace', value: ' ' },
|
|
464
|
+
{ type: 'operator', value: '-' },
|
|
465
|
+
{ type: 'whitespace', value: ' ' },
|
|
466
|
+
{ type: 'newline', value: '\n' },
|
|
467
|
+
{ type: 'whitespace', value: ' ' },
|
|
468
|
+
{ type: 'number', value: '-1' }
|
|
469
|
+
]);
|
|
470
|
+
t.isTokensNeg('-(-1)', [
|
|
471
|
+
{ type: 'operator', value: '-' },
|
|
472
|
+
{ type: 'operator', value: '(' },
|
|
473
|
+
{ type: 'number', value: '-1' },
|
|
474
|
+
{ type: 'operator', value: ')' }
|
|
475
|
+
]);
|
|
476
|
+
t.isTokensNeg('-( -1 )', [
|
|
477
|
+
{ type: 'operator', value: '-' },
|
|
478
|
+
{ type: 'operator', value: '(' },
|
|
479
|
+
{ type: 'whitespace', value: ' ' },
|
|
480
|
+
{ type: 'number', value: '-1' },
|
|
481
|
+
{ type: 'whitespace', value: ' ' },
|
|
482
|
+
{ type: 'operator', value: ')' }
|
|
483
|
+
]);
|
|
484
|
+
|
|
485
|
+
t.isTokensNeg('=true-1', [
|
|
486
|
+
{ type: 'fx-prefix', value: '=' },
|
|
487
|
+
{ type: 'bool', value: 'true' },
|
|
488
|
+
{ type: 'operator', value: '-' },
|
|
489
|
+
{ type: 'number', value: '1' }
|
|
490
|
+
]);
|
|
491
|
+
t.isTokensNeg('=true -1', [
|
|
492
|
+
{ type: 'fx-prefix', value: '=' },
|
|
493
|
+
{ type: 'bool', value: 'true' },
|
|
494
|
+
{ type: 'whitespace', value: ' ' },
|
|
495
|
+
{ type: 'operator', value: '-' },
|
|
496
|
+
{ type: 'number', value: '1' }
|
|
497
|
+
]);
|
|
498
|
+
t.isTokensNeg('=true - 1', [
|
|
499
|
+
{ type: 'fx-prefix', value: '=' },
|
|
500
|
+
{ type: 'bool', value: 'true' },
|
|
501
|
+
{ type: 'whitespace', value: ' ' },
|
|
502
|
+
{ type: 'operator', value: '-' },
|
|
503
|
+
{ type: 'whitespace', value: ' ' },
|
|
504
|
+
{ type: 'number', value: '1' }
|
|
505
|
+
]);
|
|
506
|
+
t.isTokensNeg('=#VALUE!-1', [
|
|
507
|
+
{ type: 'fx-prefix', value: '=' },
|
|
508
|
+
{ type: 'error', value: '#VALUE!' },
|
|
509
|
+
{ type: 'operator', value: '-' },
|
|
510
|
+
{ type: 'number', value: '1' }
|
|
511
|
+
]);
|
|
512
|
+
t.isTokensNeg('=#VALUE! -1', [
|
|
513
|
+
{ type: 'fx-prefix', value: '=' },
|
|
514
|
+
{ type: 'error', value: '#VALUE!' },
|
|
515
|
+
{ type: 'whitespace', value: ' ' },
|
|
516
|
+
{ type: 'operator', value: '-' },
|
|
517
|
+
{ type: 'number', value: '1' }
|
|
518
|
+
]);
|
|
519
|
+
t.isTokensNeg('=SUM(-1) -1', [
|
|
520
|
+
{ type: 'fx-prefix', value: '=' },
|
|
521
|
+
{ type: 'function', value: 'SUM' },
|
|
522
|
+
{ type: 'operator', value: '(' },
|
|
523
|
+
{ type: 'number', value: '-1' },
|
|
524
|
+
{ type: 'operator', value: ')' },
|
|
525
|
+
{ type: 'whitespace', value: ' ' },
|
|
526
|
+
{ type: 'operator', value: '-' },
|
|
527
|
+
{ type: 'number', value: '1' }
|
|
528
|
+
]);
|
|
529
|
+
t.isTokensNeg('=SUM( -1)-1', [
|
|
530
|
+
{ type: 'fx-prefix', value: '=' },
|
|
531
|
+
{ type: 'function', value: 'SUM' },
|
|
532
|
+
{ type: 'operator', value: '(' },
|
|
533
|
+
{ type: 'whitespace', value: ' ' },
|
|
534
|
+
{ type: 'number', value: '-1' },
|
|
535
|
+
{ type: 'operator', value: ')' },
|
|
536
|
+
{ type: 'operator', value: '-' },
|
|
537
|
+
{ type: 'number', value: '1' }
|
|
538
|
+
]);
|
|
539
|
+
t.isTokensNeg('=A1-1', [
|
|
540
|
+
{ type: 'fx-prefix', value: '=' },
|
|
541
|
+
{ type: 'range', value: 'A1' },
|
|
542
|
+
{ type: 'operator', value: '-' },
|
|
543
|
+
{ type: 'number', value: '1' }
|
|
544
|
+
]);
|
|
545
|
+
t.isTokensNeg('=A1 -1', [
|
|
546
|
+
{ type: 'fx-prefix', value: '=' },
|
|
547
|
+
{ type: 'range', value: 'A1' },
|
|
548
|
+
{ type: 'whitespace', value: ' ' },
|
|
549
|
+
{ type: 'operator', value: '-' },
|
|
550
|
+
{ type: 'number', value: '1' }
|
|
551
|
+
]);
|
|
552
|
+
t.isTokensNeg('=foo-1', [
|
|
553
|
+
{ type: 'fx-prefix', value: '=' },
|
|
554
|
+
{ type: 'range-named', value: 'foo' },
|
|
555
|
+
{ type: 'operator', value: '-' },
|
|
556
|
+
{ type: 'number', value: '1' }
|
|
557
|
+
]);
|
|
558
|
+
t.isTokensNeg('=foo -1', [
|
|
559
|
+
{ type: 'fx-prefix', value: '=' },
|
|
560
|
+
{ type: 'range-named', value: 'foo' },
|
|
561
|
+
{ type: 'whitespace', value: ' ' },
|
|
562
|
+
{ type: 'operator', value: '-' },
|
|
563
|
+
{ type: 'number', value: '1' }
|
|
564
|
+
]);
|
|
565
|
+
t.isTokensNeg('="true"-1', [
|
|
566
|
+
{ type: 'fx-prefix', value: '=' },
|
|
567
|
+
{ type: 'string', value: '"true"' },
|
|
568
|
+
{ type: 'operator', value: '-' },
|
|
569
|
+
{ type: 'number', value: '1' }
|
|
570
|
+
]);
|
|
571
|
+
t.isTokensNeg('="true" -1', [
|
|
572
|
+
{ type: 'fx-prefix', value: '=' },
|
|
573
|
+
{ type: 'string', value: '"true"' },
|
|
574
|
+
{ type: 'whitespace', value: ' ' },
|
|
575
|
+
{ type: 'operator', value: '-' },
|
|
576
|
+
{ type: 'number', value: '1' }
|
|
577
|
+
]);
|
|
578
|
+
|
|
579
|
+
t.isTokensNeg('=SUM(1)-1', [
|
|
580
|
+
{ type: FX_PREFIX, value: '=' },
|
|
581
|
+
{ type: FUNCTION, value: 'SUM' },
|
|
582
|
+
{ type: OPERATOR, value: '(' },
|
|
583
|
+
{ type: NUMBER, value: '1' },
|
|
584
|
+
{ type: OPERATOR, value: ')' },
|
|
585
|
+
{ type: OPERATOR, value: '-' },
|
|
586
|
+
{ type: NUMBER, value: '1' }
|
|
587
|
+
]);
|
|
588
|
+
t.isTokensNeg('={1, 2, 3}-4', [
|
|
589
|
+
{ type: FX_PREFIX, value: '=' },
|
|
590
|
+
{ type: OPERATOR, value: '{' },
|
|
591
|
+
{ type: NUMBER, value: '1' },
|
|
592
|
+
{ type: OPERATOR, value: ',' },
|
|
593
|
+
{ type: WHITESPACE, value: ' ' },
|
|
594
|
+
{ type: NUMBER, value: '2' },
|
|
595
|
+
{ type: OPERATOR, value: ',' },
|
|
596
|
+
{ type: WHITESPACE, value: ' ' },
|
|
597
|
+
{ type: NUMBER, value: '3' },
|
|
598
|
+
{ type: OPERATOR, value: '}' },
|
|
599
|
+
{ type: OPERATOR, value: '-' },
|
|
600
|
+
{ type: NUMBER, value: '4' }
|
|
601
|
+
]);
|
|
602
|
+
t.isTokensNeg('=10%-1', [
|
|
603
|
+
{ type: FX_PREFIX, value: '=' },
|
|
604
|
+
{ type: NUMBER, value: '10' },
|
|
605
|
+
{ type: OPERATOR, value: '%' },
|
|
606
|
+
{ type: OPERATOR, value: '-' },
|
|
607
|
+
{ type: NUMBER, value: '1' }
|
|
608
|
+
]);
|
|
609
|
+
t.isTokensNeg('=A1#-1', [
|
|
610
|
+
{ type: FX_PREFIX, value: '=' },
|
|
611
|
+
{ type: RANGE, value: 'A1' },
|
|
612
|
+
{ type: OPERATOR, value: '#' },
|
|
613
|
+
{ type: OPERATOR, value: '-' },
|
|
614
|
+
{ type: NUMBER, value: '1' }
|
|
615
|
+
]);
|
|
616
|
+
t.end();
|
|
617
|
+
});
|
|
618
|
+
|
|
341
619
|
test('tokenize simple equations', t => {
|
|
342
620
|
t.isTokens('=1 + 2', [
|
|
343
621
|
{ type: FX_PREFIX, value: '=' },
|
|
@@ -700,6 +978,13 @@ test('tokenize A1 style references', t => {
|
|
|
700
978
|
{ type: RANGE_BEAM, value: 'AA:JJ' }
|
|
701
979
|
]);
|
|
702
980
|
|
|
981
|
+
t.isTokens('=XFD:XFF', [
|
|
982
|
+
{ type: FX_PREFIX, value: '=' },
|
|
983
|
+
{ type: RANGE_NAMED, value: 'XFD' },
|
|
984
|
+
{ type: OPERATOR, value: ':' },
|
|
985
|
+
{ type: RANGE_NAMED, value: 'XFF' }
|
|
986
|
+
]);
|
|
987
|
+
|
|
703
988
|
t.isTokens('=Sheetname!A1', [
|
|
704
989
|
{ type: FX_PREFIX, value: '=' },
|
|
705
990
|
{ type: RANGE, value: 'Sheetname!A1' }
|
|
@@ -852,12 +1137,11 @@ test('tokenize A1 style references', t => {
|
|
|
852
1137
|
{ type: RANGE, value: 'X4' }
|
|
853
1138
|
], { mergeRanges: false });
|
|
854
1139
|
|
|
855
|
-
// largest possible A1 ref
|
|
1140
|
+
// largest possible A1 ref (in Excel)
|
|
856
1141
|
t.isTokens('=XFD1048576', [
|
|
857
1142
|
{ type: FX_PREFIX, value: '=' },
|
|
858
1143
|
{ type: RANGE, value: 'XFD1048576' }
|
|
859
1144
|
]);
|
|
860
|
-
|
|
861
1145
|
t.isTokens('=XFD1048577', [
|
|
862
1146
|
{ type: FX_PREFIX, value: '=' },
|
|
863
1147
|
{ type: RANGE_NAMED, value: 'XFD1048577' }
|
|
@@ -1055,7 +1339,7 @@ test('tokenize strings', t => {
|
|
|
1055
1339
|
// so open ended strings at the end of output are tagged.
|
|
1056
1340
|
t.isTokens('="incomple', [
|
|
1057
1341
|
{ type: FX_PREFIX, value: '=' },
|
|
1058
|
-
{ type: STRING, value: '"incomple' }
|
|
1342
|
+
{ type: STRING, value: '"incomple', unterminated: true }
|
|
1059
1343
|
]);
|
|
1060
1344
|
|
|
1061
1345
|
t.end();
|
package/{src → lib}/lexer.js
RENAMED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FX_PREFIX,
|
|
3
|
+
NEWLINE,
|
|
4
|
+
NUMBER,
|
|
5
|
+
OPERATOR,
|
|
3
6
|
PATH_BRACE,
|
|
4
7
|
PATH_PREFIX,
|
|
5
8
|
PATH_QUOTE,
|
|
6
9
|
RANGE,
|
|
7
|
-
RANGE_NAMED,
|
|
8
10
|
RANGE_BEAM,
|
|
11
|
+
RANGE_NAMED,
|
|
12
|
+
STRING,
|
|
9
13
|
UNKNOWN,
|
|
14
|
+
WHITESPACE,
|
|
10
15
|
tokenHandlersA1,
|
|
11
16
|
tokenHandlersRC
|
|
12
17
|
} from './constants.js';
|
|
@@ -15,10 +20,22 @@ const isType = (t, type) => t && t.type === type;
|
|
|
15
20
|
const isRangeOp = t => t && t.value === ':';
|
|
16
21
|
const isBangOp = t => t && t.value === '!';
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
const defaultOptions = {
|
|
24
|
+
emitRanges: false,
|
|
25
|
+
mergeRanges: true,
|
|
26
|
+
negativeNumbers: false,
|
|
27
|
+
r1c1: false
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function getTokens (fx, tokenHandlers, options = {}) {
|
|
31
|
+
const { emitRanges, mergeRanges, negativeNumbers } = Object.assign({}, defaultOptions, options);
|
|
19
32
|
const tokens = [];
|
|
20
33
|
let pos = 0;
|
|
21
34
|
const lookBehind = n => tokens[tokens.length - n];
|
|
35
|
+
const lookBehindIgnoreWS = n => {
|
|
36
|
+
const noWs = tokens.filter(t => !isType(t, WHITESPACE) && !isType(t, NEWLINE));
|
|
37
|
+
return noWs[noWs.length - n];
|
|
38
|
+
};
|
|
22
39
|
|
|
23
40
|
if (/^=/.test(fx)) {
|
|
24
41
|
const token = {
|
|
@@ -58,6 +75,23 @@ export function getTokens (fx, tokenHandlers = [], emitRanges = false, mergeRang
|
|
|
58
75
|
...(emitRanges ? { range: [ startPos, pos ] } : {})
|
|
59
76
|
};
|
|
60
77
|
|
|
78
|
+
if (tokenType === STRING && !tokenValue.endsWith('"')) {
|
|
79
|
+
token.unterminated = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (negativeNumbers && tokenType === NUMBER) {
|
|
83
|
+
const last1 = lookBehind(1);
|
|
84
|
+
if (last1 && isType(last1, OPERATOR) && last1.value === '-') {
|
|
85
|
+
// we have a number preceded by a minus
|
|
86
|
+
const last2 = lookBehindIgnoreWS(2);
|
|
87
|
+
// missing last2 means we are at the start of the stream
|
|
88
|
+
if (!last2 || isType(last2, FX_PREFIX) || (isType(last2, OPERATOR) && ![ '%', '}', ')', '#' ].includes(last2.value))) {
|
|
89
|
+
tokens.pop();
|
|
90
|
+
token.value = '-' + tokenValue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
61
95
|
if (mergeRanges) {
|
|
62
96
|
if (tokenType === RANGE || tokenType === RANGE_NAMED || tokenType === RANGE_BEAM) {
|
|
63
97
|
const merge = [];
|
|
@@ -94,7 +128,7 @@ export function getTokens (fx, tokenHandlers = [], emitRanges = false, mergeRang
|
|
|
94
128
|
|
|
95
129
|
// Formulas can either have RC or A1 style refs, not both: because C1 and R1 are both!
|
|
96
130
|
// Refmode: A1 | RC | Anostic emit ranges with RANGE
|
|
97
|
-
export function tokenize (fx,
|
|
98
|
-
const tokenHandlers = r1c1 ? tokenHandlersRC : tokenHandlersA1;
|
|
99
|
-
return getTokens(fx, tokenHandlers,
|
|
131
|
+
export function tokenize (fx, options = {}) {
|
|
132
|
+
const tokenHandlers = options.r1c1 ? tokenHandlersRC : tokenHandlersA1;
|
|
133
|
+
return getTokens(fx, tokenHandlers, options);
|
|
100
134
|
}
|
package/lib/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "module" }
|
package/{src → lib}/parseRef.js
RENAMED
|
@@ -51,7 +51,10 @@ const validRunsNamed = validRuns.concat([
|
|
|
51
51
|
]);
|
|
52
52
|
|
|
53
53
|
export function parseRef (ref, allow_named = true, tokenHandlers = []) {
|
|
54
|
-
const tokens = getTokens(ref, tokenHandlers,
|
|
54
|
+
const tokens = getTokens(ref, tokenHandlers, {
|
|
55
|
+
emitRanges: false,
|
|
56
|
+
mergeRanges: false
|
|
57
|
+
});
|
|
55
58
|
const refData = {
|
|
56
59
|
sheetName: '',
|
|
57
60
|
workbookName: '',
|
|
File without changes
|
package/{src → lib}/rc-test.js
RENAMED
|
File without changes
|
package/{src → lib}/rc.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/{src → lib}/translate.js
RENAMED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,38 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@borgar/fx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Utilities for working with Excel formulas",
|
|
5
|
-
"main": "
|
|
6
|
-
"
|
|
5
|
+
"main": "dist/fx.js",
|
|
6
|
+
"module": "lib/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/fx.js",
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
7
13
|
"scripts": {
|
|
8
|
-
"lint": "eslint index.js
|
|
9
|
-
"test": "tape
|
|
14
|
+
"lint": "eslint index.js lib/*.js",
|
|
15
|
+
"test": "tape lib/*-test.js | tap-min",
|
|
16
|
+
"build": "NODE_ENV=production rollup -c"
|
|
10
17
|
},
|
|
11
18
|
"repository": {
|
|
12
19
|
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/borgar/
|
|
20
|
+
"url": "git+https://github.com/borgar/fx.git"
|
|
14
21
|
},
|
|
15
22
|
"bugs": {
|
|
16
|
-
"url": "https://github.com/borgar/
|
|
23
|
+
"url": "https://github.com/borgar/fx/issues"
|
|
17
24
|
},
|
|
25
|
+
"browserslist": [
|
|
26
|
+
"defaults",
|
|
27
|
+
"not IE 11",
|
|
28
|
+
"maintained node versions"
|
|
29
|
+
],
|
|
18
30
|
"keywords": [
|
|
19
31
|
"excel",
|
|
20
|
-
"json",
|
|
21
32
|
"xlsx",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"spreadsheet",
|
|
25
|
-
"workbook"
|
|
33
|
+
"formula",
|
|
34
|
+
"spreadsheet"
|
|
26
35
|
],
|
|
27
36
|
"author": "Borgar Þorsteinsson <borgar@borgar.net> (http://borgar.net/)",
|
|
28
37
|
"license": "MIT",
|
|
29
38
|
"devDependencies": {
|
|
30
|
-
"@babel/core": "~7.
|
|
31
|
-
"@babel/eslint-parser": "~7.
|
|
39
|
+
"@babel/core": "~7.18.13",
|
|
40
|
+
"@babel/eslint-parser": "~7.18.9",
|
|
41
|
+
"@babel/preset-env": "~7.18.10",
|
|
32
42
|
"@borgar/eslint-config": "~2.2.1",
|
|
43
|
+
"@rollup/plugin-babel": "~5.3.1",
|
|
33
44
|
"babel-eslint": "~10.1.0",
|
|
34
|
-
"eslint": "~
|
|
45
|
+
"eslint": "~8.23.0",
|
|
46
|
+
"rollup": "~2.79.0",
|
|
35
47
|
"tap-min": "~2.0.0",
|
|
36
|
-
"tape": "~5.
|
|
48
|
+
"tape": "~5.6.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"rollup-plugin-terser": "~7.0.2"
|
|
37
52
|
}
|
|
38
53
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import babel from '@rollup/plugin-babel';
|
|
2
|
+
import { terser } from 'rollup-plugin-terser';
|
|
3
|
+
import pkg from './package.json';
|
|
4
|
+
|
|
5
|
+
const isProd = process.env.NODE_ENV === 'production';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
input: pkg.module,
|
|
9
|
+
plugins: [
|
|
10
|
+
babel({
|
|
11
|
+
babelHelpers: 'bundled',
|
|
12
|
+
presets: [ '@babel/preset-env' ]
|
|
13
|
+
})
|
|
14
|
+
],
|
|
15
|
+
output: {
|
|
16
|
+
file: pkg.main,
|
|
17
|
+
format: 'cjs',
|
|
18
|
+
sourcemap: 'inline',
|
|
19
|
+
plugins: [ isProd && terser() ]
|
|
20
|
+
}
|
|
21
|
+
};
|
package/src/addMeta-test.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { test, Test } from 'tape';
|
|
2
|
-
import { FX_PREFIX, OPERATOR, NUMBER, RANGE, RANGE_BEAM } from './constants.js';
|
|
3
|
-
import { addMeta } from './addMeta.js';
|
|
4
|
-
import { tokenize } from './lexer.js';
|
|
5
|
-
|
|
6
|
-
Test.prototype.isMetaTokens = function isTokens (expr, result, opts) {
|
|
7
|
-
this.deepEqual(addMeta(tokenize(expr), opts), result, expr);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
test('add extra meta to operators', t => {
|
|
11
|
-
// parens should be grouped and tagged with depth
|
|
12
|
-
t.isMetaTokens('=((1)+(1))', [
|
|
13
|
-
{ type: FX_PREFIX, value: '=' },
|
|
14
|
-
{ type: OPERATOR, value: '(', depth: 0, groupId: 'fxg3' },
|
|
15
|
-
{ type: OPERATOR, value: '(', depth: 1, groupId: 'fxg1' },
|
|
16
|
-
{ type: NUMBER, value: '1' },
|
|
17
|
-
{ type: OPERATOR, value: ')', depth: 1, groupId: 'fxg1' },
|
|
18
|
-
{ type: OPERATOR, value: '+' },
|
|
19
|
-
{ type: OPERATOR, value: '(', depth: 1, groupId: 'fxg2' },
|
|
20
|
-
{ type: NUMBER, value: '1' },
|
|
21
|
-
{ type: OPERATOR, value: ')', depth: 1, groupId: 'fxg2' },
|
|
22
|
-
{ type: OPERATOR, value: ')', depth: 0, groupId: 'fxg3' }
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
// don't be fooled by imbalanced parens
|
|
26
|
-
t.isMetaTokens('=)())', [
|
|
27
|
-
{ type: FX_PREFIX, value: '=' },
|
|
28
|
-
{ type: OPERATOR, value: ')', error: true },
|
|
29
|
-
{ type: OPERATOR, value: '(', depth: 0, groupId: 'fxg1' },
|
|
30
|
-
{ type: OPERATOR, value: ')', depth: 0, groupId: 'fxg1' },
|
|
31
|
-
{ type: OPERATOR, value: ')', error: true }
|
|
32
|
-
]);
|
|
33
|
-
|
|
34
|
-
// don't be fooled by nested curlys
|
|
35
|
-
t.isMetaTokens('={{}}', [
|
|
36
|
-
{ type: FX_PREFIX, value: '=' },
|
|
37
|
-
{ type: OPERATOR, value: '{', groupId: 'fxg1' },
|
|
38
|
-
{ type: OPERATOR, value: '{', error: true },
|
|
39
|
-
{ type: OPERATOR, value: '}', groupId: 'fxg1' },
|
|
40
|
-
{ type: OPERATOR, value: '}', error: true }
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
// group ranges if they are equivalent
|
|
44
|
-
t.isMetaTokens("=B11,B11:B12,'Sheet11'!B11,SHEET1!$B11,sheet1!$b$11,A1:B11,[foo]Sheet1!B11,'[foo]Sheet1'!B11", [
|
|
45
|
-
{ type: FX_PREFIX, value: '=' },
|
|
46
|
-
{ type: RANGE, value: 'B11', groupId: 'fxg1' },
|
|
47
|
-
{ type: OPERATOR, value: ',' },
|
|
48
|
-
{ type: RANGE, value: 'B11:B12', groupId: 'fxg2' },
|
|
49
|
-
{ type: OPERATOR, value: ',' },
|
|
50
|
-
{ type: RANGE, value: "'Sheet11'!B11", groupId: 'fxg3' },
|
|
51
|
-
{ type: OPERATOR, value: ',' },
|
|
52
|
-
{ type: RANGE, value: 'SHEET1!$B11', groupId: 'fxg1' },
|
|
53
|
-
{ type: OPERATOR, value: ',' },
|
|
54
|
-
{ type: RANGE, value: 'sheet1!$b$11', groupId: 'fxg1' },
|
|
55
|
-
{ type: OPERATOR, value: ',' },
|
|
56
|
-
{ type: RANGE, value: 'A1:B11', groupId: 'fxg4' },
|
|
57
|
-
{ type: OPERATOR, value: ',' },
|
|
58
|
-
{ type: RANGE, value: '[foo]Sheet1!B11', groupId: 'fxg1' },
|
|
59
|
-
{ type: OPERATOR, value: ',' },
|
|
60
|
-
{ type: RANGE, value: "'[foo]Sheet1'!B11", groupId: 'fxg1' }
|
|
61
|
-
], { sheetName: 'Sheet1', workbookName: 'foo' });
|
|
62
|
-
|
|
63
|
-
t.isMetaTokens('=A:A,1:1,Sheet1!A:A:1:1,[foo]Sheet1!1:1', [
|
|
64
|
-
{ type: FX_PREFIX, value: '=' },
|
|
65
|
-
{ type: RANGE_BEAM, value: 'A:A', groupId: 'fxg1' },
|
|
66
|
-
{ type: OPERATOR, value: ',' },
|
|
67
|
-
{ type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
|
|
68
|
-
{ type: OPERATOR, value: ',' },
|
|
69
|
-
{ type: RANGE_BEAM, value: 'Sheet1!A:A', groupId: 'fxg1' },
|
|
70
|
-
{ type: OPERATOR, value: ':' },
|
|
71
|
-
{ type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
|
|
72
|
-
{ type: OPERATOR, value: ',' },
|
|
73
|
-
{ type: RANGE_BEAM, value: '[foo]Sheet1!1:1', groupId: 'fxg2' }
|
|
74
|
-
], { sheetName: 'Sheet1', workbookName: 'foo' });
|
|
75
|
-
|
|
76
|
-
t.end();
|
|
77
|
-
});
|