Subversion Repositories pentevo

Rev

Rev 1080 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.  
  4. <head>
  5.     <meta charset="UTF-8">
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7.     <title></title>
  8.     <style type="text/css">
  9.         html,
  10.         body {
  11.             margin: 0px;
  12.             height: 100%;
  13.             font-family: Verdana, sans-serif;
  14.         }
  15.        
  16.         .divtopmost {
  17.             width: 100%;
  18.             height: 100%;
  19.             background-color: #eee;
  20.             color: #252c30;
  21.         }
  22.        
  23.         .split {
  24.             -webkit-box-sizing: border-box;
  25.             -moz-box-sizing: border-box;
  26.             box-sizing: border-box;
  27.             overflow-y: auto;
  28.             overflow-x: hidden;
  29.             background-color: inherit;
  30.         }
  31.        
  32.         .gutter {
  33.             background-color: #ddd;
  34.             background-repeat: no-repeat;
  35.             background-position: 50%;
  36.             transition: background-color 0.3s;
  37.         }
  38.        
  39.         .split.split-horizontal {
  40.             height: 100%;
  41.             float: left;
  42.         }
  43.        
  44.         .gutter.gutter-horizontal {
  45.             height: 100%;
  46.             float: left;
  47.             background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
  48.             cursor: col-resize;
  49.         }
  50.        
  51.         .gutter.gutter-vertical {
  52.             width: 100%;
  53.             background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
  54.             cursor: row-resize;
  55.         }
  56.        
  57.         #divtop {
  58.             height: 78px;
  59.             border-bottom: 2px solid black;
  60.         }
  61.        
  62.         .boardinfo {
  63.             width: 100%;
  64.             height: 100%;
  65.             border: none;
  66.             padding: 5px;
  67.         }
  68.        
  69.         .boardinfo td {
  70.             overflow: hidden;
  71.             white-space: nowrap;
  72.             width: 50%;
  73.             text-align: center;
  74.             text-overflow: ellipsis;
  75.         }
  76.        
  77.         .boardinfo .title {
  78.             font-size: 20pt;
  79.             font-weight: bold;
  80.         }
  81.        
  82.         .boardinfo .variant {
  83.             font-size: 14pt;
  84.             color: #888;
  85.             display: none;
  86.         }
  87.         /* bom table */
  88.        
  89.         .bom {
  90.             border-collapse: collapse;
  91.             font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  92.             font-size: 10pt;
  93.             table-layout: fixed;
  94.             width: 100%;
  95.             margin-top: 1px;
  96.         }
  97.        
  98.         .bom th,
  99.         .bom td {
  100.             border: 1px solid black;
  101.             padding: 5px;
  102.             word-wrap: break-word;
  103.             text-align: center;
  104.             position: relative;
  105.         }
  106.        
  107.         .bom th {
  108.             background-color: #CCCCCC;
  109.             background-clip: padding-box;
  110.             cursor: pointer;
  111.         }
  112.        
  113.         .bom tr {
  114.             transition: background-color 0.2s;
  115.         }
  116.        
  117.         .bom tr:nth-child(even) {
  118.             background-color: #f2f2f2;
  119.         }
  120.        
  121.         .bom tr.active:nth-child(n) {
  122.             background-color: #00abff;
  123.             color: #eee;
  124.             font-weight: bold;
  125.         }
  126.        
  127.         .bom tr.active:nth-child(even) {
  128.             background-color: #00abff;
  129.             color: #eee;
  130.             font-weight: bold;
  131.         }
  132.        
  133.         .bom .active {
  134.             background-color: #00abff;
  135.             color: #eee;
  136.             font-weight: bold;
  137.         }
  138.        
  139.         .bom tr.checked {
  140.             color: #aaa;
  141.         }
  142.        
  143.         .bom .numcol {
  144.             width: 25px;
  145.         }
  146.        
  147.         .bom .bom-checkbox {
  148.             width: 50px;
  149.             position: relative;
  150.             user-select: none;
  151.             -moz-user-select: none;
  152.         }
  153.        
  154.         .bom .bom-checkbox:before {
  155.             content: "";
  156.             position: absolute;
  157.             border-width: 15px;
  158.             border-style: solid;
  159.             border-color: #51829f transparent transparent transparent;
  160.             visibility: hidden;
  161.             top: -15px;
  162.         }
  163.        
  164.         .bom .bom-checkbox:after {
  165.             content: "Double click to set/unset all";
  166.             position: absolute;
  167.             color: white;
  168.             top: -35px;
  169.             left: -26px;
  170.             background: #51829f;
  171.             padding: 5px 15px;
  172.             border-radius: 8px;
  173.             white-space: nowrap;
  174.             visibility: hidden;
  175.         }
  176.        
  177.         .bom .value {
  178.             width: 15%;
  179.         }
  180.        
  181.         .bom .quantity {
  182.             width: 65px;
  183.         }
  184.        
  185.         .bom .placed {
  186.             font-size: 8pt;
  187.             color: #b87333;
  188.             display: inline;
  189.         }
  190.         /* prefs menu */
  191.        
  192.         .prefs_menu {
  193.             position: relative;
  194.             display: inline-block;
  195.             margin: 10px 10px 10px 0px;
  196.         }
  197.        
  198.         .prefs_menu:hover {
  199.             display: block;
  200.             background-color: #eee;
  201.         }
  202.        
  203.         .prefs_menubtn {
  204.             background-color: white;
  205.             border: none;
  206.             background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36' viewBox='0 0 20 20'%3E%3Cpath fill='none' d='M0 0h20v20H0V0z'/%3E%3Cpath d='M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z'/%3E%3C/svg%3E%0A");
  207.             background-position: center;
  208.             background-repeat: no-repeat;
  209.         }
  210.        
  211.         .prefs_menu_content {
  212.             display: none;
  213.             position: absolute;
  214.             background-color: white;
  215.             right: 0;
  216.             min-width: 300px;
  217.             box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  218.             z-index: 100;
  219.             padding: 8px;
  220.         }
  221.        
  222.         .prefs_menu:hover .prefs_menubtn {
  223.             background-color: #eee;
  224.         }
  225.        
  226.         .prefs_menu:hover .prefs_menu_content {
  227.             display: block;
  228.         }
  229.        
  230.         .prefs_menu_label {
  231.             display: inline-block;
  232.             padding: 8px;
  233.             border: 1px solid #ccc;
  234.             border-top: 0;
  235.             width: calc(100% - 18px);
  236.         }
  237.        
  238.         .prefs_menu_label_top {
  239.             border-top: 1px solid #ccc;
  240.         }
  241.        
  242.         .version {
  243.             float: right;
  244.             font-size: 10pt;
  245.             color: #888;
  246.         }
  247.        
  248.         .slider {
  249.             width: 100%;
  250.         }
  251.         /* buttons menu */
  252.        
  253.         .button_container {
  254.             font-size: 0;
  255.             margin: 10px 10px 10px 0px;
  256.         }
  257.        
  258.         button {
  259.             background-color: #eee;
  260.             border: 1px solid #888;
  261.             color: black;
  262.             height: 44px;
  263.             width: 44px;
  264.             text-align: center;
  265.             text-decoration: none;
  266.             display: inline-block;
  267.             font-size: 14px;
  268.             font-weight: bolder;
  269.         }
  270.        
  271.         button:focus {
  272.             outline: 0;
  273.         }
  274.        
  275.         button.selected {
  276.             background-color: #007bff;
  277.             color: white;
  278.         }
  279.        
  280.         .button_container button {
  281.             background-size: 32px 32px;
  282.             background-position: 5px 5px;
  283.             background-repeat: no-repeat;
  284.         }
  285.        
  286.         .left_most_button {
  287.             border-right: 0;
  288.             border-top-left-radius: 6px;
  289.             border-bottom-left-radius: 6px;
  290.         }
  291.        
  292.         .middle_button {
  293.             border-right: 0;
  294.         }
  295.        
  296.         .right_most_button {
  297.             border-top-right-radius: 6px;
  298.             border-bottom-right-radius: 6px;
  299.         }
  300.         /* canvas */
  301.        
  302.         canvas {
  303.             cursor: crosshair;
  304.         }
  305.        
  306.         canvas:active {
  307.             cursor: grabbing;
  308.         }
  309.         /* nets */
  310.        
  311.         .net_inverse {
  312.             text-decoration: overline;
  313.         }
  314.     </style>
  315. </head>
  316.  
  317. <body>
  318.     <div id="divtopmost" class="divtopmost">
  319.         <div id="divtop">
  320.             <div style="float: right; height: 100%;">
  321.                 <!-- prefs menu -->
  322.                 <div class="prefs_menu" style="float: right; top: 8px;">
  323.                     <button class="prefs_menubtn"></button>
  324.                     <div class="prefs_menu_content">
  325.                         <!-- display -->
  326.                         <div class="prefs_menu_label prefs_menu_label_top">
  327.                             <div style="text-align: center; margin-bottom: 4px;">Display</div>
  328.                             <label class="prefs_menu_label prefs_menu_label_top">
  329.                                 <input id="cbDisplayAssy" type="checkbox" onchange="setDisplayAssy(this.checked)" checked>
  330.                                 <label for="cbDisplayAssy">Assembly</label>
  331.                             </label>
  332.                             <label class="prefs_menu_label">
  333.                                 <input id="cbDisplaySilk" type="checkbox" onchange="setDisplaySilk(this.checked)" checked>
  334.                                 <label for="cbDisplaySilk">Silkscreen</label>
  335.                             </label>
  336.                             <label class="prefs_menu_label">
  337.                                 <input id="cbDisplayNets" type="checkbox" onchange="setDisplayNets(this.checked)" checked>
  338.                                 <label for="cbDisplayNets">Nets</label>
  339.                             </label>
  340.                             <label class="prefs_menu_label">
  341.                                 <input id="cbDisplayCopperPours" type="checkbox" onchange="setDisplayCopperPours(this.checked)">
  342.                                 <label for="cbDisplayCopperPours">Copper Pours</label>
  343.                             </label>
  344.                             <label class="prefs_menu_label">
  345.                                 <input id="cbDisplayFiducials" type="checkbox" onchange="setDisplayFiducials(this.checked)" checked>
  346.                                 <label for="cbDisplayFiducials">Fiducials</label>
  347.                             </label>
  348.                             <label class="prefs_menu_label">
  349.                                 <input id="cbDisplayPads" type="checkbox" onchange="setDisplayPads(this.checked)" checked>
  350.                                 <label for="cbDisplayPads">Pads</label>
  351.                             </label>
  352.                             <label class="prefs_menu_label">
  353.                                 <input id="cbDisplayVias" type="checkbox" onchange="setDisplayVias(this.checked)" checked>
  354.                                 <label for="cbDisplayVias">Vias</label>
  355.                             </label>
  356.                             <label class="prefs_menu_label">
  357.                                 <input id="cbDisplaySuppliers" type="checkbox" onchange="setDisplaySuppliers(this.checked)" checked>
  358.                                 <label for="cbDisplaySuppliers">Suppliers</label>
  359.                             </label>
  360.                         </div>
  361.                         <!-- board rotation -->
  362.                         <div class="prefs_menu_label">
  363.                             <label>
  364.                                 <span>Board rotation</span><span style="float: right;"><span id="boardRotationDegree">0</span>&deg;</span>
  365.                                 <input id="boardRotation" class="slider" type="range" min="-36" max="36" value="0" oninput="setBoardRotation(this.value)" onchange="setBoardRotation(this.value)">
  366.                             </label>
  367.                         </div>
  368.                         <div class="prefs_menu_label">
  369.                             <label><span id="version" class="version"></span></label>
  370.                         </div>
  371.                     </div>
  372.                 </div>
  373.                 <!-- canvas layout menu -->
  374.                 <div class="button_container" style="float: right; position: relative; top: 8px">
  375.                     <button id="btnCanvasTop" class="left_most_button" onclick="changeCanvasLayout('T')" title="Top Only">T</button>
  376.                     <button id="btnCanvasTopBottom" class="middle_button selected" onclick="changeCanvasLayout('TB')" title="Top and Bottom">TB</button>
  377.                     <button id="btnCanvasBottom" class="right_most_button" onclick="changeCanvasLayout('B')" title="Bottom Only">B</button>
  378.                 </div>
  379.                 <!-- bom layout menu -->
  380.                 <div class="button_container" style="float: right; position: relative; top: 8px">
  381.                     <button id="btnBOMOnly" class="left_most_button" onclick="changeBOMLayout('bom-only')" title="BOM Only">BOM</button>
  382.                     <button id="btnBOMLeftRight" class="middle_button" onclick="changeBOMLayout('left-right')" title="BOM - Left, Drawing - Right">LR</button>
  383.                     <button id="btnBOMTopBottom" class="right_most_button" onclick="changeBOMLayout('top-bottom')" title="BOM - Top, Drawing - Bottom">TB</button>
  384.                 </div>
  385.                 <!-- bom group menu -->
  386.                 <div class="button_container" style="float: right; position: relative; top: 8px">
  387.                     <button id="btnGUngroup" class="left_most_button selected" onclick="changeBomGroup('U')" title="Ungroup">U</button>
  388.                     <button id="btnGNetlist" class="middle_button" onclick="changeBomGroup('NL')" title="Netlist">NL</button>
  389.                     <button id="btnGName" class="middle_button" onclick="changeBomGroup('N')" title="Component Name">N</button>
  390.                     <button id="btnGNameValue" class="middle_button" onclick="changeBomGroup('NV')" title="Component Name and Value">NV</button>
  391.                     <button id="btnGNamePattern" class="middle_button" onclick="changeBomGroup('NP')" title="Component Name and Pattern">NP</button>
  392.                     <button id="btnGNameValuePattern" class="right_most_button" onclick="changeBomGroup('NVP')" title="Component Name, Value and Pattern">NVP</button>
  393.                 </div>
  394.             </div>
  395.             <div id="boardinfo" style="height: 100%; overflow: auto;">
  396.                 <table class="boardinfo">
  397.                     <tbody>
  398.                         <tr>
  399.                             <td id="board_name" class="title"></td>
  400.                         </tr>
  401.                         <tr>
  402.                             <td id="assembly_variant" class="variant"></td>
  403.                         </tr>
  404.                     </tbody>
  405.                 </table>
  406.             </div>
  407.         </div>
  408.         <div id="divbottom" class="split" style="height: calc(100% - 80px);">
  409.             <div id="divbom" class="split split-horizontal" style="width: calc(50% - 3px);">
  410.                 <!-- search -->
  411.                 <div style="width: 100%;"></div>
  412.                 <!-- table -->
  413.                 <table class="bom">
  414.                     <thead id="tblhead">
  415.                         <tr>
  416.                             <th class="numcol"></th>
  417.                             <th class="bom-checkbox">Placed</th>
  418.                             <th>Reference(s)</th>
  419.                             <th>Name</th>
  420.                             <th class="value">Value</th>
  421.                             <th>Pattern</th>
  422.                             <th class="quantity">Quantity</th>
  423.                         </tr>
  424.                     </thead>
  425.                     <tbody id="tblbody">
  426.                         <tr id="bomrow1">
  427.                             <td>1</td>
  428.                             <td><input type="checkbox" /></td>
  429.                             <td></td>
  430.                             <td></td>
  431.                             <td></td>
  432.                             <td></td>
  433.                             <td></td>
  434.                         </tr>
  435.                     </tbody>
  436.                 </table>
  437.             </div>
  438.             <div class="gutter gutter-horizontal" style="width: 6px;"></div>
  439.             <div id="divcanvas" class="split split-horizontal" style="width: calc(50% - 3px);">
  440.                 <div id="topcanvas" class="split" touch-action="none" style="overflow: hidden; height: calc(50% - 3px);">
  441.                     <div style="position: relative; width: 100%; height: 100%;">
  442.                         <canvas id="topBG" style="position: absolute; left: 0px; top: 0px; z-index: 0; width: 800px; height: 600px;" width="800" height="600"></canvas>
  443.                         <canvas id="topSILK" style="position: absolute; left: 0px; top: 0px; z-index: 1; width: 800px; height: 600px;" width="800" height="600"></canvas>
  444.                         <canvas id="topASSY" style="position: absolute; left: 0px; top: 0px; z-index: 2; width: 800px; height: 600px;" width="800" height="600"></canvas>
  445.                         <canvas id="topHL" style="position: absolute; left: 0px; top: 0px; z-index: 3; width: 800px; height: 600px;" width="800" height="600"></canvas>
  446.                     </div>
  447.                 </div>
  448.                 <div class="gutter gutter-vertical" style="height: 6px;"></div>
  449.                 <div id="bottomcanvas" class="split" touch-action="none" style="overflow: hidden; height: calc(50% - 3px);">
  450.                     <div style="position: relative; width: 100%; height: 100%;">
  451.                         <canvas id="bottomBG" style="position: absolute; left: 0px; top: 0px; z-index: 0; width: 800px; height: 600px;" width="800" height="600"></canvas>
  452.                         <canvas id="bottomSILK" style="position: absolute; left: 0px; top: 0px; z-index: 1; width: 800px; height: 600px;" width="800" height="600"></canvas>
  453.                         <canvas id="bottomASSY" style="position: absolute; left: 0px; top: 0px; z-index: 2; width: 800px; height: 600px;" width="800" height="600"></canvas>
  454.                         <canvas id="bottomHL" style="position: absolute; left: 0px; top: 0px; z-index: 3; width: 800px; height: 600px;" width="800" height="600"></canvas>
  455.                     </div>
  456.                 </div>
  457.             </div>
  458.         </div>
  459.     </div>
  460.     <script type="text/javascript">
  461.         /*--- 3D party ---*/
  462.  
  463.         /* Split.js - v1.6.2 MIT License https://github.com/nathancahill/Split.js */
  464.         ! function(e, t) {
  465.             "object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e = e || self).Split = t()
  466.         }(this, (function() {
  467.             "use strict";
  468.             var e = "undefined" != typeof window ? window : null,
  469.                 t = null === e,
  470.                 n = t ? void 0 : e.document,
  471.                 i = function() {
  472.                     return !1
  473.                 },
  474.                 r = t ? "calc" : ["", "-webkit-", "-moz-", "-o-"].filter((function(e) {
  475.                     var t = n.createElement("div");
  476.                     return t.style.cssText = "width:" + e + "calc(9px)", !!t.style.length
  477.                 })).shift() + "calc",
  478.                 s = function(e) {
  479.                     return "string" == typeof e || e instanceof String
  480.                 },
  481.                 o = function(e) {
  482.                     if (s(e)) {
  483.                         var t = n.querySelector(e);
  484.                         if (!t) throw new Error("Selector " + e + " did not match a DOM element");
  485.                         return t
  486.                     }
  487.                     return e
  488.                 },
  489.                 a = function(e, t, n) {
  490.                     var i = e[t];
  491.                     return void 0 !== i ? i : n
  492.                 },
  493.                 u = function(e, t, n, i) {
  494.                     if (t) {
  495.                         if ("end" === i) return 0;
  496.                         if ("center" === i) return e / 2
  497.                     } else if (n) {
  498.                         if ("start" === i) return 0;
  499.                         if ("center" === i) return e / 2
  500.                     }
  501.                     return e
  502.                 },
  503.                 l = function(e, t) {
  504.                     var i = n.createElement("div");
  505.                     return i.className = "gutter gutter-" + t, i
  506.                 },
  507.                 c = function(e, t, n) {
  508.                     var i = {};
  509.                     return s(t) ? i[e] = t : i[e] = r + "(" + t + "% - " + n + "px)", i
  510.                 },
  511.                 h = function(e, t) {
  512.                     var n;
  513.                     return (n = {})[e] = t + "px", n
  514.                 };
  515.             return function(r, s) {
  516.                 if (void 0 === s && (s = {}), t) return {};
  517.                 var d, f, v, m, g, p, y = r;
  518.                 Array.from && (y = Array.from(y));
  519.                 var z = o(y[0]).parentNode,
  520.                     b = getComputedStyle ? getComputedStyle(z) : null,
  521.                     E = b ? b.flexDirection : null,
  522.                     S = a(s, "sizes") || y.map((function() {
  523.                         return 100 / y.length
  524.                     })),
  525.                     L = a(s, "minSize", 100),
  526.                     _ = Array.isArray(L) ? L : y.map((function() {
  527.                         return L
  528.                     })),
  529.                     w = a(s, "expandToMin", !1),
  530.                     k = a(s, "gutterSize", 10),
  531.                     x = a(s, "gutterAlign", "center"),
  532.                     C = a(s, "snapOffset", 30),
  533.                     M = a(s, "dragInterval", 1),
  534.                     U = a(s, "direction", "horizontal"),
  535.                     O = a(s, "cursor", "horizontal" === U ? "col-resize" : "row-resize"),
  536.                     D = a(s, "gutter", l),
  537.                     A = a(s, "elementStyle", c),
  538.                     B = a(s, "gutterStyle", h);
  539.  
  540.                 function j(e, t, n, i) {
  541.                     var r = A(d, t, n, i);
  542.                     Object.keys(r).forEach((function(t) {
  543.                         e.style[t] = r[t]
  544.                     }))
  545.                 }
  546.  
  547.                 function F() {
  548.                     return p.map((function(e) {
  549.                         return e.size
  550.                     }))
  551.                 }
  552.  
  553.                 function R(e) {
  554.                     return "touches" in e ? e.touches[0][f] : e[f]
  555.                 }
  556.  
  557.                 function T(e) {
  558.                     var t = p[this.a],
  559.                         n = p[this.b],
  560.                         i = t.size + n.size;
  561.                     t.size = e / this.size * i, n.size = i - e / this.size * i, j(t.element, t.size, this._b, t.i), j(n.element, n.size, this._c, n.i)
  562.                 }
  563.  
  564.                 function N(e) {
  565.                     var t, n = p[this.a],
  566.                         r = p[this.b];
  567.                     this.dragging && (t = R(e) - this.start + (this._b - this.dragOffset), M > 1 && (t = Math.round(t / M) * M), t <= n.minSize + C + this._b ? t = n.minSize + this._b : t >= this.size - (r.minSize + C + this._c) && (t = this.size - (r.minSize + this._c)), T.call(this, t), a(s, "onDrag", i)(F()))
  568.                 }
  569.  
  570.                 function q() {
  571.                     var e = p[this.a].element,
  572.                         t = p[this.b].element,
  573.                         n = e.getBoundingClientRect(),
  574.                         i = t.getBoundingClientRect();
  575.                     this.size = n[d] + i[d] + this._b + this._c, this.start = n[v], this.end = n[m]
  576.                 }
  577.  
  578.                 function H(e) {
  579.                     var t = function(e) {
  580.                         if (!getComputedStyle) return null;
  581.                         var t = getComputedStyle(e);
  582.                         if (!t) return null;
  583.                         var n = e[g];
  584.                         return 0 === n ? null : n -= "horizontal" === U ? parseFloat(t.paddingLeft) + parseFloat(t.paddingRight) : parseFloat(t.paddingTop) + parseFloat(t.paddingBottom)
  585.                     }(z);
  586.                     if (null === t) return e;
  587.                     if (_.reduce((function(e, t) {
  588.                             return e + t
  589.                         }), 0) > t) return e;
  590.                     var n = 0,
  591.                         i = [],
  592.                         r = e.map((function(r, s) {
  593.                             var o = t * r / 100,
  594.                                 a = u(k, 0 === s, s === e.length - 1, x),
  595.                                 l = _[s] + a;
  596.                             return o < l ? (n += l - o, i.push(0), l) : (i.push(o - l), o)
  597.                         }));
  598.                     return 0 === n ? e : r.map((function(e, r) {
  599.                         var s = e;
  600.                         if (n > 0 && i[r] - n > 0) {
  601.                             var o = Math.min(n, i[r] - n);
  602.                             n -= o, s = e - o
  603.                         }
  604.                         return s / t * 100
  605.                     }))
  606.                 }
  607.  
  608.                 function I() {
  609.                     var t = p[this.a].element,
  610.                         r = p[this.b].element;
  611.                     this.dragging && a(s, "onDragEnd", i)(F()), this.dragging = !1, e.removeEventListener("mouseup", this.stop), e.removeEventListener("touchend", this.stop), e.removeEventListener("touchcancel", this.stop), e.removeEventListener("mousemove", this.move), e.removeEventListener("touchmove", this.move), this.stop = null, this.move = null, t.removeEventListener("selectstart", i), t.removeEventListener("dragstart", i), r.removeEventListener("selectstart", i), r.removeEventListener("dragstart", i), t.style.userSelect = "", t.style.webkitUserSelect = "", t.style.MozUserSelect = "", t.style.pointerEvents = "", r.style.userSelect = "", r.style.webkitUserSelect = "", r.style.MozUserSelect = "", r.style.pointerEvents = "", this.gutter.style.cursor = "", this.parent.style.cursor = "", n.body.style.cursor = ""
  612.                 }
  613.  
  614.                 function W(t) {
  615.                     if (!("button" in t) || 0 === t.button) {
  616.                         var r = p[this.a].element,
  617.                             o = p[this.b].element;
  618.                         this.dragging || a(s, "onDragStart", i)(F()), t.preventDefault(), this.dragging = !0, this.move = N.bind(this), this.stop = I.bind(this), e.addEventListener("mouseup", this.stop), e.addEventListener("touchend", this.stop), e.addEventListener("touchcancel", this.stop), e.addEventListener("mousemove", this.move), e.addEventListener("touchmove", this.move), r.addEventListener("selectstart", i), r.addEventListener("dragstart", i), o.addEventListener("selectstart", i), o.addEventListener("dragstart", i), r.style.userSelect = "none", r.style.webkitUserSelect = "none", r.style.MozUserSelect = "none", r.style.pointerEvents = "none", o.style.userSelect = "none", o.style.webkitUserSelect = "none", o.style.MozUserSelect = "none", o.style.pointerEvents = "none", this.gutter.style.cursor = O, this.parent.style.cursor = O, n.body.style.cursor = O, q.call(this), this.dragOffset = R(t) - this.end
  619.                     }
  620.                 }
  621.                 "horizontal" === U ? (d = "width", f = "clientX", v = "left", m = "right", g = "clientWidth") : "vertical" === U && (d = "height", f = "clientY", v = "top", m = "bottom", g = "clientHeight"), S = H(S);
  622.                 var X = [];
  623.  
  624.                 function Y(e) {
  625.                     var t = e.i === X.length,
  626.                         n = t ? X[e.i - 1] : X[e.i];
  627.                     q.call(n);
  628.                     var i = t ? n.size - e.minSize - n._c : e.minSize + n._b;
  629.                     T.call(n, i)
  630.                 }
  631.                 return (p = y.map((function(e, t) {
  632.                     var n, i = {
  633.                         element: o(e),
  634.                         size: S[t],
  635.                         minSize: _[t],
  636.                         i: t
  637.                     };
  638.                     if (t > 0 && ((n = {
  639.                             a: t - 1,
  640.                             b: t,
  641.                             dragging: !1,
  642.                             direction: U,
  643.                             parent: z
  644.                         })._b = u(k, t - 1 == 0, !1, x), n._c = u(k, !1, t === y.length - 1, x), "row-reverse" === E || "column-reverse" === E)) {
  645.                         var r = n.a;
  646.                         n.a = n.b, n.b = r
  647.                     }
  648.                     if (t > 0) {
  649.                         var s = D(t, U, i.element);
  650.                         ! function(e, t, n) {
  651.                             var i = B(d, t, n);
  652.                             Object.keys(i).forEach((function(t) {
  653.                                 e.style[t] = i[t]
  654.                             }))
  655.                         }(s, k, t), n._a = W.bind(n), s.addEventListener("mousedown", n._a), s.addEventListener("touchstart", n._a), z.insertBefore(s, i.element), n.gutter = s
  656.                     }
  657.                     return j(i.element, i.size, u(k, 0 === t, t === y.length - 1, x), t), t > 0 && X.push(n), i
  658.                 }))).forEach((function(e) {
  659.                     var t = e.element.getBoundingClientRect()[d];
  660.                     t < e.minSize && (w ? Y(e) : e.minSize = t)
  661.                 })), {
  662.                     setSizes: function(e) {
  663.                         var t = H(e);
  664.                         t.forEach((function(e, n) {
  665.                             if (n > 0) {
  666.                                 var i = X[n - 1],
  667.                                     r = p[i.a],
  668.                                     s = p[i.b];
  669.                                 r.size = t[n - 1], s.size = e, j(r.element, r.size, i._b, r.i), j(s.element, s.size, i._c, s.i)
  670.                             }
  671.                         }))
  672.                     },
  673.                     getSizes: F,
  674.                     collapse: function(e) {
  675.                         Y(p[e])
  676.                     },
  677.                     destroy: function(e, t) {
  678.                         X.forEach((function(n) {
  679.                             if (!0 !== t ? n.parent.removeChild(n.gutter) : (n.gutter.removeEventListener("mousedown", n._a), n.gutter.removeEventListener("touchstart", n._a)), !0 !== e) {
  680.                                 var i = A(d, n.a.size, n._b);
  681.                                 Object.keys(i).forEach((function(e) {
  682.                                     p[n.a].element.style[e] = "", p[n.b].element.style[e] = ""
  683.                                 }))
  684.                             }
  685.                         }))
  686.                     },
  687.                     parent: z,
  688.                     pairs: X
  689.                 }
  690.             }
  691.         }));
  692.  
  693.         // Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
  694.         // This work is free. You can redistribute it and/or modify it
  695.         // under the terms of the WTFPL, Version 2
  696.         // For more information see LICENSE.txt or http://www.wtfpl.net/
  697.         // For more information, the home page:
  698.         // http://pieroxy.net/blog/pages/lz-string/testing.html
  699.         // LZ-based compression algorithm, version 1.4.4
  700.         var LZString = function() {
  701.             function o(o, r) {
  702.                 if (!t[o]) {
  703.                     t[o] = {};
  704.                     for (var n = 0; n < o.length; n++) t[o][o.charAt(n)] = n
  705.                 }
  706.                 return t[o][r]
  707.             }
  708.             var r = String.fromCharCode,
  709.                 n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  710.                 e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",
  711.                 t = {},
  712.                 i = {
  713.                     compressToBase64: function(o) {
  714.                         if (null == o) return "";
  715.                         var r = i._compress(o, 6, function(o) {
  716.                             return n.charAt(o)
  717.                         });
  718.                         switch (r.length % 4) {
  719.                             default:
  720.                                 case 0:
  721.                                 return r;
  722.                             case 1:
  723.                                     return r + "===";
  724.                             case 2:
  725.                                     return r + "==";
  726.                             case 3:
  727.                                     return r + "="
  728.                         }
  729.                     },
  730.                     decompressFromBase64: function(r) {
  731.                         return null == r ? "" : "" == r ? null : i._decompress(r.length, 32, function(e) {
  732.                             return o(n, r.charAt(e))
  733.                         })
  734.                     },
  735.                     compressToUTF16: function(o) {
  736.                         return null == o ? "" : i._compress(o, 15, function(o) {
  737.                             return r(o + 32)
  738.                         }) + " "
  739.                     },
  740.                     decompressFromUTF16: function(o) {
  741.                         return null == o ? "" : "" == o ? null : i._decompress(o.length, 16384, function(r) {
  742.                             return o.charCodeAt(r) - 32
  743.                         })
  744.                     },
  745.                     compressToUint8Array: function(o) {
  746.                         for (var r = i.compress(o), n = new Uint8Array(2 * r.length), e = 0, t = r.length; t > e; e++) {
  747.                             var s = r.charCodeAt(e);
  748.                             n[2 * e] = s >>> 8, n[2 * e + 1] = s % 256
  749.                         }
  750.                         return n
  751.                     },
  752.                     decompressFromUint8Array: function(o) {
  753.                         if (null === o || void 0 === o) return i.decompress(o);
  754.                         for (var n = new Array(o.length / 2), e = 0, t = n.length; t > e; e++) n[e] = 256 * o[2 * e] + o[2 * e + 1];
  755.                         var s = [];
  756.                         return n.forEach(function(o) {
  757.                             s.push(r(o))
  758.                         }), i.decompress(s.join(""))
  759.                     },
  760.                     compressToEncodedURIComponent: function(o) {
  761.                         return null == o ? "" : i._compress(o, 6, function(o) {
  762.                             return e.charAt(o)
  763.                         })
  764.                     },
  765.                     decompressFromEncodedURIComponent: function(r) {
  766.                         return null == r ? "" : "" == r ? null : (r = r.replace(/ /g, "+"), i._decompress(r.length, 32, function(n) {
  767.                             return o(e, r.charAt(n))
  768.                         }))
  769.                     },
  770.                     compress: function(o) {
  771.                         return i._compress(o, 16, function(o) {
  772.                             return r(o)
  773.                         })
  774.                     },
  775.                     _compress: function(o, r, n) {
  776.                         if (null == o) return "";
  777.                         var e, t, i, s = {},
  778.                             p = {},
  779.                             u = "",
  780.                             c = "",
  781.                             a = "",
  782.                             l = 2,
  783.                             f = 3,
  784.                             h = 2,
  785.                             d = [],
  786.                             m = 0,
  787.                             v = 0;
  788.                         for (i = 0; i < o.length; i += 1)
  789.                             if (u = o.charAt(i), Object.prototype.hasOwnProperty.call(s, u) || (s[u] = f++, p[u] = !0), c = a + u, Object.prototype.hasOwnProperty.call(s, c)) a = c;
  790.                             else {
  791.                                 if (Object.prototype.hasOwnProperty.call(p, a)) {
  792.                                     if (a.charCodeAt(0) < 256) {
  793.                                         for (e = 0; h > e; e++) m <<= 1, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++;
  794.                                         for (t = a.charCodeAt(0), e = 0; 8 > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1
  795.                                     } else {
  796.                                         for (t = 1, e = 0; h > e; e++) m = m << 1 | t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t = 0;
  797.                                         for (t = a.charCodeAt(0), e = 0; 16 > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1
  798.                                     }
  799.                                     l--, 0 == l && (l = Math.pow(2, h), h++), delete p[a]
  800.                                 } else
  801.                                     for (t = s[a], e = 0; h > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1;
  802.                                 l--, 0 == l && (l = Math.pow(2, h), h++), s[c] = f++, a = String(u)
  803.                             }
  804.                         if ("" !== a) {
  805.                             if (Object.prototype.hasOwnProperty.call(p, a)) {
  806.                                 if (a.charCodeAt(0) < 256) {
  807.                                     for (e = 0; h > e; e++) m <<= 1, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++;
  808.                                     for (t = a.charCodeAt(0), e = 0; 8 > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1
  809.                                 } else {
  810.                                     for (t = 1, e = 0; h > e; e++) m = m << 1 | t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t = 0;
  811.                                     for (t = a.charCodeAt(0), e = 0; 16 > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1
  812.                                 }
  813.                                 l--, 0 == l && (l = Math.pow(2, h), h++), delete p[a]
  814.                             } else
  815.                                 for (t = s[a], e = 0; h > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1;
  816.                             l--, 0 == l && (l = Math.pow(2, h), h++)
  817.                         }
  818.                         for (t = 2, e = 0; h > e; e++) m = m << 1 | 1 & t, v == r - 1 ? (v = 0, d.push(n(m)), m = 0) : v++, t >>= 1;
  819.                         for (;;) {
  820.                             if (m <<= 1, v == r - 1) {
  821.                                 d.push(n(m));
  822.                                 break
  823.                             }
  824.                             v++
  825.                         }
  826.                         return d.join("")
  827.                     },
  828.                     decompress: function(o) {
  829.                         return null == o ? "" : "" == o ? null : i._decompress(o.length, 32768, function(r) {
  830.                             return o.charCodeAt(r)
  831.                         })
  832.                     },
  833.                     _decompress: function(o, n, e) {
  834.                         var t, i, s, p, u, c, a, l, f = [],
  835.                             h = 4,
  836.                             d = 4,
  837.                             m = 3,
  838.                             v = "",
  839.                             w = [],
  840.                             A = {
  841.                                 val: e(0),
  842.                                 position: n,
  843.                                 index: 1
  844.                             };
  845.                         for (i = 0; 3 > i; i += 1) f[i] = i;
  846.                         for (p = 0, c = Math.pow(2, 2), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  847.                         switch (t = p) {
  848.                             case 0:
  849.                                 for (p = 0, c = Math.pow(2, 8), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  850.                                 l = r(p);
  851.                                 break;
  852.                             case 1:
  853.                                 for (p = 0, c = Math.pow(2, 16), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  854.                                 l = r(p);
  855.                                 break;
  856.                             case 2:
  857.                                 return ""
  858.                         }
  859.                         for (f[3] = l, s = l, w.push(l);;) {
  860.                             if (A.index > o) return "";
  861.                             for (p = 0, c = Math.pow(2, m), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  862.                             switch (l = p) {
  863.                                 case 0:
  864.                                     for (p = 0, c = Math.pow(2, 8), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  865.                                     f[d++] = r(p), l = d - 1, h--;
  866.                                     break;
  867.                                 case 1:
  868.                                     for (p = 0, c = Math.pow(2, 16), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1;
  869.                                     f[d++] = r(p), l = d - 1, h--;
  870.                                     break;
  871.                                 case 2:
  872.                                     return w.join("")
  873.                             }
  874.                             if (0 == h && (h = Math.pow(2, m), m++), f[l]) v = f[l];
  875.                             else {
  876.                                 if (l !== d) return null;
  877.                                 v = s + s.charAt(0)
  878.                             }
  879.                             w.push(v), f[d++] = s + v.charAt(0), h--, s = v, 0 == h && (h = Math.pow(2, m), m++)
  880.                         }
  881.                     }
  882.                 };
  883.             return i
  884.         }();
  885.         "function" == typeof define && define.amd ? define(function() {
  886.             return LZString
  887.         }) : "undefined" != typeof module && null != module && (module.exports = LZString);
  888.  
  889.         // canvas polyfill
  890.         (function(_0x58f57c, _0x2fa52d) {
  891.             if (_0x58f57c == undefined) {
  892.                 _0x58f57c = _0x2fa52d('canvas')['Context2d'];
  893.             }
  894.             if (_0x58f57c['prototype']['ellipse'] == undefined) {
  895.                 _0x58f57c['prototype']['ellipse'] = function(_0x251577, _0x4bf590, _0x3e8b2e, _0x2e7f82, _0x73bb7e, _0x102d04, _0x223dfa, _0x5270a4) {
  896.                     this['save']();
  897.                     this['translate'](_0x251577, _0x4bf590);
  898.                     this['rotate'](_0x73bb7e);
  899.                     this['scale'](_0x3e8b2e, _0x2e7f82);
  900.                     this['arc'](0x0, 0x0, 0x1, _0x102d04, _0x223dfa, _0x5270a4);
  901.                     this['restore']();
  902.                 };
  903.             }
  904.             if (typeof Path2D !== 'function' || typeof new Path2D()['addPath'] !== 'function') {
  905.                 (function() {
  906.                     parser = function() {
  907.                         function _0x222e3c(_0x4a67da, _0x23272f) {
  908.                             function _0x5dcaef() {
  909.                                 this['constructor'] = _0x4a67da;
  910.                             }
  911.                             _0x5dcaef['prototype'] = _0x23272f['prototype'];
  912.                             _0x4a67da['prototype'] = new _0x5dcaef();
  913.                         }
  914.  
  915.                         function _0x4cc4a9(_0x128787, _0x229f0e, _0x18f31a, _0x39d3f2, _0x400682, _0x436a2b) {
  916.                             this['message'] = _0x128787;
  917.                             this['expected'] = _0x229f0e;
  918.                             this['found'] = _0x18f31a;
  919.                             this['offset'] = _0x39d3f2;
  920.                             this['line'] = _0x400682;
  921.                             this['column'] = _0x436a2b;
  922.                             this['name'] = 'SyntaxError';
  923.                         }
  924.                         _0x222e3c(_0x4cc4a9, Error);
  925.  
  926.                         function _0x4b296c(_0x3a6242) {
  927.                             var _0xf95720 = arguments['length'] > 0x1 ? arguments[0x1] : {},
  928.                                 _0x4e763b = {},
  929.                                 _0x520ba4 = {
  930.                                     'svg_path': _0x19a2be
  931.                                 },
  932.                                 _0x3c91de = _0x19a2be,
  933.                                 _0x56093a = _0x4e763b,
  934.                                 _0x4c69bd = [],
  935.                                 _0x375d49 = null,
  936.                                 _0x46920b = function(_0x1e3596) {
  937.                                     return _0x65b89a;
  938.                                 },
  939.                                 _0x1f3890 = /^[Mm]/,
  940.                                 _0x5cb2e6 = {
  941.                                     'type': 'class',
  942.                                     'value': '[Mm]',
  943.                                     'description': '[Mm]'
  944.                                 },
  945.                                 _0x24a516 = function(_0x472687, _0x3a73b5) {
  946.                                     var _0x1798ed = _0x472687;
  947.                                     if (_0x52dd75) {
  948.                                         _0x1798ed = 'M';
  949.                                         _0x52dd75 = ![];
  950.                                     }
  951.                                     _0x65b89a['push']({
  952.                                         'type': 'moveTo',
  953.                                         'args': _0x17d776(_0x1798ed, _0x3a73b5[0x0])
  954.                                     });
  955.                                     for (var _0x2881fb = 0x1; _0x2881fb < _0x3a73b5['length']; _0x2881fb++) {
  956.                                         _0x65b89a['push']({
  957.                                             'type': 'lineTo',
  958.                                             'args': _0x17d776(_0x472687, _0x3a73b5[_0x2881fb])
  959.                                         });
  960.                                     }
  961.                                 },
  962.                                 _0x5e38d7 = function(_0x5cb700, _0x5cd47f) {
  963.                                     return _0x4ab5ce(_0x5cb700, _0x5cd47f);
  964.                                 },
  965.                                 _0x387727 = /^[Zz]/,
  966.                                 _0x2868a8 = {
  967.                                     'type': 'class',
  968.                                     'value': '[Zz]',
  969.                                     'description': '[Zz]'
  970.                                 },
  971.                                 _0x594869 = function() {
  972.                                     _0x65b89a['push']({
  973.                                         'type': 'closePath',
  974.                                         'args': []
  975.                                     });
  976.                                 },
  977.                                 _0x589f3b = /^[Ll]/,
  978.                                 _0x2d2081 = {
  979.                                     'type': 'class',
  980.                                     'value': '[Ll]',
  981.                                     'description': '[Ll]'
  982.                                 },
  983.                                 _0x50849d = function(_0x6f1c73, _0x4201ff) {
  984.                                     for (var _0x1ab8fa = 0x0; _0x1ab8fa < _0x4201ff['length']; _0x1ab8fa++) {
  985.                                         _0x65b89a['push']({
  986.                                             'type': 'lineTo',
  987.                                             'args': _0x17d776(_0x6f1c73, _0x4201ff[_0x1ab8fa])
  988.                                         });
  989.                                     }
  990.                                 },
  991.                                 _0x4c4628 = /^[Hh]/,
  992.                                 _0x36aa8b = {
  993.                                     'type': 'class',
  994.                                     'value': '[Hh]',
  995.                                     'description': '[Hh]'
  996.                                 },
  997.                                 _0x487dce = function(_0x2be630, _0x27cbf1) {
  998.                                     for (var _0x3497a6 = 0x0; _0x3497a6 < _0x27cbf1['length']; _0x3497a6++) {
  999.                                         _0x65b89a['push']({
  1000.                                             'type': 'lineTo',
  1001.                                             'args': _0x1134cf(_0x2be630, _0x27cbf1[_0x3497a6])
  1002.                                         });
  1003.                                     }
  1004.                                 },
  1005.                                 _0x2f8fdc = /^[Vv]/,
  1006.                                 _0x391e28 = {
  1007.                                     'type': 'class',
  1008.                                     'value': '[Vv]',
  1009.                                     'description': '[Vv]'
  1010.                                 },
  1011.                                 _0x2fb111 = function(_0x4a057b, _0x5752df) {
  1012.                                     for (var _0x1d8aa8 = 0x0; _0x1d8aa8 < _0x5752df['length']; _0x1d8aa8++) {
  1013.                                         _0x65b89a['push']({
  1014.                                             'type': 'lineTo',
  1015.                                             'args': _0x5b73e4(_0x4a057b, _0x5752df[_0x1d8aa8])
  1016.                                         });
  1017.                                     }
  1018.                                 },
  1019.                                 _0x4a4882 = /^[Cc]/,
  1020.                                 _0x1371ac = {
  1021.                                     'type': 'class',
  1022.                                     'value': '[Cc]',
  1023.                                     'description': '[Cc]'
  1024.                                 },
  1025.                                 _0x51b1f6 = function(_0x591e86, _0x47c797) {
  1026.                                     for (var _0x414596 = 0x0; _0x414596 < _0x47c797['length']; _0x414596++) {
  1027.                                         _0x65b89a['push']({
  1028.                                             'type': 'bezierCurveTo',
  1029.                                             'args': _0x54e14f(_0x591e86, _0x47c797[_0x414596])
  1030.                                         });
  1031.                                     }
  1032.                                 },
  1033.                                 _0xe1e1 = function(_0x503c00, _0x3cb31d, _0x4fcedc) {
  1034.                                     return _0x503c00['concat'](_0x3cb31d, _0x4fcedc);
  1035.                                 },
  1036.                                 _0x3c0d2e = /^[Ss]/,
  1037.                                 _0x394135 = {
  1038.                                     'type': 'class',
  1039.                                     'value': '[Ss]',
  1040.                                     'description': '[Ss]'
  1041.                                 },
  1042.                                 _0x4aa6f7 = function(_0xbe6c5c, _0xfe5f70) {
  1043.                                     for (var _0x1ad248 = 0x0; _0x1ad248 < _0xfe5f70['length']; _0x1ad248++) {
  1044.                                         _0x65b89a['push']({
  1045.                                             'type': 'bezierCurveTo',
  1046.                                             'args': _0x2d262a()['concat'](_0x54e14f(_0xbe6c5c, _0xfe5f70[_0x1ad248]))
  1047.                                         });
  1048.                                     }
  1049.                                 },
  1050.                                 _0x30c615 = function(_0x7d0b66, _0x20da34) {
  1051.                                     return _0x7d0b66['concat'](_0x20da34);
  1052.                                 },
  1053.                                 _0x3a67c6 = /^[Qq]/,
  1054.                                 _0x85b933 = {
  1055.                                     'type': 'class',
  1056.                                     'value': '[Qq]',
  1057.                                     'description': '[Qq]'
  1058.                                 },
  1059.                                 _0x3ceb0a = function(_0x50f7bd, _0x497820) {
  1060.                                     for (var _0x50f9ef = 0x0; _0x50f9ef < _0x497820['length']; _0x50f9ef++) {
  1061.                                         _0x65b89a['push']({
  1062.                                             'type': 'quadraticCurveTo',
  1063.                                             'args': _0x54e14f(_0x50f7bd, _0x497820[_0x50f9ef])
  1064.                                         });
  1065.                                     }
  1066.                                 },
  1067.                                 _0x543bea = /^[Tt]/,
  1068.                                 _0x16de6e = {
  1069.                                     'type': 'class',
  1070.                                     'value': '[Tt]',
  1071.                                     'description': '[Tt]'
  1072.                                 },
  1073.                                 _0x207488 = function(_0x301f77, _0x27fec5) {
  1074.                                     for (var _0xacff90 = 0x0; _0xacff90 < _0x27fec5['length']; _0xacff90++) {
  1075.                                         var _0x5a46f5 = _0x2d262a();
  1076.                                         _0x65b89a['push']({
  1077.                                             'type': 'quadraticCurveTo',
  1078.                                             'args': _0x5a46f5['concat'](_0x54e14f(_0x301f77, _0x27fec5[_0xacff90]))
  1079.                                         });
  1080.                                         _0x594746 = _0x5a46f5['slice'](0x0);
  1081.                                     }
  1082.                                 },
  1083.                                 _0xd18715 = /^[Aa]/,
  1084.                                 _0x30a6b0 = {
  1085.                                     'type': 'class',
  1086.                                     'value': '[Aa]',
  1087.                                     'description': '[Aa]'
  1088.                                 },
  1089.                                 _0xbeac27 = function(_0x2ee17b, _0x33cbf9) {
  1090.                                     for (var _0x56c3b5 = 0x0; _0x56c3b5 < _0x33cbf9['length']; _0x56c3b5++) {
  1091.                                         var _0x1c894f = [_0x5b0427['slice']()];
  1092.                                         var _0x1b27e1 = [_0x17d776(_0x2ee17b, _0x33cbf9[_0x56c3b5]['slice'](-0x2))];
  1093.                                         absArgs = _0x1c894f['concat'](_0x33cbf9[_0x56c3b5]['slice'](0x0, -0x2), _0x1b27e1);
  1094.                                         _0x42a62a['apply'](this, absArgs);
  1095.                                     }
  1096.                                 },
  1097.                                 _0x2cbb71 = function(_0x7dca7a, _0x218490, _0x59acec, _0x3327e6, _0x497542, _0x1953dc) {
  1098.                                     return [parseFloat(_0x7dca7a), parseFloat(_0x218490), parseFloat(_0x4eee96(_0x59acec)['join']('')), parseInt(_0x3327e6), parseInt(_0x497542), _0x1953dc[0x0], _0x1953dc[0x1]];
  1099.                                 },
  1100.                                 _0x201fa4 = function(_0x2ea5f3, _0x3e9760) {
  1101.                                     return [_0x2ea5f3, _0x3e9760];
  1102.                                 },
  1103.                                 _0x5a72e5 = function(_0x49c77a) {
  1104.                                     return parseFloat(_0x4eee96(_0x49c77a)['join'](''));
  1105.                                 },
  1106.                                 _0x444dd7 = '0',
  1107.                                 _0x44e46d = {
  1108.                                     'type': 'literal',
  1109.                                     'value': '0',
  1110.                                     'description': '\x220\x22'
  1111.                                 },
  1112.                                 _0x8b2ec9 = '1',
  1113.                                 _0x2bab45 = {
  1114.                                     'type': 'literal',
  1115.                                     'value': '1',
  1116.                                     'description': '\x221\x22'
  1117.                                 },
  1118.                                 _0x5b6dde = ',',
  1119.                                 _0x3d3d23 = {
  1120.                                     'type': 'literal',
  1121.                                     'value': ',',
  1122.                                     'description': '\x22,\x22'
  1123.                                 },
  1124.                                 _0x57d0b1 = '.',
  1125.                                 _0x3e764 = {
  1126.                                     'type': 'literal',
  1127.                                     'value': '.',
  1128.                                     'description': '\x22.\x22'
  1129.                                 },
  1130.                                 _0x1e3f99 = /^[eE]/,
  1131.                                 _0x1123fe = {
  1132.                                     'type': 'class',
  1133.                                     'value': '[eE]',
  1134.                                     'description': '[eE]'
  1135.                                 },
  1136.                                 _0x59832c = '+',
  1137.                                 _0x423117 = {
  1138.                                     'type': 'literal',
  1139.                                     'value': '+',
  1140.                                     'description': '\x22+\x22'
  1141.                                 },
  1142.                                 _0xf5aaab = '-',
  1143.                                 _0x198f27 = {
  1144.                                     'type': 'literal',
  1145.                                     'value': '-',
  1146.                                     'description': '\x22-\x22'
  1147.                                 },
  1148.                                 _0x1d19eb = /^[0-9]/,
  1149.                                 _0x2a6cc4 = {
  1150.                                     'type': 'class',
  1151.                                     'value': '[0-9]',
  1152.                                     'description': '[0-9]'
  1153.                                 },
  1154.                                 _0x3a87d5 = function(_0x48bf53) {
  1155.                                     return _0x48bf53['join']('');
  1156.                                 },
  1157.                                 _0x15ce60 = /^[ \t\n\r]/,
  1158.                                 _0x41f84b = {
  1159.                                     'type': 'class',
  1160.                                     'value': '[\x20\x5ct\x5cn\x5cr]',
  1161.                                     'description': '[\x20\x5ct\x5cn\x5cr]'
  1162.                                 },
  1163.                                 _0x3e408e = 0x0,
  1164.                                 _0x55bc2f = 0x0,
  1165.                                 _0x5f2f07 = 0x0,
  1166.                                 _0x482c66 = {
  1167.                                     'line': 0x1,
  1168.                                     'column': 0x1,
  1169.                                     'seenCR': ![]
  1170.                                 },
  1171.                                 _0x7dbbe5 = 0x0,
  1172.                                 _0x1fda2f = [],
  1173.                                 _0x15e012 = 0x0,
  1174.                                 _0x2bfff2;
  1175.                             if ('startRule' in _0xf95720) {
  1176.                                 if (!(_0xf95720['startRule'] in _0x520ba4)) {
  1177.                                     throw new Error('Can\x27t\x20start\x20parsing\x20from\x20rule\x20\x22' + _0xf95720['startRule'] + '\x22.');
  1178.                                 }
  1179.                                 _0x3c91de = _0x520ba4[_0xf95720['startRule']];
  1180.                             }
  1181.  
  1182.                             function _0x55e6ee() {
  1183.                                 return _0x3a6242['substring'](_0x55bc2f, _0x3e408e);
  1184.                             }
  1185.  
  1186.                             function _0x34aa85() {
  1187.                                 return _0x55bc2f;
  1188.                             }
  1189.  
  1190.                             function _0x83f5f7() {
  1191.                                 return _0x3d95d5(_0x55bc2f)['line'];
  1192.                             }
  1193.  
  1194.                             function _0x299bb3() {
  1195.                                 return _0x3d95d5(_0x55bc2f)['column'];
  1196.                             }
  1197.  
  1198.                             function _0x5f591f(_0x3c65e8) {
  1199.                                 throw _0x2f901a(null, [{
  1200.                                     'type': 'other',
  1201.                                     'description': _0x3c65e8
  1202.                                 }], _0x55bc2f);
  1203.                             }
  1204.  
  1205.                             function _0x5038a9(_0x1ed506) {
  1206.                                 throw _0x2f901a(_0x1ed506, null, _0x55bc2f);
  1207.                             }
  1208.  
  1209.                             function _0x3d95d5(_0x4f850f) {
  1210.                                 function _0x122f48(_0x20a115, _0x56c31b, _0x20288c) {
  1211.                                     var _0x448ad8, _0x62a2a1;
  1212.                                     for (_0x448ad8 = _0x56c31b; _0x448ad8 < _0x20288c; _0x448ad8++) {
  1213.                                         _0x62a2a1 = _0x3a6242['charAt'](_0x448ad8);
  1214.                                         if (_0x62a2a1 === '\x0a') {
  1215.                                             if (!_0x20a115['seenCR']) {
  1216.                                                 _0x20a115['line']++;
  1217.                                             }
  1218.                                             _0x20a115['column'] = 0x1;
  1219.                                             _0x20a115['seenCR'] = ![];
  1220.                                         } else if (_0x62a2a1 === '\x0d' || _0x62a2a1 === '\u2028' || _0x62a2a1 === '\u2029') {
  1221.                                             _0x20a115['line']++;
  1222.                                             _0x20a115['column'] = 0x1;
  1223.                                             _0x20a115['seenCR'] = !![];
  1224.                                         } else {
  1225.                                             _0x20a115['column']++;
  1226.                                             _0x20a115['seenCR'] = ![];
  1227.                                         }
  1228.                                     }
  1229.                                 }
  1230.                                 if (_0x5f2f07 !== _0x4f850f) {
  1231.                                     if (_0x5f2f07 > _0x4f850f) {
  1232.                                         _0x5f2f07 = 0x0;
  1233.                                         _0x482c66 = {
  1234.                                             'line': 0x1,
  1235.                                             'column': 0x1,
  1236.                                             'seenCR': ![]
  1237.                                         };
  1238.                                     }
  1239.                                     _0x122f48(_0x482c66, _0x5f2f07, _0x4f850f);
  1240.                                     _0x5f2f07 = _0x4f850f;
  1241.                                 }
  1242.                                 return _0x482c66;
  1243.                             }
  1244.  
  1245.                             function _0x569314(_0x1bd4d0) {
  1246.                                 if (_0x3e408e < _0x7dbbe5) {
  1247.                                     return;
  1248.                                 }
  1249.                                 if (_0x3e408e > _0x7dbbe5) {
  1250.                                     _0x7dbbe5 = _0x3e408e;
  1251.                                     _0x1fda2f = [];
  1252.                                 }
  1253.                                 _0x1fda2f['push'](_0x1bd4d0);
  1254.                             }
  1255.  
  1256.                             function _0x2f901a(_0x13e6a0, _0xf91d3e, _0x3c913f) {
  1257.                                 function _0x2e97b2(_0x24c9dd) {
  1258.                                     var _0xba4eba = 0x1;
  1259.                                     _0x24c9dd['sort'](function(_0x15643f, _0x7b7e06) {
  1260.                                         if (_0x15643f['description'] < _0x7b7e06['description']) {
  1261.                                             return -0x1;
  1262.                                         } else if (_0x15643f['description'] > _0x7b7e06['description']) {
  1263.                                             return 0x1;
  1264.                                         } else {
  1265.                                             return 0x0;
  1266.                                         }
  1267.                                     });
  1268.                                     while (_0xba4eba < _0x24c9dd['length']) {
  1269.                                         if (_0x24c9dd[_0xba4eba - 0x1] === _0x24c9dd[_0xba4eba]) {
  1270.                                             _0x24c9dd['splice'](_0xba4eba, 0x1);
  1271.                                         } else {
  1272.                                             _0xba4eba++;
  1273.                                         }
  1274.                                     }
  1275.                                 }
  1276.  
  1277.                                 function _0x208340(_0x31e3aa, _0x2d3db5) {
  1278.                                     function _0x1f97e3(_0x12ebdf) {
  1279.                                         function _0x1a1dba(_0x4783bd) {
  1280.                                             return _0x4783bd['charCodeAt'](0x0)['toString'](0x10)['toUpperCase']();
  1281.                                         }
  1282.                                         return _0x12ebdf['replace'](/\\/g, '\x5c\x5c')['replace'](/"/g, '\x5c\x22')['replace'](/\x08/g, '\x5cb')['replace'](/\t/g, '\x5ct')['replace'](/\n/g, '\x5cn')['replace'](/\f/g, '\x5cf')['replace'](/\r/g, '\x5cr')['replace'](/[\x00-\x07\x0B\x0E\x0F]/g, function(_0x4d0809) {
  1283.                                            return '\x5cx0' + _0x1a1dba(_0x4d0809);
  1284.                                        })['replace'](/[\x10-\x1F\x80-\xFF]/g, function(_0xf5b428) {
  1285.                                            return '\x5cx' + _0x1a1dba(_0xf5b428);
  1286.                                        })['replace'](/[\u0180-\u0FFF]/g, function(_0x25ab64) {
  1287.                                            return '\x5cu0' + _0x1a1dba(_0x25ab64);
  1288.                                        })['replace'](/[\u1080-\uFFFF]/g, function(_0x23b97b) {
  1289.                                            return '\x5cu' + _0x1a1dba(_0x23b97b);
  1290.                                        });
  1291.                                    }
  1292.                                    var _0x280d62 = new Array(_0x31e3aa['length']),
  1293.                                        _0x1be497, _0x350d25, _0xc094de;
  1294.                                    for (_0xc094de = 0x0; _0xc094de < _0x31e3aa['length']; _0xc094de++) {
  1295.                                        _0x280d62[_0xc094de] = _0x31e3aa[_0xc094de]['description'];
  1296.                                    }
  1297.                                    _0x1be497 = _0x31e3aa['length'] > 0x1 ? _0x280d62['slice'](0x0, -0x1)['join'](',\x20') + '\x20or\x20' + _0x280d62[_0x31e3aa['length'] - 0x1] : _0x280d62[0x0];
  1298.                                    _0x350d25 = _0x2d3db5 ? '\x22' + _0x1f97e3(_0x2d3db5) + '\x22' : 'end\x20of\x20input';
  1299.                                    return 'Expected\x20' + _0x1be497 + '\x20but\x20' + _0x350d25 + '\x20found.';
  1300.                                }
  1301.                                var _0x28c2cf = _0x3d95d5(_0x3c913f),
  1302.                                    _0x3a7d1a = _0x3c913f < _0x3a6242['length'] ? _0x3a6242['charAt'](_0x3c913f) : null;
  1303.                                if (_0xf91d3e !== null) {
  1304.                                    _0x2e97b2(_0xf91d3e);
  1305.                                }
  1306.                                return new _0x4cc4a9(_0x13e6a0 !== null ? _0x13e6a0 : _0x208340(_0xf91d3e, _0x3a7d1a), _0xf91d3e, _0x3a7d1a, _0x3c913f, _0x28c2cf['line'], _0x28c2cf['column']);
  1307.                            }
  1308.  
  1309.                            function _0x19a2be() {
  1310.                                var _0xce07fa, _0x4a404b, _0x27603b, _0x5a3f6a, _0x1e5b9e;
  1311.                                _0xce07fa = _0x3e408e;
  1312.                                _0x4a404b = [];
  1313.                                _0x27603b = _0x553f5b();
  1314.                                while (_0x27603b !== _0x4e763b) {
  1315.                                    _0x4a404b['push'](_0x27603b);
  1316.                                    _0x27603b = _0x553f5b();
  1317.                                }
  1318.                                if (_0x4a404b !== _0x4e763b) {
  1319.                                    _0x27603b = _0x3b76e1();
  1320.                                    if (_0x27603b === _0x4e763b) {
  1321.                                        _0x27603b = _0x375d49;
  1322.                                    }
  1323.                                    if (_0x27603b !== _0x4e763b) {
  1324.                                        _0x5a3f6a = [];
  1325.                                        _0x1e5b9e = _0x553f5b();
  1326.                                        while (_0x1e5b9e !== _0x4e763b) {
  1327.                                            _0x5a3f6a['push'](_0x1e5b9e);
  1328.                                            _0x1e5b9e = _0x553f5b();
  1329.                                        }
  1330.                                        if (_0x5a3f6a !== _0x4e763b) {
  1331.                                            _0x55bc2f = _0xce07fa;
  1332.                                            _0x4a404b = _0x46920b(_0x27603b);
  1333.                                            _0xce07fa = _0x4a404b;
  1334.                                        } else {
  1335.                                            _0x3e408e = _0xce07fa;
  1336.                                            _0xce07fa = _0x56093a;
  1337.                                        }
  1338.                                    } else {
  1339.                                        _0x3e408e = _0xce07fa;
  1340.                                        _0xce07fa = _0x56093a;
  1341.                                    }
  1342.                                } else {
  1343.                                    _0x3e408e = _0xce07fa;
  1344.                                    _0xce07fa = _0x56093a;
  1345.                                }
  1346.                                return _0xce07fa;
  1347.                            }
  1348.  
  1349.                            function _0x3b76e1() {
  1350.                                var _0x35b597, _0x3e84a3, _0x1f9f3d, _0x105cd4, _0x55d3ab;
  1351.                                _0x35b597 = _0x3e408e;
  1352.                                _0x3e84a3 = _0x1da102();
  1353.                                if (_0x3e84a3 !== _0x4e763b) {
  1354.                                    _0x1f9f3d = _0x3e408e;
  1355.                                    _0x105cd4 = [];
  1356.                                    _0x55d3ab = _0x553f5b();
  1357.                                    while (_0x55d3ab !== _0x4e763b) {
  1358.                                        _0x105cd4['push'](_0x55d3ab);
  1359.                                        _0x55d3ab = _0x553f5b();
  1360.                                    }
  1361.                                    if (_0x105cd4 !== _0x4e763b) {
  1362.                                        _0x55d3ab = _0x3b76e1();
  1363.                                        if (_0x55d3ab !== _0x4e763b) {
  1364.                                            _0x105cd4 = [_0x105cd4, _0x55d3ab];
  1365.                                            _0x1f9f3d = _0x105cd4;
  1366.                                        } else {
  1367.                                            _0x3e408e = _0x1f9f3d;
  1368.                                            _0x1f9f3d = _0x56093a;
  1369.                                        }
  1370.                                    } else {
  1371.                                        _0x3e408e = _0x1f9f3d;
  1372.                                        _0x1f9f3d = _0x56093a;
  1373.                                    }
  1374.                                    if (_0x1f9f3d === _0x4e763b) {
  1375.                                        _0x1f9f3d = _0x375d49;
  1376.                                    }
  1377.                                    if (_0x1f9f3d !== _0x4e763b) {
  1378.                                        _0x3e84a3 = [_0x3e84a3, _0x1f9f3d];
  1379.                                        _0x35b597 = _0x3e84a3;
  1380.                                    } else {
  1381.                                        _0x3e408e = _0x35b597;
  1382.                                        _0x35b597 = _0x56093a;
  1383.                                    }
  1384.                                } else {
  1385.                                    _0x3e408e = _0x35b597;
  1386.                                    _0x35b597 = _0x56093a;
  1387.                                }
  1388.                                return _0x35b597;
  1389.                            }
  1390.  
  1391.                            function _0x1da102() {
  1392.                                var _0x3876a5, _0x233bbe, _0x1c2791, _0x4e689d, _0x22482a;
  1393.                                _0x3876a5 = _0x3e408e;
  1394.                                _0x233bbe = _0x893e26();
  1395.                                if (_0x233bbe !== _0x4e763b) {
  1396.                                    _0x1c2791 = _0x3e408e;
  1397.                                    _0x4e689d = [];
  1398.                                    _0x22482a = _0x553f5b();
  1399.                                    while (_0x22482a !== _0x4e763b) {
  1400.                                        _0x4e689d['push'](_0x22482a);
  1401.                                        _0x22482a = _0x553f5b();
  1402.                                    }
  1403.                                    if (_0x4e689d !== _0x4e763b) {
  1404.                                        _0x22482a = _0x12b906();
  1405.                                        if (_0x22482a !== _0x4e763b) {
  1406.                                            _0x4e689d = [_0x4e689d, _0x22482a];
  1407.                                            _0x1c2791 = _0x4e689d;
  1408.                                        } else {
  1409.                                            _0x3e408e = _0x1c2791;
  1410.                                            _0x1c2791 = _0x56093a;
  1411.                                        }
  1412.                                    } else {
  1413.                                        _0x3e408e = _0x1c2791;
  1414.                                        _0x1c2791 = _0x56093a;
  1415.                                    }
  1416.                                    if (_0x1c2791 === _0x4e763b) {
  1417.                                        _0x1c2791 = _0x375d49;
  1418.                                    }
  1419.                                    if (_0x1c2791 !== _0x4e763b) {
  1420.                                        _0x233bbe = [_0x233bbe, _0x1c2791];
  1421.                                        _0x3876a5 = _0x233bbe;
  1422.                                    } else {
  1423.                                        _0x3e408e = _0x3876a5;
  1424.                                        _0x3876a5 = _0x56093a;
  1425.                                    }
  1426.                                } else {
  1427.                                    _0x3e408e = _0x3876a5;
  1428.                                    _0x3876a5 = _0x56093a;
  1429.                                }
  1430.                                return _0x3876a5;
  1431.                            }
  1432.  
  1433.                            function _0x12b906() {
  1434.                                var _0x470592, _0x4f49fa, _0x527996, _0xdffd8d, _0x564644;
  1435.                                _0x470592 = _0x3e408e;
  1436.                                _0x4f49fa = _0x2ef62e();
  1437.                                if (_0x4f49fa !== _0x4e763b) {
  1438.                                    _0x527996 = _0x3e408e;
  1439.                                    _0xdffd8d = [];
  1440.                                    _0x564644 = _0x553f5b();
  1441.                                    while (_0x564644 !== _0x4e763b) {
  1442.                                        _0xdffd8d['push'](_0x564644);
  1443.                                        _0x564644 = _0x553f5b();
  1444.                                    }
  1445.                                    if (_0xdffd8d !== _0x4e763b) {
  1446.                                        _0x564644 = _0x12b906();
  1447.                                        if (_0x564644 !== _0x4e763b) {
  1448.                                            _0xdffd8d = [_0xdffd8d, _0x564644];
  1449.                                            _0x527996 = _0xdffd8d;
  1450.                                        } else {
  1451.                                            _0x3e408e = _0x527996;
  1452.                                            _0x527996 = _0x56093a;
  1453.                                        }
  1454.                                    } else {
  1455.                                        _0x3e408e = _0x527996;
  1456.                                        _0x527996 = _0x56093a;
  1457.                                    }
  1458.                                    if (_0x527996 === _0x4e763b) {
  1459.                                        _0x527996 = _0x375d49;
  1460.                                    }
  1461.                                    if (_0x527996 !== _0x4e763b) {
  1462.                                        _0x4f49fa = [_0x4f49fa, _0x527996];
  1463.                                        _0x470592 = _0x4f49fa;
  1464.                                    } else {
  1465.                                        _0x3e408e = _0x470592;
  1466.                                        _0x470592 = _0x56093a;
  1467.                                    }
  1468.                                } else {
  1469.                                    _0x3e408e = _0x470592;
  1470.                                    _0x470592 = _0x56093a;
  1471.                                }
  1472.                                return _0x470592;
  1473.                            }
  1474.  
  1475.                            function _0x2ef62e() {
  1476.                                var _0x61ef5c;
  1477.                                _0x61ef5c = _0xf830c1();
  1478.                                if (_0x61ef5c === _0x4e763b) {
  1479.                                    _0x61ef5c = _0x4e4f13();
  1480.                                    if (_0x61ef5c === _0x4e763b) {
  1481.                                        _0x61ef5c = _0x5e3341();
  1482.                                        if (_0x61ef5c === _0x4e763b) {
  1483.                                            _0x61ef5c = _0x5804f9();
  1484.                                            if (_0x61ef5c === _0x4e763b) {
  1485.                                                _0x61ef5c = _0x1fa3d9();
  1486.                                                if (_0x61ef5c === _0x4e763b) {
  1487.                                                    _0x61ef5c = _0x3bb24f();
  1488.                                                    if (_0x61ef5c === _0x4e763b) {
  1489.                                                        _0x61ef5c = _0x1d0640();
  1490.                                                        if (_0x61ef5c === _0x4e763b) {
  1491.                                                            _0x61ef5c = _0x348547();
  1492.                                                            if (_0x61ef5c === _0x4e763b) {
  1493.                                                                _0x61ef5c = _0x553067();
  1494.                                                            }
  1495.                                                        }
  1496.                                                    }
  1497.                                                }
  1498.                                            }
  1499.                                        }
  1500.                                    }
  1501.                                }
  1502.                                return _0x61ef5c;
  1503.                            }
  1504.  
  1505.                            function _0x893e26() {
  1506.                                var _0x381238, _0x436b86, _0x2b7c21, _0x41077d;
  1507.                                _0x381238 = _0x3e408e;
  1508.                                if (_0x1f3890['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1509.                                    _0x436b86 = _0x3a6242['charAt'](_0x3e408e);
  1510.                                    _0x3e408e++;
  1511.                                } else {
  1512.                                    _0x436b86 = _0x4e763b;
  1513.                                    if (_0x15e012 === 0x0) {
  1514.                                        _0x569314(_0x5cb2e6);
  1515.                                    }
  1516.                                }
  1517.                                if (_0x436b86 !== _0x4e763b) {
  1518.                                    _0x2b7c21 = [];
  1519.                                    _0x41077d = _0x553f5b();
  1520.                                    while (_0x41077d !== _0x4e763b) {
  1521.                                        _0x2b7c21['push'](_0x41077d);
  1522.                                        _0x41077d = _0x553f5b();
  1523.                                    }
  1524.                                    if (_0x2b7c21 !== _0x4e763b) {
  1525.                                        _0x41077d = _0x4fc8de();
  1526.                                        if (_0x41077d !== _0x4e763b) {
  1527.                                            _0x55bc2f = _0x381238;
  1528.                                            _0x436b86 = _0x24a516(_0x436b86, _0x41077d);
  1529.                                            _0x381238 = _0x436b86;
  1530.                                        } else {
  1531.                                            _0x3e408e = _0x381238;
  1532.                                            _0x381238 = _0x56093a;
  1533.                                        }
  1534.                                    } else {
  1535.                                        _0x3e408e = _0x381238;
  1536.                                        _0x381238 = _0x56093a;
  1537.                                    }
  1538.                                } else {
  1539.                                    _0x3e408e = _0x381238;
  1540.                                    _0x381238 = _0x56093a;
  1541.                                }
  1542.                                return _0x381238;
  1543.                            }
  1544.  
  1545.                            function _0x4fc8de() {
  1546.                                var _0x580c45, _0x3f7f44, _0x2ace55, _0x21a7f1, _0xe4cd2b;
  1547.                                _0x580c45 = _0x3e408e;
  1548.                                _0x3f7f44 = _0x38a50a();
  1549.                                if (_0x3f7f44 !== _0x4e763b) {
  1550.                                    _0x2ace55 = _0x3e408e;
  1551.                                    _0x21a7f1 = _0x5bbfe4();
  1552.                                    if (_0x21a7f1 === _0x4e763b) {
  1553.                                        _0x21a7f1 = _0x375d49;
  1554.                                    }
  1555.                                    if (_0x21a7f1 !== _0x4e763b) {
  1556.                                        _0xe4cd2b = _0x26c904();
  1557.                                        if (_0xe4cd2b !== _0x4e763b) {
  1558.                                            _0x21a7f1 = [_0x21a7f1, _0xe4cd2b];
  1559.                                            _0x2ace55 = _0x21a7f1;
  1560.                                        } else {
  1561.                                            _0x3e408e = _0x2ace55;
  1562.                                            _0x2ace55 = _0x56093a;
  1563.                                        }
  1564.                                    } else {
  1565.                                        _0x3e408e = _0x2ace55;
  1566.                                        _0x2ace55 = _0x56093a;
  1567.                                    }
  1568.                                    if (_0x2ace55 === _0x4e763b) {
  1569.                                        _0x2ace55 = _0x375d49;
  1570.                                    }
  1571.                                    if (_0x2ace55 !== _0x4e763b) {
  1572.                                        _0x55bc2f = _0x580c45;
  1573.                                        _0x3f7f44 = _0x5e38d7(_0x3f7f44, _0x2ace55);
  1574.                                        _0x580c45 = _0x3f7f44;
  1575.                                    } else {
  1576.                                        _0x3e408e = _0x580c45;
  1577.                                        _0x580c45 = _0x56093a;
  1578.                                    }
  1579.                                } else {
  1580.                                    _0x3e408e = _0x580c45;
  1581.                                    _0x580c45 = _0x56093a;
  1582.                                }
  1583.                                return _0x580c45;
  1584.                            }
  1585.  
  1586.                            function _0xf830c1() {
  1587.                                var _0x4a09ef, _0x3814c5;
  1588.                                _0x4a09ef = _0x3e408e;
  1589.                                if (_0x387727['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1590.                                    _0x3814c5 = _0x3a6242['charAt'](_0x3e408e);
  1591.                                    _0x3e408e++;
  1592.                                } else {
  1593.                                    _0x3814c5 = _0x4e763b;
  1594.                                    if (_0x15e012 === 0x0) {
  1595.                                        _0x569314(_0x2868a8);
  1596.                                    }
  1597.                                }
  1598.                                if (_0x3814c5 !== _0x4e763b) {
  1599.                                    _0x55bc2f = _0x4a09ef;
  1600.                                    _0x3814c5 = _0x594869();
  1601.                                }
  1602.                                _0x4a09ef = _0x3814c5;
  1603.                                return _0x4a09ef;
  1604.                            }
  1605.  
  1606.                            function _0x4e4f13() {
  1607.                                var _0x334609, _0xb49ef9, _0x341763, _0x5aa41b;
  1608.                                _0x334609 = _0x3e408e;
  1609.                                if (_0x589f3b['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1610.                                    _0xb49ef9 = _0x3a6242['charAt'](_0x3e408e);
  1611.                                    _0x3e408e++;
  1612.                                } else {
  1613.                                    _0xb49ef9 = _0x4e763b;
  1614.                                    if (_0x15e012 === 0x0) {
  1615.                                        _0x569314(_0x2d2081);
  1616.                                    }
  1617.                                }
  1618.                                if (_0xb49ef9 !== _0x4e763b) {
  1619.                                    _0x341763 = [];
  1620.                                    _0x5aa41b = _0x553f5b();
  1621.                                    while (_0x5aa41b !== _0x4e763b) {
  1622.                                        _0x341763['push'](_0x5aa41b);
  1623.                                        _0x5aa41b = _0x553f5b();
  1624.                                    }
  1625.                                    if (_0x341763 !== _0x4e763b) {
  1626.                                        _0x5aa41b = _0x26c904();
  1627.                                        if (_0x5aa41b !== _0x4e763b) {
  1628.                                            _0x55bc2f = _0x334609;
  1629.                                            _0xb49ef9 = _0x50849d(_0xb49ef9, _0x5aa41b);
  1630.                                            _0x334609 = _0xb49ef9;
  1631.                                        } else {
  1632.                                            _0x3e408e = _0x334609;
  1633.                                            _0x334609 = _0x56093a;
  1634.                                        }
  1635.                                    } else {
  1636.                                        _0x3e408e = _0x334609;
  1637.                                        _0x334609 = _0x56093a;
  1638.                                    }
  1639.                                } else {
  1640.                                    _0x3e408e = _0x334609;
  1641.                                    _0x334609 = _0x56093a;
  1642.                                }
  1643.                                return _0x334609;
  1644.                            }
  1645.  
  1646.                            function _0x26c904() {
  1647.                                var _0x4a15e6, _0x4a995b, _0x27d7c7, _0x2e38ab, _0x4563fc;
  1648.                                _0x4a15e6 = _0x3e408e;
  1649.                                _0x4a995b = _0x38a50a();
  1650.                                if (_0x4a995b !== _0x4e763b) {
  1651.                                    _0x27d7c7 = _0x3e408e;
  1652.                                    _0x2e38ab = _0x5bbfe4();
  1653.                                    if (_0x2e38ab === _0x4e763b) {
  1654.                                        _0x2e38ab = _0x375d49;
  1655.                                    }
  1656.                                    if (_0x2e38ab !== _0x4e763b) {
  1657.                                        _0x4563fc = _0x26c904();
  1658.                                        if (_0x4563fc !== _0x4e763b) {
  1659.                                            _0x2e38ab = [_0x2e38ab, _0x4563fc];
  1660.                                            _0x27d7c7 = _0x2e38ab;
  1661.                                        } else {
  1662.                                            _0x3e408e = _0x27d7c7;
  1663.                                            _0x27d7c7 = _0x56093a;
  1664.                                        }
  1665.                                    } else {
  1666.                                        _0x3e408e = _0x27d7c7;
  1667.                                        _0x27d7c7 = _0x56093a;
  1668.                                    }
  1669.                                    if (_0x27d7c7 === _0x4e763b) {
  1670.                                        _0x27d7c7 = _0x375d49;
  1671.                                    }
  1672.                                    if (_0x27d7c7 !== _0x4e763b) {
  1673.                                        _0x55bc2f = _0x4a15e6;
  1674.                                        _0x4a995b = _0x5e38d7(_0x4a995b, _0x27d7c7);
  1675.                                        _0x4a15e6 = _0x4a995b;
  1676.                                    } else {
  1677.                                        _0x3e408e = _0x4a15e6;
  1678.                                        _0x4a15e6 = _0x56093a;
  1679.                                    }
  1680.                                } else {
  1681.                                    _0x3e408e = _0x4a15e6;
  1682.                                    _0x4a15e6 = _0x56093a;
  1683.                                }
  1684.                                return _0x4a15e6;
  1685.                            }
  1686.  
  1687.                            function _0x5e3341() {
  1688.                                var _0xf3e26, _0x5c6a34, _0x304759, _0x4e8cd7;
  1689.                                _0xf3e26 = _0x3e408e;
  1690.                                if (_0x4c4628['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1691.                                    _0x5c6a34 = _0x3a6242['charAt'](_0x3e408e);
  1692.                                    _0x3e408e++;
  1693.                                } else {
  1694.                                    _0x5c6a34 = _0x4e763b;
  1695.                                    if (_0x15e012 === 0x0) {
  1696.                                        _0x569314(_0x36aa8b);
  1697.                                    }
  1698.                                }
  1699.                                if (_0x5c6a34 !== _0x4e763b) {
  1700.                                    _0x304759 = [];
  1701.                                    _0x4e8cd7 = _0x553f5b();
  1702.                                    while (_0x4e8cd7 !== _0x4e763b) {
  1703.                                        _0x304759['push'](_0x4e8cd7);
  1704.                                        _0x4e8cd7 = _0x553f5b();
  1705.                                    }
  1706.                                    if (_0x304759 !== _0x4e763b) {
  1707.                                        _0x4e8cd7 = _0x2920d4();
  1708.                                        if (_0x4e8cd7 !== _0x4e763b) {
  1709.                                            _0x55bc2f = _0xf3e26;
  1710.                                            _0x5c6a34 = _0x487dce(_0x5c6a34, _0x4e8cd7);
  1711.                                            _0xf3e26 = _0x5c6a34;
  1712.                                        } else {
  1713.                                            _0x3e408e = _0xf3e26;
  1714.                                            _0xf3e26 = _0x56093a;
  1715.                                        }
  1716.                                    } else {
  1717.                                        _0x3e408e = _0xf3e26;
  1718.                                        _0xf3e26 = _0x56093a;
  1719.                                    }
  1720.                                } else {
  1721.                                    _0x3e408e = _0xf3e26;
  1722.                                    _0xf3e26 = _0x56093a;
  1723.                                }
  1724.                                return _0xf3e26;
  1725.                            }
  1726.  
  1727.                            function _0x2920d4() {
  1728.                                var _0x837728, _0x486290, _0x427e42, _0x48f743, _0xa4edad;
  1729.                                _0x837728 = _0x3e408e;
  1730.                                _0x486290 = _0x462d74();
  1731.                                if (_0x486290 !== _0x4e763b) {
  1732.                                    _0x427e42 = _0x3e408e;
  1733.                                    _0x48f743 = _0x5bbfe4();
  1734.                                    if (_0x48f743 === _0x4e763b) {
  1735.                                        _0x48f743 = _0x375d49;
  1736.                                    }
  1737.                                    if (_0x48f743 !== _0x4e763b) {
  1738.                                        _0xa4edad = _0x2920d4();
  1739.                                        if (_0xa4edad !== _0x4e763b) {
  1740.                                            _0x48f743 = [_0x48f743, _0xa4edad];
  1741.                                            _0x427e42 = _0x48f743;
  1742.                                        } else {
  1743.                                            _0x3e408e = _0x427e42;
  1744.                                            _0x427e42 = _0x56093a;
  1745.                                        }
  1746.                                    } else {
  1747.                                        _0x3e408e = _0x427e42;
  1748.                                        _0x427e42 = _0x56093a;
  1749.                                    }
  1750.                                    if (_0x427e42 === _0x4e763b) {
  1751.                                        _0x427e42 = _0x375d49;
  1752.                                    }
  1753.                                    if (_0x427e42 !== _0x4e763b) {
  1754.                                        _0x55bc2f = _0x837728;
  1755.                                        _0x486290 = _0x5e38d7(_0x486290, _0x427e42);
  1756.                                        _0x837728 = _0x486290;
  1757.                                    } else {
  1758.                                        _0x3e408e = _0x837728;
  1759.                                        _0x837728 = _0x56093a;
  1760.                                    }
  1761.                                } else {
  1762.                                    _0x3e408e = _0x837728;
  1763.                                    _0x837728 = _0x56093a;
  1764.                                }
  1765.                                return _0x837728;
  1766.                            }
  1767.  
  1768.                            function _0x5804f9() {
  1769.                                var _0x8965a, _0xf28695, _0x3aa646, _0x431142;
  1770.                                _0x8965a = _0x3e408e;
  1771.                                if (_0x2f8fdc['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1772.                                    _0xf28695 = _0x3a6242['charAt'](_0x3e408e);
  1773.                                    _0x3e408e++;
  1774.                                } else {
  1775.                                    _0xf28695 = _0x4e763b;
  1776.                                    if (_0x15e012 === 0x0) {
  1777.                                        _0x569314(_0x391e28);
  1778.                                    }
  1779.                                }
  1780.                                if (_0xf28695 !== _0x4e763b) {
  1781.                                    _0x3aa646 = [];
  1782.                                    _0x431142 = _0x553f5b();
  1783.                                    while (_0x431142 !== _0x4e763b) {
  1784.                                        _0x3aa646['push'](_0x431142);
  1785.                                        _0x431142 = _0x553f5b();
  1786.                                    }
  1787.                                    if (_0x3aa646 !== _0x4e763b) {
  1788.                                        _0x431142 = _0x2920d4();
  1789.                                        if (_0x431142 !== _0x4e763b) {
  1790.                                            _0x55bc2f = _0x8965a;
  1791.                                            _0xf28695 = _0x2fb111(_0xf28695, _0x431142);
  1792.                                            _0x8965a = _0xf28695;
  1793.                                        } else {
  1794.                                            _0x3e408e = _0x8965a;
  1795.                                            _0x8965a = _0x56093a;
  1796.                                        }
  1797.                                    } else {
  1798.                                        _0x3e408e = _0x8965a;
  1799.                                        _0x8965a = _0x56093a;
  1800.                                    }
  1801.                                } else {
  1802.                                    _0x3e408e = _0x8965a;
  1803.                                    _0x8965a = _0x56093a;
  1804.                                }
  1805.                                return _0x8965a;
  1806.                            }
  1807.  
  1808.                            function _0x1fa3d9() {
  1809.                                var _0x2bd81b, _0x4ead37, _0xb9e94a, _0x1f1d21;
  1810.                                _0x2bd81b = _0x3e408e;
  1811.                                if (_0x4a4882['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1812.                                    _0x4ead37 = _0x3a6242['charAt'](_0x3e408e);
  1813.                                    _0x3e408e++;
  1814.                                } else {
  1815.                                    _0x4ead37 = _0x4e763b;
  1816.                                    if (_0x15e012 === 0x0) {
  1817.                                        _0x569314(_0x1371ac);
  1818.                                    }
  1819.                                }
  1820.                                if (_0x4ead37 !== _0x4e763b) {
  1821.                                    _0xb9e94a = [];
  1822.                                    _0x1f1d21 = _0x553f5b();
  1823.                                    while (_0x1f1d21 !== _0x4e763b) {
  1824.                                        _0xb9e94a['push'](_0x1f1d21);
  1825.                                        _0x1f1d21 = _0x553f5b();
  1826.                                    }
  1827.                                    if (_0xb9e94a !== _0x4e763b) {
  1828.                                        _0x1f1d21 = _0x49f3cf();
  1829.                                        if (_0x1f1d21 !== _0x4e763b) {
  1830.                                            _0x55bc2f = _0x2bd81b;
  1831.                                            _0x4ead37 = _0x51b1f6(_0x4ead37, _0x1f1d21);
  1832.                                            _0x2bd81b = _0x4ead37;
  1833.                                        } else {
  1834.                                            _0x3e408e = _0x2bd81b;
  1835.                                            _0x2bd81b = _0x56093a;
  1836.                                        }
  1837.                                    } else {
  1838.                                        _0x3e408e = _0x2bd81b;
  1839.                                        _0x2bd81b = _0x56093a;
  1840.                                    }
  1841.                                } else {
  1842.                                    _0x3e408e = _0x2bd81b;
  1843.                                    _0x2bd81b = _0x56093a;
  1844.                                }
  1845.                                return _0x2bd81b;
  1846.                            }
  1847.  
  1848.                            function _0x49f3cf() {
  1849.                                var _0xe5c33a, _0x477328, _0x119ce9, _0xdf5b04, _0x57237e;
  1850.                                _0xe5c33a = _0x3e408e;
  1851.                                _0x477328 = _0x1a31ff();
  1852.                                if (_0x477328 !== _0x4e763b) {
  1853.                                    _0x119ce9 = _0x3e408e;
  1854.                                    _0xdf5b04 = _0x5bbfe4();
  1855.                                    if (_0xdf5b04 === _0x4e763b) {
  1856.                                        _0xdf5b04 = _0x375d49;
  1857.                                    }
  1858.                                    if (_0xdf5b04 !== _0x4e763b) {
  1859.                                        _0x57237e = _0x49f3cf();
  1860.                                        if (_0x57237e !== _0x4e763b) {
  1861.                                            _0xdf5b04 = [_0xdf5b04, _0x57237e];
  1862.                                            _0x119ce9 = _0xdf5b04;
  1863.                                        } else {
  1864.                                            _0x3e408e = _0x119ce9;
  1865.                                            _0x119ce9 = _0x56093a;
  1866.                                        }
  1867.                                    } else {
  1868.                                        _0x3e408e = _0x119ce9;
  1869.                                        _0x119ce9 = _0x56093a;
  1870.                                    }
  1871.                                    if (_0x119ce9 === _0x4e763b) {
  1872.                                        _0x119ce9 = _0x375d49;
  1873.                                    }
  1874.                                    if (_0x119ce9 !== _0x4e763b) {
  1875.                                        _0x55bc2f = _0xe5c33a;
  1876.                                        _0x477328 = _0x5e38d7(_0x477328, _0x119ce9);
  1877.                                        _0xe5c33a = _0x477328;
  1878.                                    } else {
  1879.                                        _0x3e408e = _0xe5c33a;
  1880.                                        _0xe5c33a = _0x56093a;
  1881.                                    }
  1882.                                } else {
  1883.                                    _0x3e408e = _0xe5c33a;
  1884.                                    _0xe5c33a = _0x56093a;
  1885.                                }
  1886.                                return _0xe5c33a;
  1887.                            }
  1888.  
  1889.                            function _0x1a31ff() {
  1890.                                var _0x2c770d, _0x25f1f8, _0x1b91ba, _0x12ee28, _0x425af4, _0x2feeef;
  1891.                                _0x2c770d = _0x3e408e;
  1892.                                _0x25f1f8 = _0x38a50a();
  1893.                                if (_0x25f1f8 !== _0x4e763b) {
  1894.                                    _0x1b91ba = _0x5bbfe4();
  1895.                                    if (_0x1b91ba === _0x4e763b) {
  1896.                                        _0x1b91ba = _0x375d49;
  1897.                                    }
  1898.                                    if (_0x1b91ba !== _0x4e763b) {
  1899.                                        _0x12ee28 = _0x38a50a();
  1900.                                        if (_0x12ee28 !== _0x4e763b) {
  1901.                                            _0x425af4 = _0x5bbfe4();
  1902.                                            if (_0x425af4 === _0x4e763b) {
  1903.                                                _0x425af4 = _0x375d49;
  1904.                                            }
  1905.                                            if (_0x425af4 !== _0x4e763b) {
  1906.                                                _0x2feeef = _0x38a50a();
  1907.                                                if (_0x2feeef !== _0x4e763b) {
  1908.                                                    _0x55bc2f = _0x2c770d;
  1909.                                                    _0x25f1f8 = _0xe1e1(_0x25f1f8, _0x12ee28, _0x2feeef);
  1910.                                                    _0x2c770d = _0x25f1f8;
  1911.                                                } else {
  1912.                                                    _0x3e408e = _0x2c770d;
  1913.                                                    _0x2c770d = _0x56093a;
  1914.                                                }
  1915.                                            } else {
  1916.                                                _0x3e408e = _0x2c770d;
  1917.                                                _0x2c770d = _0x56093a;
  1918.                                            }
  1919.                                        } else {
  1920.                                            _0x3e408e = _0x2c770d;
  1921.                                            _0x2c770d = _0x56093a;
  1922.                                        }
  1923.                                    } else {
  1924.                                        _0x3e408e = _0x2c770d;
  1925.                                        _0x2c770d = _0x56093a;
  1926.                                    }
  1927.                                } else {
  1928.                                    _0x3e408e = _0x2c770d;
  1929.                                    _0x2c770d = _0x56093a;
  1930.                                }
  1931.                                return _0x2c770d;
  1932.                            }
  1933.  
  1934.                            function _0x3bb24f() {
  1935.                                var _0x1efc96, _0x3533a4, _0x5baf6a, _0x3eaabf;
  1936.                                _0x1efc96 = _0x3e408e;
  1937.                                if (_0x3c0d2e['test'](_0x3a6242['charAt'](_0x3e408e))) {
  1938.                                    _0x3533a4 = _0x3a6242['charAt'](_0x3e408e);
  1939.                                    _0x3e408e++;
  1940.                                } else {
  1941.                                    _0x3533a4 = _0x4e763b;
  1942.                                    if (_0x15e012 === 0x0) {
  1943.                                        _0x569314(_0x394135);
  1944.                                    }
  1945.                                }
  1946.                                if (_0x3533a4 !== _0x4e763b) {
  1947.                                    _0x5baf6a = [];
  1948.                                    _0x3eaabf = _0x553f5b();
  1949.                                    while (_0x3eaabf !== _0x4e763b) {
  1950.                                        _0x5baf6a['push'](_0x3eaabf);
  1951.                                        _0x3eaabf = _0x553f5b();
  1952.                                    }
  1953.                                    if (_0x5baf6a !== _0x4e763b) {
  1954.                                        _0x3eaabf = _0x1effcd();
  1955.                                        if (_0x3eaabf !== _0x4e763b) {
  1956.                                            _0x55bc2f = _0x1efc96;
  1957.                                            _0x3533a4 = _0x4aa6f7(_0x3533a4, _0x3eaabf);
  1958.                                            _0x1efc96 = _0x3533a4;
  1959.                                        } else {
  1960.                                            _0x3e408e = _0x1efc96;
  1961.                                            _0x1efc96 = _0x56093a;
  1962.                                        }
  1963.                                    } else {
  1964.                                        _0x3e408e = _0x1efc96;
  1965.                                        _0x1efc96 = _0x56093a;
  1966.                                    }
  1967.                                } else {
  1968.                                    _0x3e408e = _0x1efc96;
  1969.                                    _0x1efc96 = _0x56093a;
  1970.                                }
  1971.                                return _0x1efc96;
  1972.                            }
  1973.  
  1974.                            function _0x1effcd() {
  1975.                                var _0xd15e3b, _0x2e6edc, _0x560d2e, _0x3d4eec, _0x5b4cfd;
  1976.                                _0xd15e3b = _0x3e408e;
  1977.                                _0x2e6edc = _0x52a948();
  1978.                                if (_0x2e6edc !== _0x4e763b) {
  1979.                                    _0x560d2e = _0x3e408e;
  1980.                                    _0x3d4eec = _0x5bbfe4();
  1981.                                    if (_0x3d4eec === _0x4e763b) {
  1982.                                        _0x3d4eec = _0x375d49;
  1983.                                    }
  1984.                                    if (_0x3d4eec !== _0x4e763b) {
  1985.                                        _0x5b4cfd = _0x1effcd();
  1986.                                        if (_0x5b4cfd !== _0x4e763b) {
  1987.                                            _0x3d4eec = [_0x3d4eec, _0x5b4cfd];
  1988.                                            _0x560d2e = _0x3d4eec;
  1989.                                        } else {
  1990.                                            _0x3e408e = _0x560d2e;
  1991.                                            _0x560d2e = _0x56093a;
  1992.                                        }
  1993.                                    } else {
  1994.                                        _0x3e408e = _0x560d2e;
  1995.                                        _0x560d2e = _0x56093a;
  1996.                                    }
  1997.                                    if (_0x560d2e === _0x4e763b) {
  1998.                                        _0x560d2e = _0x375d49;
  1999.                                    }
  2000.                                    if (_0x560d2e !== _0x4e763b) {
  2001.                                        _0x55bc2f = _0xd15e3b;
  2002.                                        _0x2e6edc = _0x5e38d7(_0x2e6edc, _0x560d2e);
  2003.                                        _0xd15e3b = _0x2e6edc;
  2004.                                    } else {
  2005.                                        _0x3e408e = _0xd15e3b;
  2006.                                        _0xd15e3b = _0x56093a;
  2007.                                    }
  2008.                                } else {
  2009.                                    _0x3e408e = _0xd15e3b;
  2010.                                    _0xd15e3b = _0x56093a;
  2011.                                }
  2012.                                return _0xd15e3b;
  2013.                            }
  2014.  
  2015.                            function _0x52a948() {
  2016.                                var _0x8789b3, _0x4f9331, _0x132a7a, _0x181899;
  2017.                                _0x8789b3 = _0x3e408e;
  2018.                                _0x4f9331 = _0x38a50a();
  2019.                                if (_0x4f9331 !== _0x4e763b) {
  2020.                                    _0x132a7a = _0x5bbfe4();
  2021.                                    if (_0x132a7a === _0x4e763b) {
  2022.                                        _0x132a7a = _0x375d49;
  2023.                                    }
  2024.                                    if (_0x132a7a !== _0x4e763b) {
  2025.                                        _0x181899 = _0x38a50a();
  2026.                                        if (_0x181899 !== _0x4e763b) {
  2027.                                            _0x55bc2f = _0x8789b3;
  2028.                                            _0x4f9331 = _0x30c615(_0x4f9331, _0x181899);
  2029.                                            _0x8789b3 = _0x4f9331;
  2030.                                        } else {
  2031.                                            _0x3e408e = _0x8789b3;
  2032.                                            _0x8789b3 = _0x56093a;
  2033.                                        }
  2034.                                    } else {
  2035.                                        _0x3e408e = _0x8789b3;
  2036.                                        _0x8789b3 = _0x56093a;
  2037.                                    }
  2038.                                } else {
  2039.                                    _0x3e408e = _0x8789b3;
  2040.                                    _0x8789b3 = _0x56093a;
  2041.                                }
  2042.                                return _0x8789b3;
  2043.                            }
  2044.  
  2045.                            function _0x1d0640() {
  2046.                                var _0x4bc9ab, _0x599d9a, _0x49718b, _0x23fc95;
  2047.                                _0x4bc9ab = _0x3e408e;
  2048.                                if (_0x3a67c6['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2049.                                    _0x599d9a = _0x3a6242['charAt'](_0x3e408e);
  2050.                                    _0x3e408e++;
  2051.                                } else {
  2052.                                    _0x599d9a = _0x4e763b;
  2053.                                    if (_0x15e012 === 0x0) {
  2054.                                        _0x569314(_0x85b933);
  2055.                                    }
  2056.                                }
  2057.                                if (_0x599d9a !== _0x4e763b) {
  2058.                                    _0x49718b = [];
  2059.                                    _0x23fc95 = _0x553f5b();
  2060.                                    while (_0x23fc95 !== _0x4e763b) {
  2061.                                        _0x49718b['push'](_0x23fc95);
  2062.                                        _0x23fc95 = _0x553f5b();
  2063.                                    }
  2064.                                    if (_0x49718b !== _0x4e763b) {
  2065.                                        _0x23fc95 = _0x525db0();
  2066.                                        if (_0x23fc95 !== _0x4e763b) {
  2067.                                            _0x55bc2f = _0x4bc9ab;
  2068.                                            _0x599d9a = _0x3ceb0a(_0x599d9a, _0x23fc95);
  2069.                                            _0x4bc9ab = _0x599d9a;
  2070.                                        } else {
  2071.                                            _0x3e408e = _0x4bc9ab;
  2072.                                            _0x4bc9ab = _0x56093a;
  2073.                                        }
  2074.                                    } else {
  2075.                                        _0x3e408e = _0x4bc9ab;
  2076.                                        _0x4bc9ab = _0x56093a;
  2077.                                    }
  2078.                                } else {
  2079.                                    _0x3e408e = _0x4bc9ab;
  2080.                                    _0x4bc9ab = _0x56093a;
  2081.                                }
  2082.                                return _0x4bc9ab;
  2083.                            }
  2084.  
  2085.                            function _0x525db0() {
  2086.                                var _0x58bd8f, _0x27e03c, _0x102d08, _0x59fdd8, _0xa8edd;
  2087.                                _0x58bd8f = _0x3e408e;
  2088.                                _0x27e03c = _0x48e64d();
  2089.                                if (_0x27e03c !== _0x4e763b) {
  2090.                                    _0x102d08 = _0x3e408e;
  2091.                                    _0x59fdd8 = _0x5bbfe4();
  2092.                                    if (_0x59fdd8 === _0x4e763b) {
  2093.                                        _0x59fdd8 = _0x375d49;
  2094.                                    }
  2095.                                    if (_0x59fdd8 !== _0x4e763b) {
  2096.                                        _0xa8edd = _0x525db0();
  2097.                                        if (_0xa8edd !== _0x4e763b) {
  2098.                                            _0x59fdd8 = [_0x59fdd8, _0xa8edd];
  2099.                                            _0x102d08 = _0x59fdd8;
  2100.                                        } else {
  2101.                                            _0x3e408e = _0x102d08;
  2102.                                            _0x102d08 = _0x56093a;
  2103.                                        }
  2104.                                    } else {
  2105.                                        _0x3e408e = _0x102d08;
  2106.                                        _0x102d08 = _0x56093a;
  2107.                                    }
  2108.                                    if (_0x102d08 === _0x4e763b) {
  2109.                                        _0x102d08 = _0x375d49;
  2110.                                    }
  2111.                                    if (_0x102d08 !== _0x4e763b) {
  2112.                                        _0x55bc2f = _0x58bd8f;
  2113.                                        _0x27e03c = _0x5e38d7(_0x27e03c, _0x102d08);
  2114.                                        _0x58bd8f = _0x27e03c;
  2115.                                    } else {
  2116.                                        _0x3e408e = _0x58bd8f;
  2117.                                        _0x58bd8f = _0x56093a;
  2118.                                    }
  2119.                                } else {
  2120.                                    _0x3e408e = _0x58bd8f;
  2121.                                    _0x58bd8f = _0x56093a;
  2122.                                }
  2123.                                return _0x58bd8f;
  2124.                            }
  2125.  
  2126.                            function _0x48e64d() {
  2127.                                var _0x5986f2, _0x42674d, _0x3d238c, _0x4fc37e;
  2128.                                _0x5986f2 = _0x3e408e;
  2129.                                _0x42674d = _0x38a50a();
  2130.                                if (_0x42674d !== _0x4e763b) {
  2131.                                    _0x3d238c = _0x5bbfe4();
  2132.                                    if (_0x3d238c === _0x4e763b) {
  2133.                                        _0x3d238c = _0x375d49;
  2134.                                    }
  2135.                                    if (_0x3d238c !== _0x4e763b) {
  2136.                                        _0x4fc37e = _0x38a50a();
  2137.                                        if (_0x4fc37e !== _0x4e763b) {
  2138.                                            _0x55bc2f = _0x5986f2;
  2139.                                            _0x42674d = _0x30c615(_0x42674d, _0x4fc37e);
  2140.                                            _0x5986f2 = _0x42674d;
  2141.                                        } else {
  2142.                                            _0x3e408e = _0x5986f2;
  2143.                                            _0x5986f2 = _0x56093a;
  2144.                                        }
  2145.                                    } else {
  2146.                                        _0x3e408e = _0x5986f2;
  2147.                                        _0x5986f2 = _0x56093a;
  2148.                                    }
  2149.                                } else {
  2150.                                    _0x3e408e = _0x5986f2;
  2151.                                    _0x5986f2 = _0x56093a;
  2152.                                }
  2153.                                return _0x5986f2;
  2154.                            }
  2155.  
  2156.                            function _0x348547() {
  2157.                                var _0x5a90a2, _0x15ac19, _0x5d1d81, _0x2bfd38;
  2158.                                _0x5a90a2 = _0x3e408e;
  2159.                                if (_0x543bea['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2160.                                    _0x15ac19 = _0x3a6242['charAt'](_0x3e408e);
  2161.                                    _0x3e408e++;
  2162.                                } else {
  2163.                                    _0x15ac19 = _0x4e763b;
  2164.                                    if (_0x15e012 === 0x0) {
  2165.                                        _0x569314(_0x16de6e);
  2166.                                    }
  2167.                                }
  2168.                                if (_0x15ac19 !== _0x4e763b) {
  2169.                                    _0x5d1d81 = [];
  2170.                                    _0x2bfd38 = _0x553f5b();
  2171.                                    while (_0x2bfd38 !== _0x4e763b) {
  2172.                                        _0x5d1d81['push'](_0x2bfd38);
  2173.                                        _0x2bfd38 = _0x553f5b();
  2174.                                    }
  2175.                                    if (_0x5d1d81 !== _0x4e763b) {
  2176.                                        _0x2bfd38 = _0x18fab1();
  2177.                                        if (_0x2bfd38 !== _0x4e763b) {
  2178.                                            _0x55bc2f = _0x5a90a2;
  2179.                                            _0x15ac19 = _0x207488(_0x15ac19, _0x2bfd38);
  2180.                                            _0x5a90a2 = _0x15ac19;
  2181.                                        } else {
  2182.                                            _0x3e408e = _0x5a90a2;
  2183.                                            _0x5a90a2 = _0x56093a;
  2184.                                        }
  2185.                                    } else {
  2186.                                        _0x3e408e = _0x5a90a2;
  2187.                                        _0x5a90a2 = _0x56093a;
  2188.                                    }
  2189.                                } else {
  2190.                                    _0x3e408e = _0x5a90a2;
  2191.                                    _0x5a90a2 = _0x56093a;
  2192.                                }
  2193.                                return _0x5a90a2;
  2194.                            }
  2195.  
  2196.                            function _0x18fab1() {
  2197.                                var _0x4ce267, _0x2c1571, _0x536ee2, _0x33dfbc, _0x36236f;
  2198.                                _0x4ce267 = _0x3e408e;
  2199.                                _0x2c1571 = _0x38a50a();
  2200.                                if (_0x2c1571 !== _0x4e763b) {
  2201.                                    _0x536ee2 = _0x3e408e;
  2202.                                    _0x33dfbc = _0x5bbfe4();
  2203.                                    if (_0x33dfbc === _0x4e763b) {
  2204.                                        _0x33dfbc = _0x375d49;
  2205.                                    }
  2206.                                    if (_0x33dfbc !== _0x4e763b) {
  2207.                                        _0x36236f = _0x18fab1();
  2208.                                        if (_0x36236f !== _0x4e763b) {
  2209.                                            _0x33dfbc = [_0x33dfbc, _0x36236f];
  2210.                                            _0x536ee2 = _0x33dfbc;
  2211.                                        } else {
  2212.                                            _0x3e408e = _0x536ee2;
  2213.                                            _0x536ee2 = _0x56093a;
  2214.                                        }
  2215.                                    } else {
  2216.                                        _0x3e408e = _0x536ee2;
  2217.                                        _0x536ee2 = _0x56093a;
  2218.                                    }
  2219.                                    if (_0x536ee2 === _0x4e763b) {
  2220.                                        _0x536ee2 = _0x375d49;
  2221.                                    }
  2222.                                    if (_0x536ee2 !== _0x4e763b) {
  2223.                                        _0x55bc2f = _0x4ce267;
  2224.                                        _0x2c1571 = _0x5e38d7(_0x2c1571, _0x536ee2);
  2225.                                        _0x4ce267 = _0x2c1571;
  2226.                                    } else {
  2227.                                        _0x3e408e = _0x4ce267;
  2228.                                        _0x4ce267 = _0x56093a;
  2229.                                    }
  2230.                                } else {
  2231.                                    _0x3e408e = _0x4ce267;
  2232.                                    _0x4ce267 = _0x56093a;
  2233.                                }
  2234.                                return _0x4ce267;
  2235.                            }
  2236.  
  2237.                            function _0x553067() {
  2238.                                var _0x241dc9, _0x3a69e5, _0x52a19f, _0x5ed547;
  2239.                                _0x241dc9 = _0x3e408e;
  2240.                                if (_0xd18715['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2241.                                    _0x3a69e5 = _0x3a6242['charAt'](_0x3e408e);
  2242.                                    _0x3e408e++;
  2243.                                } else {
  2244.                                    _0x3a69e5 = _0x4e763b;
  2245.                                    if (_0x15e012 === 0x0) {
  2246.                                        _0x569314(_0x30a6b0);
  2247.                                    }
  2248.                                }
  2249.                                if (_0x3a69e5 !== _0x4e763b) {
  2250.                                    _0x52a19f = [];
  2251.                                    _0x5ed547 = _0x553f5b();
  2252.                                    while (_0x5ed547 !== _0x4e763b) {
  2253.                                        _0x52a19f['push'](_0x5ed547);
  2254.                                        _0x5ed547 = _0x553f5b();
  2255.                                    }
  2256.                                    if (_0x52a19f !== _0x4e763b) {
  2257.                                        _0x5ed547 = _0x21d7c9();
  2258.                                        if (_0x5ed547 !== _0x4e763b) {
  2259.                                            _0x55bc2f = _0x241dc9;
  2260.                                            _0x3a69e5 = _0xbeac27(_0x3a69e5, _0x5ed547);
  2261.                                            _0x241dc9 = _0x3a69e5;
  2262.                                        } else {
  2263.                                            _0x3e408e = _0x241dc9;
  2264.                                            _0x241dc9 = _0x56093a;
  2265.                                        }
  2266.                                    } else {
  2267.                                        _0x3e408e = _0x241dc9;
  2268.                                        _0x241dc9 = _0x56093a;
  2269.                                    }
  2270.                                } else {
  2271.                                    _0x3e408e = _0x241dc9;
  2272.                                    _0x241dc9 = _0x56093a;
  2273.                                }
  2274.                                return _0x241dc9;
  2275.                            }
  2276.  
  2277.                            function _0x21d7c9() {
  2278.                                var _0x2f2dca, _0x2b58d6, _0x17db3e, _0x795ed1, _0x3cc0de;
  2279.                                _0x2f2dca = _0x3e408e;
  2280.                                _0x2b58d6 = _0x4eedd3();
  2281.                                if (_0x2b58d6 !== _0x4e763b) {
  2282.                                    _0x17db3e = _0x3e408e;
  2283.                                    _0x795ed1 = _0x5bbfe4();
  2284.                                    if (_0x795ed1 === _0x4e763b) {
  2285.                                        _0x795ed1 = _0x375d49;
  2286.                                    }
  2287.                                    if (_0x795ed1 !== _0x4e763b) {
  2288.                                        _0x3cc0de = _0x21d7c9();
  2289.                                        if (_0x3cc0de !== _0x4e763b) {
  2290.                                            _0x795ed1 = [_0x795ed1, _0x3cc0de];
  2291.                                            _0x17db3e = _0x795ed1;
  2292.                                        } else {
  2293.                                            _0x3e408e = _0x17db3e;
  2294.                                            _0x17db3e = _0x56093a;
  2295.                                        }
  2296.                                    } else {
  2297.                                        _0x3e408e = _0x17db3e;
  2298.                                        _0x17db3e = _0x56093a;
  2299.                                    }
  2300.                                    if (_0x17db3e === _0x4e763b) {
  2301.                                        _0x17db3e = _0x375d49;
  2302.                                    }
  2303.                                    if (_0x17db3e !== _0x4e763b) {
  2304.                                        _0x55bc2f = _0x2f2dca;
  2305.                                        _0x2b58d6 = _0x5e38d7(_0x2b58d6, _0x17db3e);
  2306.                                        _0x2f2dca = _0x2b58d6;
  2307.                                    } else {
  2308.                                        _0x3e408e = _0x2f2dca;
  2309.                                        _0x2f2dca = _0x56093a;
  2310.                                    }
  2311.                                } else {
  2312.                                    _0x3e408e = _0x2f2dca;
  2313.                                    _0x2f2dca = _0x56093a;
  2314.                                }
  2315.                                return _0x2f2dca;
  2316.                            }
  2317.  
  2318.                            function _0x4eedd3() {
  2319.                                var _0x10205c, _0x280c0a, _0x436886, _0x3c8efd, _0x5d6240, _0x151e7d, _0x5e6210, _0x525f36, _0x167195, _0x451acb, _0x4e74a4, _0x460bfa;
  2320.                                _0x10205c = _0x3e408e;
  2321.                                _0x280c0a = _0x442fed();
  2322.                                if (_0x280c0a !== _0x4e763b) {
  2323.                                    _0x436886 = _0x5bbfe4();
  2324.                                    if (_0x436886 === _0x4e763b) {
  2325.                                        _0x436886 = _0x375d49;
  2326.                                    }
  2327.                                    if (_0x436886 !== _0x4e763b) {
  2328.                                        _0x3c8efd = _0x442fed();
  2329.                                        if (_0x3c8efd !== _0x4e763b) {
  2330.                                            _0x5d6240 = _0x5bbfe4();
  2331.                                            if (_0x5d6240 === _0x4e763b) {
  2332.                                                _0x5d6240 = _0x375d49;
  2333.                                            }
  2334.                                            if (_0x5d6240 !== _0x4e763b) {
  2335.                                                _0x151e7d = _0x33fb0d();
  2336.                                                if (_0x151e7d !== _0x4e763b) {
  2337.                                                    _0x5e6210 = _0x5bbfe4();
  2338.                                                    if (_0x5e6210 !== _0x4e763b) {
  2339.                                                        _0x525f36 = _0x15076b();
  2340.                                                        if (_0x525f36 !== _0x4e763b) {
  2341.                                                            _0x167195 = _0x5bbfe4();
  2342.                                                            if (_0x167195 === _0x4e763b) {
  2343.                                                                _0x167195 = _0x375d49;
  2344.                                                            }
  2345.                                                            if (_0x167195 !== _0x4e763b) {
  2346.                                                                _0x451acb = _0x15076b();
  2347.                                                                if (_0x451acb !== _0x4e763b) {
  2348.                                                                    _0x4e74a4 = _0x5bbfe4();
  2349.                                                                    if (_0x4e74a4 === _0x4e763b) {
  2350.                                                                        _0x4e74a4 = _0x375d49;
  2351.                                                                    }
  2352.                                                                    if (_0x4e74a4 !== _0x4e763b) {
  2353.                                                                        _0x460bfa = _0x38a50a();
  2354.                                                                        if (_0x460bfa !== _0x4e763b) {
  2355.                                                                            _0x55bc2f = _0x10205c;
  2356.                                                                            _0x280c0a = _0x2cbb71(_0x280c0a, _0x3c8efd, _0x151e7d, _0x525f36, _0x451acb, _0x460bfa);
  2357.                                                                            _0x10205c = _0x280c0a;
  2358.                                                                        } else {
  2359.                                                                            _0x3e408e = _0x10205c;
  2360.                                                                            _0x10205c = _0x56093a;
  2361.                                                                        }
  2362.                                                                    } else {
  2363.                                                                        _0x3e408e = _0x10205c;
  2364.                                                                        _0x10205c = _0x56093a;
  2365.                                                                    }
  2366.                                                                } else {
  2367.                                                                    _0x3e408e = _0x10205c;
  2368.                                                                    _0x10205c = _0x56093a;
  2369.                                                                }
  2370.                                                            } else {
  2371.                                                                _0x3e408e = _0x10205c;
  2372.                                                                _0x10205c = _0x56093a;
  2373.                                                            }
  2374.                                                        } else {
  2375.                                                            _0x3e408e = _0x10205c;
  2376.                                                            _0x10205c = _0x56093a;
  2377.                                                        }
  2378.                                                    } else {
  2379.                                                        _0x3e408e = _0x10205c;
  2380.                                                        _0x10205c = _0x56093a;
  2381.                                                    }
  2382.                                                } else {
  2383.                                                    _0x3e408e = _0x10205c;
  2384.                                                    _0x10205c = _0x56093a;
  2385.                                                }
  2386.                                            } else {
  2387.                                                _0x3e408e = _0x10205c;
  2388.                                                _0x10205c = _0x56093a;
  2389.                                            }
  2390.                                        } else {
  2391.                                            _0x3e408e = _0x10205c;
  2392.                                            _0x10205c = _0x56093a;
  2393.                                        }
  2394.                                    } else {
  2395.                                        _0x3e408e = _0x10205c;
  2396.                                        _0x10205c = _0x56093a;
  2397.                                    }
  2398.                                } else {
  2399.                                    _0x3e408e = _0x10205c;
  2400.                                    _0x10205c = _0x56093a;
  2401.                                }
  2402.                                return _0x10205c;
  2403.                            }
  2404.  
  2405.                            function _0x38a50a() {
  2406.                                var _0x28b05c, _0x15aa6a, _0x27e6b7, _0x36c52b;
  2407.                                _0x28b05c = _0x3e408e;
  2408.                                _0x15aa6a = _0x462d74();
  2409.                                if (_0x15aa6a !== _0x4e763b) {
  2410.                                    _0x27e6b7 = _0x5bbfe4();
  2411.                                    if (_0x27e6b7 === _0x4e763b) {
  2412.                                        _0x27e6b7 = _0x375d49;
  2413.                                    }
  2414.                                    if (_0x27e6b7 !== _0x4e763b) {
  2415.                                        _0x36c52b = _0x462d74();
  2416.                                        if (_0x36c52b !== _0x4e763b) {
  2417.                                            _0x55bc2f = _0x28b05c;
  2418.                                            _0x15aa6a = _0x201fa4(_0x15aa6a, _0x36c52b);
  2419.                                            _0x28b05c = _0x15aa6a;
  2420.                                        } else {
  2421.                                            _0x3e408e = _0x28b05c;
  2422.                                            _0x28b05c = _0x56093a;
  2423.                                        }
  2424.                                    } else {
  2425.                                        _0x3e408e = _0x28b05c;
  2426.                                        _0x28b05c = _0x56093a;
  2427.                                    }
  2428.                                } else {
  2429.                                    _0x3e408e = _0x28b05c;
  2430.                                    _0x28b05c = _0x56093a;
  2431.                                }
  2432.                                return _0x28b05c;
  2433.                            }
  2434.  
  2435.                            function _0x462d74() {
  2436.                                var _0x4e23cc, _0x3d1d23;
  2437.                                _0x4e23cc = _0x3e408e;
  2438.                                _0x3d1d23 = _0x33fb0d();
  2439.                                if (_0x3d1d23 !== _0x4e763b) {
  2440.                                    _0x55bc2f = _0x4e23cc;
  2441.                                    _0x3d1d23 = _0x5a72e5(_0x3d1d23);
  2442.                                }
  2443.                                _0x4e23cc = _0x3d1d23;
  2444.                                return _0x4e23cc;
  2445.                            }
  2446.  
  2447.                            function _0x442fed() {
  2448.                                var _0x5b5bca;
  2449.                                _0x5b5bca = _0x1aacaf();
  2450.                                if (_0x5b5bca === _0x4e763b) {
  2451.                                    _0x5b5bca = _0x501b81();
  2452.                                }
  2453.                                return _0x5b5bca;
  2454.                            }
  2455.  
  2456.                            function _0x33fb0d() {
  2457.                                var _0x150415, _0xe8558, _0x34fdae;
  2458.                                _0x150415 = _0x3e408e;
  2459.                                _0xe8558 = _0x48a226();
  2460.                                if (_0xe8558 === _0x4e763b) {
  2461.                                    _0xe8558 = _0x375d49;
  2462.                                }
  2463.                                if (_0xe8558 !== _0x4e763b) {
  2464.                                    _0x34fdae = _0x1aacaf();
  2465.                                    if (_0x34fdae !== _0x4e763b) {
  2466.                                        _0xe8558 = [_0xe8558, _0x34fdae];
  2467.                                        _0x150415 = _0xe8558;
  2468.                                    } else {
  2469.                                        _0x3e408e = _0x150415;
  2470.                                        _0x150415 = _0x56093a;
  2471.                                    }
  2472.                                } else {
  2473.                                    _0x3e408e = _0x150415;
  2474.                                    _0x150415 = _0x56093a;
  2475.                                }
  2476.                                if (_0x150415 === _0x4e763b) {
  2477.                                    _0x150415 = _0x3e408e;
  2478.                                    _0xe8558 = _0x48a226();
  2479.                                    if (_0xe8558 === _0x4e763b) {
  2480.                                        _0xe8558 = _0x375d49;
  2481.                                    }
  2482.                                    if (_0xe8558 !== _0x4e763b) {
  2483.                                        _0x34fdae = _0x501b81();
  2484.                                        if (_0x34fdae !== _0x4e763b) {
  2485.                                            _0xe8558 = [_0xe8558, _0x34fdae];
  2486.                                            _0x150415 = _0xe8558;
  2487.                                        } else {
  2488.                                            _0x3e408e = _0x150415;
  2489.                                            _0x150415 = _0x56093a;
  2490.                                        }
  2491.                                    } else {
  2492.                                        _0x3e408e = _0x150415;
  2493.                                        _0x150415 = _0x56093a;
  2494.                                    }
  2495.                                }
  2496.                                return _0x150415;
  2497.                            }
  2498.  
  2499.                            function _0x15076b() {
  2500.                                var _0x1961e0;
  2501.                                if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x30) {
  2502.                                    _0x1961e0 = _0x444dd7;
  2503.                                    _0x3e408e++;
  2504.                                } else {
  2505.                                    _0x1961e0 = _0x4e763b;
  2506.                                    if (_0x15e012 === 0x0) {
  2507.                                        _0x569314(_0x44e46d);
  2508.                                    }
  2509.                                }
  2510.                                if (_0x1961e0 === _0x4e763b) {
  2511.                                    if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x31) {
  2512.                                        _0x1961e0 = _0x8b2ec9;
  2513.                                        _0x3e408e++;
  2514.                                    } else {
  2515.                                        _0x1961e0 = _0x4e763b;
  2516.                                        if (_0x15e012 === 0x0) {
  2517.                                            _0x569314(_0x2bab45);
  2518.                                        }
  2519.                                    }
  2520.                                }
  2521.                                return _0x1961e0;
  2522.                            }
  2523.  
  2524.                            function _0x5bbfe4() {
  2525.                                var _0x1b120d, _0x19a767, _0x218bca, _0x4c8546, _0x4e4c52;
  2526.                                _0x1b120d = _0x3e408e;
  2527.                                _0x19a767 = [];
  2528.                                _0x218bca = _0x553f5b();
  2529.                                if (_0x218bca !== _0x4e763b) {
  2530.                                    while (_0x218bca !== _0x4e763b) {
  2531.                                        _0x19a767['push'](_0x218bca);
  2532.                                        _0x218bca = _0x553f5b();
  2533.                                    }
  2534.                                } else {
  2535.                                    _0x19a767 = _0x56093a;
  2536.                                }
  2537.                                if (_0x19a767 !== _0x4e763b) {
  2538.                                    _0x218bca = _0x177a0e();
  2539.                                    if (_0x218bca === _0x4e763b) {
  2540.                                        _0x218bca = _0x375d49;
  2541.                                    }
  2542.                                    if (_0x218bca !== _0x4e763b) {
  2543.                                        _0x4c8546 = [];
  2544.                                        _0x4e4c52 = _0x553f5b();
  2545.                                        while (_0x4e4c52 !== _0x4e763b) {
  2546.                                            _0x4c8546['push'](_0x4e4c52);
  2547.                                            _0x4e4c52 = _0x553f5b();
  2548.                                        }
  2549.                                        if (_0x4c8546 !== _0x4e763b) {
  2550.                                            _0x19a767 = [_0x19a767, _0x218bca, _0x4c8546];
  2551.                                            _0x1b120d = _0x19a767;
  2552.                                        } else {
  2553.                                            _0x3e408e = _0x1b120d;
  2554.                                            _0x1b120d = _0x56093a;
  2555.                                        }
  2556.                                    } else {
  2557.                                        _0x3e408e = _0x1b120d;
  2558.                                        _0x1b120d = _0x56093a;
  2559.                                    }
  2560.                                } else {
  2561.                                    _0x3e408e = _0x1b120d;
  2562.                                    _0x1b120d = _0x56093a;
  2563.                                }
  2564.                                if (_0x1b120d === _0x4e763b) {
  2565.                                    _0x1b120d = _0x3e408e;
  2566.                                    _0x19a767 = _0x177a0e();
  2567.                                    if (_0x19a767 !== _0x4e763b) {
  2568.                                        _0x218bca = [];
  2569.                                        _0x4c8546 = _0x553f5b();
  2570.                                        while (_0x4c8546 !== _0x4e763b) {
  2571.                                            _0x218bca['push'](_0x4c8546);
  2572.                                            _0x4c8546 = _0x553f5b();
  2573.                                        }
  2574.                                        if (_0x218bca !== _0x4e763b) {
  2575.                                            _0x19a767 = [_0x19a767, _0x218bca];
  2576.                                            _0x1b120d = _0x19a767;
  2577.                                        } else {
  2578.                                            _0x3e408e = _0x1b120d;
  2579.                                            _0x1b120d = _0x56093a;
  2580.                                        }
  2581.                                    } else {
  2582.                                        _0x3e408e = _0x1b120d;
  2583.                                        _0x1b120d = _0x56093a;
  2584.                                    }
  2585.                                }
  2586.                                return _0x1b120d;
  2587.                            }
  2588.  
  2589.                            function _0x177a0e() {
  2590.                                var _0x48f3b1;
  2591.                                if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x2c) {
  2592.                                    _0x48f3b1 = _0x5b6dde;
  2593.                                    _0x3e408e++;
  2594.                                } else {
  2595.                                    _0x48f3b1 = _0x4e763b;
  2596.                                    if (_0x15e012 === 0x0) {
  2597.                                        _0x569314(_0x3d3d23);
  2598.                                    }
  2599.                                }
  2600.                                return _0x48f3b1;
  2601.                            }
  2602.  
  2603.                            function _0x1aacaf() {
  2604.                                var _0x1d3f41, _0x56163c, _0x5baf4d;
  2605.                                _0x1d3f41 = _0x3e408e;
  2606.                                _0x56163c = _0x1f553a();
  2607.                                if (_0x56163c !== _0x4e763b) {
  2608.                                    _0x5baf4d = _0x22dc18();
  2609.                                    if (_0x5baf4d === _0x4e763b) {
  2610.                                        _0x5baf4d = _0x375d49;
  2611.                                    }
  2612.                                    if (_0x5baf4d !== _0x4e763b) {
  2613.                                        _0x56163c = [_0x56163c, _0x5baf4d];
  2614.                                        _0x1d3f41 = _0x56163c;
  2615.                                    } else {
  2616.                                        _0x3e408e = _0x1d3f41;
  2617.                                        _0x1d3f41 = _0x56093a;
  2618.                                    }
  2619.                                } else {
  2620.                                    _0x3e408e = _0x1d3f41;
  2621.                                    _0x1d3f41 = _0x56093a;
  2622.                                }
  2623.                                if (_0x1d3f41 === _0x4e763b) {
  2624.                                    _0x1d3f41 = _0x3e408e;
  2625.                                    _0x56163c = _0x501b81();
  2626.                                    if (_0x56163c !== _0x4e763b) {
  2627.                                        _0x5baf4d = _0x22dc18();
  2628.                                        if (_0x5baf4d !== _0x4e763b) {
  2629.                                            _0x56163c = [_0x56163c, _0x5baf4d];
  2630.                                            _0x1d3f41 = _0x56163c;
  2631.                                        } else {
  2632.                                            _0x3e408e = _0x1d3f41;
  2633.                                            _0x1d3f41 = _0x56093a;
  2634.                                        }
  2635.                                    } else {
  2636.                                        _0x3e408e = _0x1d3f41;
  2637.                                        _0x1d3f41 = _0x56093a;
  2638.                                    }
  2639.                                }
  2640.                                return _0x1d3f41;
  2641.                            }
  2642.  
  2643.                            function _0x1f553a() {
  2644.                                var _0x28b12e, _0x3867ef, _0x4227d4, _0x28fdd3;
  2645.                                _0x28b12e = _0x3e408e;
  2646.                                _0x3867ef = _0x501b81();
  2647.                                if (_0x3867ef === _0x4e763b) {
  2648.                                    _0x3867ef = _0x375d49;
  2649.                                }
  2650.                                if (_0x3867ef !== _0x4e763b) {
  2651.                                    if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x2e) {
  2652.                                        _0x4227d4 = _0x57d0b1;
  2653.                                        _0x3e408e++;
  2654.                                    } else {
  2655.                                        _0x4227d4 = _0x4e763b;
  2656.                                        if (_0x15e012 === 0x0) {
  2657.                                            _0x569314(_0x3e764);
  2658.                                        }
  2659.                                    }
  2660.                                    if (_0x4227d4 !== _0x4e763b) {
  2661.                                        _0x28fdd3 = _0x501b81();
  2662.                                        if (_0x28fdd3 !== _0x4e763b) {
  2663.                                            _0x3867ef = [_0x3867ef, _0x4227d4, _0x28fdd3];
  2664.                                            _0x28b12e = _0x3867ef;
  2665.                                        } else {
  2666.                                            _0x3e408e = _0x28b12e;
  2667.                                            _0x28b12e = _0x56093a;
  2668.                                        }
  2669.                                    } else {
  2670.                                        _0x3e408e = _0x28b12e;
  2671.                                        _0x28b12e = _0x56093a;
  2672.                                    }
  2673.                                } else {
  2674.                                    _0x3e408e = _0x28b12e;
  2675.                                    _0x28b12e = _0x56093a;
  2676.                                }
  2677.                                if (_0x28b12e === _0x4e763b) {
  2678.                                    _0x28b12e = _0x3e408e;
  2679.                                    _0x3867ef = _0x501b81();
  2680.                                    if (_0x3867ef !== _0x4e763b) {
  2681.                                        if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x2e) {
  2682.                                            _0x4227d4 = _0x57d0b1;
  2683.                                            _0x3e408e++;
  2684.                                        } else {
  2685.                                            _0x4227d4 = _0x4e763b;
  2686.                                            if (_0x15e012 === 0x0) {
  2687.                                                _0x569314(_0x3e764);
  2688.                                            }
  2689.                                        }
  2690.                                        if (_0x4227d4 !== _0x4e763b) {
  2691.                                            _0x3867ef = [_0x3867ef, _0x4227d4];
  2692.                                            _0x28b12e = _0x3867ef;
  2693.                                        } else {
  2694.                                            _0x3e408e = _0x28b12e;
  2695.                                            _0x28b12e = _0x56093a;
  2696.                                        }
  2697.                                    } else {
  2698.                                        _0x3e408e = _0x28b12e;
  2699.                                        _0x28b12e = _0x56093a;
  2700.                                    }
  2701.                                }
  2702.                                return _0x28b12e;
  2703.                            }
  2704.  
  2705.                            function _0x22dc18() {
  2706.                                var _0x10eb16, _0x746fd4, _0x2bd004, _0x402e7e;
  2707.                                _0x10eb16 = _0x3e408e;
  2708.                                if (_0x1e3f99['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2709.                                    _0x746fd4 = _0x3a6242['charAt'](_0x3e408e);
  2710.                                    _0x3e408e++;
  2711.                                } else {
  2712.                                    _0x746fd4 = _0x4e763b;
  2713.                                    if (_0x15e012 === 0x0) {
  2714.                                        _0x569314(_0x1123fe);
  2715.                                    }
  2716.                                }
  2717.                                if (_0x746fd4 !== _0x4e763b) {
  2718.                                    _0x2bd004 = _0x48a226();
  2719.                                    if (_0x2bd004 === _0x4e763b) {
  2720.                                        _0x2bd004 = _0x375d49;
  2721.                                    }
  2722.                                    if (_0x2bd004 !== _0x4e763b) {
  2723.                                        _0x402e7e = _0x501b81();
  2724.                                        if (_0x402e7e !== _0x4e763b) {
  2725.                                            _0x746fd4 = [_0x746fd4, _0x2bd004, _0x402e7e];
  2726.                                            _0x10eb16 = _0x746fd4;
  2727.                                        } else {
  2728.                                            _0x3e408e = _0x10eb16;
  2729.                                            _0x10eb16 = _0x56093a;
  2730.                                        }
  2731.                                    } else {
  2732.                                        _0x3e408e = _0x10eb16;
  2733.                                        _0x10eb16 = _0x56093a;
  2734.                                    }
  2735.                                } else {
  2736.                                    _0x3e408e = _0x10eb16;
  2737.                                    _0x10eb16 = _0x56093a;
  2738.                                }
  2739.                                return _0x10eb16;
  2740.                            }
  2741.  
  2742.                            function _0x48a226() {
  2743.                                var _0x30442e;
  2744.                                if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x2b) {
  2745.                                    _0x30442e = _0x59832c;
  2746.                                    _0x3e408e++;
  2747.                                } else {
  2748.                                    _0x30442e = _0x4e763b;
  2749.                                    if (_0x15e012 === 0x0) {
  2750.                                        _0x569314(_0x423117);
  2751.                                    }
  2752.                                }
  2753.                                if (_0x30442e === _0x4e763b) {
  2754.                                    if (_0x3a6242['charCodeAt'](_0x3e408e) === 0x2d) {
  2755.                                        _0x30442e = _0xf5aaab;
  2756.                                        _0x3e408e++;
  2757.                                    } else {
  2758.                                        _0x30442e = _0x4e763b;
  2759.                                        if (_0x15e012 === 0x0) {
  2760.                                            _0x569314(_0x198f27);
  2761.                                        }
  2762.                                    }
  2763.                                }
  2764.                                return _0x30442e;
  2765.                            }
  2766.  
  2767.                            function _0x501b81() {
  2768.                                var _0x3405a5, _0x388e32, _0x5cddad;
  2769.                                _0x3405a5 = _0x3e408e;
  2770.                                _0x388e32 = [];
  2771.                                if (_0x1d19eb['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2772.                                    _0x5cddad = _0x3a6242['charAt'](_0x3e408e);
  2773.                                    _0x3e408e++;
  2774.                                } else {
  2775.                                    _0x5cddad = _0x4e763b;
  2776.                                    if (_0x15e012 === 0x0) {
  2777.                                        _0x569314(_0x2a6cc4);
  2778.                                    }
  2779.                                }
  2780.                                if (_0x5cddad !== _0x4e763b) {
  2781.                                    while (_0x5cddad !== _0x4e763b) {
  2782.                                        _0x388e32['push'](_0x5cddad);
  2783.                                        if (_0x1d19eb['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2784.                                            _0x5cddad = _0x3a6242['charAt'](_0x3e408e);
  2785.                                            _0x3e408e++;
  2786.                                        } else {
  2787.                                            _0x5cddad = _0x4e763b;
  2788.                                            if (_0x15e012 === 0x0) {
  2789.                                                _0x569314(_0x2a6cc4);
  2790.                                            }
  2791.                                        }
  2792.                                    }
  2793.                                } else {
  2794.                                    _0x388e32 = _0x56093a;
  2795.                                }
  2796.                                if (_0x388e32 !== _0x4e763b) {
  2797.                                    _0x55bc2f = _0x3405a5;
  2798.                                    _0x388e32 = _0x3a87d5(_0x388e32);
  2799.                                }
  2800.                                _0x3405a5 = _0x388e32;
  2801.                                return _0x3405a5;
  2802.                            }
  2803.  
  2804.                            function _0x553f5b() {
  2805.                                var _0x52f7d4;
  2806.                                if (_0x15ce60['test'](_0x3a6242['charAt'](_0x3e408e))) {
  2807.                                    _0x52f7d4 = _0x3a6242['charAt'](_0x3e408e);
  2808.                                    _0x3e408e++;
  2809.                                } else {
  2810.                                    _0x52f7d4 = _0x4e763b;
  2811.                                    if (_0x15e012 === 0x0) {
  2812.                                        _0x569314(_0x41f84b);
  2813.                                    }
  2814.                                }
  2815.                                return _0x52f7d4;
  2816.                            }
  2817.                            var _0x5b0427 = [0x0, 0x0];
  2818.                            var _0x594746 = [0x0, 0x0];
  2819.                            var _0x65b89a = [];
  2820.                            var _0x52dd75 = !![];
  2821.                            var _0x5d45c1 = '';
  2822.  
  2823.                            function _0x4eee96(_0x1918a7) {
  2824.                                var _0x1c220a = [];
  2825.                                for (var _0x4a2cee = 0x0; _0x4a2cee < _0x1918a7['length']; _0x4a2cee++) {
  2826.                                    if (_0x1918a7[_0x4a2cee] instanceof Array) {
  2827.                                        _0x1c220a['push']['apply'](_0x1c220a, _0x4eee96(_0x1918a7[_0x4a2cee]));
  2828.                                    } else {
  2829.                                        _0x1c220a['push'](_0x1918a7[_0x4a2cee]);
  2830.                                    }
  2831.                                }
  2832.                                return _0x1c220a;
  2833.                            }
  2834.  
  2835.                            function _0x17d776(_0x345c90, _0xb69db9) {
  2836.                                if ('mlazhvcsqt' ['indexOf'](_0x345c90) === -0x1) {
  2837.                                    _0x5b0427 = _0xb69db9;
  2838.                                } else {
  2839.                                    _0x5b0427[0x0] += _0xb69db9[0x0];
  2840.                                    _0x5b0427[0x1] += _0xb69db9[0x1];
  2841.                                }
  2842.                                _0x5d45c1 = _0x345c90;
  2843.                                return _0x5b0427['slice'](0x0);
  2844.                            }
  2845.  
  2846.                            function _0x54e14f(_0xa6104a, _0x4c5d11) {
  2847.                                var _0x5f1573 = [];
  2848.                                var _0x4e994b = _0x5b0427['slice'](0x0);
  2849.                                for (var _0x34ce1a = 0x0; _0x34ce1a < _0x4c5d11['length']; _0x34ce1a += 0x2) {
  2850.                                    _0x5b0427 = _0x4e994b['slice'](0x0);
  2851.                                    var _0x4d36b1 = _0x17d776(_0xa6104a, _0x4c5d11['slice'](_0x34ce1a, _0x34ce1a + 0x2));
  2852.                                    _0x5f1573 = _0x5f1573['concat'](_0x4d36b1);
  2853.                                    if (_0x34ce1a == _0x4c5d11['length'] - 0x4) {
  2854.                                        _0x594746 = _0x4d36b1['slice'](0x0);
  2855.                                    }
  2856.                                }
  2857.                                return _0x5f1573;
  2858.                            }
  2859.  
  2860.                            function _0x2d262a() {
  2861.                                if ('CcSsQqTt' ['indexOf'](_0x5d45c1) == -0x1) {
  2862.                                    _0x594746 = _0x5b0427['slice'](0x0);
  2863.                                }
  2864.                                var _0x5b7767 = [0x0, 0x0];
  2865.                                _0x5b7767[0x0] = 0x2 * _0x5b0427[0x0] - _0x594746[0x0];
  2866.                                _0x5b7767[0x1] = 0x2 * _0x5b0427[0x1] - _0x594746[0x1];
  2867.                                return _0x5b7767;
  2868.                            }
  2869.  
  2870.                            function _0x1134cf(_0x1c0b52, _0x9a24a2) {
  2871.                                var _0x3a4723 = [_0x9a24a2, 0x0];
  2872.                                if (_0x1c0b52 == 'H') {
  2873.                                    _0x3a4723[0x1] = _0x5b0427[0x1];
  2874.                                }
  2875.                                return _0x17d776(_0x1c0b52, _0x3a4723);
  2876.                            }
  2877.  
  2878.                            function _0x5b73e4(_0x4d8f29, _0x1b987c) {
  2879.                                var _0x185519 = [0x0, _0x1b987c];
  2880.                                if (_0x4d8f29 == 'V') {
  2881.                                    _0x185519[0x0] = _0x5b0427[0x0];
  2882.                                }
  2883.                                return _0x17d776(_0x4d8f29, _0x185519);
  2884.                            }
  2885.  
  2886.                            function _0x4ab5ce(_0x4c167f, _0x141977) {
  2887.                                var _0x5e13bc = [_0x4c167f];
  2888.                                if (_0x141977 && _0x141977['length'] > 0x1) {
  2889.                                    var _0x1c60a4 = _0x141977[0x1];
  2890.                                    for (var _0x4ffc46 = 0x0; _0x4ffc46 < _0x1c60a4['length']; _0x4ffc46++) {
  2891.                                        _0x5e13bc['push'](_0x1c60a4[_0x4ffc46]);
  2892.                                    }
  2893.                                }
  2894.                                return _0x5e13bc;
  2895.                            }
  2896.  
  2897.                            function _0x2c59c9(_0x453315) {
  2898.                                return Math['sqrt'](Math['pow'](_0x453315[0x0], 0x2) + Math['pow'](_0x453315[0x1], 0x2));
  2899.                            }
  2900.  
  2901.                            function _0x1aad7e(_0x4299a0, _0x477caf) {
  2902.                                return _0x4299a0[0x0] * _0x477caf[0x0] + _0x4299a0[0x1] * _0x477caf[0x1];
  2903.                            }
  2904.  
  2905.                            function _0x51383e(_0x301135, _0xec8df7) {
  2906.                                return _0x1aad7e(_0x301135, _0xec8df7) / (_0x2c59c9(_0x301135) * _0x2c59c9(_0xec8df7));
  2907.                            }
  2908.  
  2909.                            function _0x557f60(_0x6e3356, _0x38de63, _0x5d8dfd) {
  2910.                                return Math['min'](Math['max'](val, _0x38de63), _0x5d8dfd);
  2911.                            }
  2912.  
  2913.                            function _0x9d88b2(_0xd6f2ed, _0x432d82) {
  2914.                                var _0x303e2d = 0x1;
  2915.                                if (_0xd6f2ed[0x0] * _0x432d82[0x1] - _0xd6f2ed[0x1] * _0x432d82[0x0] < 0x0) {
  2916.                                    _0x303e2d = -0x1;
  2917.                                }
  2918.                                return _0x303e2d * Math['acos'](_0x557f60(_0x51383e(_0xd6f2ed, _0x432d82)), -0x1, 0x1);
  2919.                            }
  2920.  
  2921.                            function _0x43f6bd(_0x48ff4c, _0x36fea1) {
  2922.                                var _0x7f4d28 = Math['cos'](_0x36fea1);
  2923.                                var _0x39169d = Math['sin'](_0x36fea1);
  2924.                                return [_0x7f4d28 * _0x48ff4c[0x0] + _0x39169d * _0x48ff4c[0x1], -0x1 * _0x39169d * _0x48ff4c[0x0] + _0x7f4d28 * _0x48ff4c[0x1]];
  2925.                            }
  2926.  
  2927.                            function _0x509b55(_0x34f713, _0x4e3e24) {
  2928.                                var _0x40eef2 = Math['cos'](_0x4e3e24);
  2929.                                var _0x1235bb = Math['sin'](_0x4e3e24);
  2930.                                return [_0x40eef2 * _0x34f713[0x0] - _0x1235bb * _0x34f713[0x1], _0x1235bb * _0x34f713[0x0] + _0x40eef2 * _0x34f713[0x1]];
  2931.                            }
  2932.  
  2933.                            function _0xbc7bed(_0x4b40bc, _0x4a4bb7) {
  2934.                                return [(_0x4b40bc[0x0] - _0x4a4bb7[0x0]) / 0x2, (_0x4b40bc[0x1] - _0x4a4bb7[0x1]) / 0x2];
  2935.                            }
  2936.  
  2937.                            function _0x54dfbe(_0x58fa17, _0xfc0dbd) {
  2938.                                return [(_0x58fa17[0x0] + _0xfc0dbd[0x0]) / 0x2, (_0x58fa17[0x1] + _0xfc0dbd[0x1]) / 0x2];
  2939.                            }
  2940.  
  2941.                            function _0x1d52fe(_0x5517ff, _0x40781b) {
  2942.                                return [_0x5517ff[0x0] * _0x40781b[0x0], _0x5517ff[0x1] * _0x40781b[0x1]];
  2943.                            }
  2944.  
  2945.                            function _0x5d5519(_0x1ff7e9, _0x5b95b2) {
  2946.                                return [_0x1ff7e9 * _0x5b95b2[0x0], _0x1ff7e9 * _0x5b95b2[0x1]];
  2947.                            }
  2948.  
  2949.                            function _0x23f816(_0x4fd0e5, _0x426b2a) {
  2950.                                return [_0x4fd0e5[0x0] + _0x426b2a[0x0], _0x4fd0e5[0x1] + _0x426b2a[0x1]];
  2951.                            }
  2952.  
  2953.                            function _0x42a62a(_0x53c84b, _0x197350, _0x2ebbee, _0x498c53, _0x122b93, _0x281ee8, _0x455437) {
  2954.                                if (_0x197350 == 0x0 || _0x2ebbee == 0x0) {
  2955.                                    _0x65b89a['push']({
  2956.                                        'type': 'lineTo',
  2957.                                        'args': _0x455437
  2958.                                    });
  2959.                                    return;
  2960.                                }
  2961.                                var _0x498c53 = _0x498c53 * (Math['PI'] / 0xb4);
  2962.                                _0x197350 = Math['abs'](_0x197350);
  2963.                                _0x2ebbee = Math['abs'](_0x2ebbee);
  2964.                                var _0x52e608 = _0x43f6bd(_0xbc7bed(_0x53c84b, _0x455437), _0x498c53);
  2965.                                var _0x3648b4 = _0x1d52fe(_0x52e608, _0x52e608);
  2966.                                var _0x5bceb0 = Math['pow'](_0x197350, 0x2);
  2967.                                var _0x23b38 = Math['pow'](_0x2ebbee, 0x2);
  2968.                                var _0x51edaf = Math['sqrt'](_0x3648b4[0x0] / _0x5bceb0 + _0x3648b4[0x1] / _0x23b38);
  2969.                                if (_0x51edaf > 0x1) {
  2970.                                    _0x197350 *= _0x51edaf;
  2971.                                    _0x2ebbee *= _0x51edaf;
  2972.                                    _0x5bceb0 = Math['pow'](_0x197350, 0x2);
  2973.                                    _0x23b38 = Math['pow'](_0x2ebbee, 0x2);
  2974.                                }
  2975.                                var _0x1c2ee5 = Math['sqrt'](Math['abs'](_0x5bceb0 * _0x23b38 - _0x5bceb0 * _0x3648b4[0x1] - _0x23b38 * _0x3648b4[0x0]) / (_0x5bceb0 * _0x3648b4[0x1] + _0x23b38 * _0x3648b4[0x0]));
  2976.                                if (_0x122b93 == _0x281ee8) {
  2977.                                    _0x1c2ee5 *= -0x1;
  2978.                                }
  2979.                                var _0x514190 = _0x5d5519(_0x1c2ee5, [_0x197350 * _0x52e608[0x1] / _0x2ebbee, -_0x2ebbee * _0x52e608[0x0] / _0x197350]);
  2980.                                var _0x35530e = _0x23f816(_0x509b55(_0x514190, _0x498c53), _0x54dfbe(_0x53c84b, _0x455437));
  2981.                                var _0x29cd1d = [(_0x52e608[0x0] - _0x514190[0x0]) / _0x197350, (_0x52e608[0x1] - _0x514190[0x1]) / _0x2ebbee];
  2982.                                var _0x248328 = [(-0x1 * _0x52e608[0x0] - _0x514190[0x0]) / _0x197350, (-0x1 * _0x52e608[0x1] - _0x514190[0x1]) / _0x2ebbee];
  2983.                                var _0x552567 = _0x9d88b2([0x1, 0x0], _0x29cd1d);
  2984.                                var _0x253710 = _0x9d88b2(_0x29cd1d, _0x248328);
  2985.                                var _0x48c1bb = _0x552567;
  2986.                                var _0x3da7fc = _0x552567 + _0x253710;
  2987.                                _0x65b89a['push']({
  2988.                                    'type': 'save',
  2989.                                    'args': []
  2990.                                }, {
  2991.                                    'type': 'translate',
  2992.                                    'args': [_0x35530e[0x0], _0x35530e[0x1]]
  2993.                                }, {
  2994.                                    'type': 'rotate',
  2995.                                    'args': [_0x498c53]
  2996.                                }, {
  2997.                                    'type': 'scale',
  2998.                                    'args': [_0x197350, _0x2ebbee]
  2999.                                }, {
  3000.                                    'type': 'arc',
  3001.                                    'args': [0x0, 0x0, 0x1, _0x48c1bb, _0x3da7fc, 0x1 - _0x281ee8]
  3002.                                }, {
  3003.                                    'type': 'restore',
  3004.                                    'args': []
  3005.                                });
  3006.                            }
  3007.                            _0x2bfff2 = _0x3c91de();
  3008.                            if (_0x2bfff2 !== _0x4e763b && _0x3e408e === _0x3a6242['length']) {
  3009.                                return _0x2bfff2;
  3010.                            } else {
  3011.                                if (_0x2bfff2 !== _0x4e763b && _0x3e408e < _0x3a6242['length']) {
  3012.                                    _0x569314({
  3013.                                        'type': 'end',
  3014.                                        'description': 'end\x20of\x20input'
  3015.                                    });
  3016.                                }
  3017.                                throw _0x2f901a(null, _0x1fda2f, _0x7dbbe5);
  3018.                            }
  3019.                        }
  3020.                        return {
  3021.                            'SyntaxError': _0x4cc4a9,
  3022.                            'parse': _0x4b296c
  3023.                        };
  3024.                    }();
  3025.  
  3026.                    function _0x2e7f39(_0x6b1952) {
  3027.                        this['ops_'] = [];
  3028.                        if (_0x6b1952 == undefined) {
  3029.                            return;
  3030.                        }
  3031.                        if (typeof _0x6b1952 == 'string') {
  3032.                            try {
  3033.                                this['ops_'] = parser['parse'](_0x6b1952);
  3034.                            } catch (_0x3cea62) {}
  3035.                        } else if (_0x6b1952['hasOwnProperty']('ops_')) {
  3036.                            this['ops_'] = _0x6b1952['ops_']['slice'](0x0);
  3037.                        } else {
  3038.                            throw 'Error:\x20' + typeof _0x6b1952 + 'is\x20not\x20a\x20valid\x20argument\x20to\x20Path';
  3039.                        }
  3040.                    };
  3041.                    var _0x12bf09 = ['closePath', 'moveTo', 'lineTo', 'quadraticCurveTo', 'bezierCurveTo', 'rect', 'arc', 'arcTo', 'ellipse', 'isPointInPath', 'isPointInStroke'];
  3042.  
  3043.                    function _0x3591e3(_0x4b537b) {
  3044.                        return function() {
  3045.                            this['ops_']['push']({
  3046.                                'type': _0x4b537b,
  3047.                                'args': Array['prototype']['slice']['call'](arguments, 0x0)
  3048.                            });
  3049.                        };
  3050.                    }
  3051.                    for (var _0x4136da = 0x0; _0x4136da < _0x12bf09['length']; _0x4136da++) {
  3052.                        var _0x513083 = _0x12bf09[_0x4136da];
  3053.                        _0x2e7f39['prototype'][_0x513083] = _0x3591e3(_0x513083);
  3054.                    }
  3055.                    _0x2e7f39['prototype']['addPath'] = function(_0x13e45b, _0xe33f76) {
  3056.                        var _0x4f6995 = ![];
  3057.                        if (_0xe33f76 && _0xe33f76['a'] != undefined && _0xe33f76['b'] != undefined && _0xe33f76['c'] != undefined && _0xe33f76['d'] != undefined && _0xe33f76['e'] != undefined && _0xe33f76['f'] != undefined) {
  3058.                            _0x4f6995 = !![];
  3059.                            this['ops_']['push']({
  3060.                                'type': 'save',
  3061.                                'args': []
  3062.                            });
  3063.                            this['ops_']['push']({
  3064.                                'type': 'transform',
  3065.                                'args': [_0xe33f76['a'], _0xe33f76['b'], _0xe33f76['c'], _0xe33f76['d'], _0xe33f76['e'], _0xe33f76['f']]
  3066.                            });
  3067.                        }
  3068.                        this['ops_'] = this['ops_']['concat'](_0x13e45b['ops_']);
  3069.                        if (_0x4f6995) {
  3070.                            this['ops_']['push']({
  3071.                                'type': 'restore',
  3072.                                'args': []
  3073.                            });
  3074.                        }
  3075.                    };
  3076.                    original_fill = _0x58f57c['prototype']['fill'];
  3077.                    original_stroke = _0x58f57c['prototype']['stroke'];
  3078.                    original_clip = _0x58f57c['prototype']['clip'];
  3079.                    original_is_point_in_path = _0x58f57c['prototype']['isPointInPath'];
  3080.                    original_is_point_in_stroke = _0x58f57c['prototype']['isPointInStroke'];
  3081.                    _0x58f57c['prototype']['fill'] = function(_0x158a44) {
  3082.                        if (_0x158a44 instanceof _0x2e7f39) {
  3083.                            this['beginPath']();
  3084.                            for (var _0x2583d1 = 0x0, _0x5aeabc = _0x158a44['ops_']['length']; _0x2583d1 < _0x5aeabc; _0x2583d1++) {
  3085.                                var _0x2535d2 = _0x158a44['ops_'][_0x2583d1];
  3086.                                _0x58f57c['prototype'][_0x2535d2['type']]['apply'](this, _0x2535d2['args']);
  3087.                            }
  3088.                            original_fill['apply'](this, Array['prototype']['slice']['call'](arguments, 0x1));
  3089.                        } else {
  3090.                            original_fill['apply'](this, arguments);
  3091.                        }
  3092.                    };
  3093.                    _0x58f57c['prototype']['stroke'] = function(_0x320e56) {
  3094.                        if (_0x320e56 instanceof _0x2e7f39) {
  3095.                            this['beginPath']();
  3096.                            for (var _0xfda099 = 0x0, _0x22e51f = _0x320e56['ops_']['length']; _0xfda099 < _0x22e51f; _0xfda099++) {
  3097.                                var _0x436be2 = _0x320e56['ops_'][_0xfda099];
  3098.                                _0x58f57c['prototype'][_0x436be2['type']]['apply'](this, _0x436be2['args']);
  3099.                            }
  3100.                            original_stroke['call'](this);
  3101.                        } else {
  3102.                            original_stroke['call'](this);
  3103.                        }
  3104.                    };
  3105.                    _0x58f57c['prototype']['clip'] = function(_0xc86e0c) {
  3106.                        if (_0xc86e0c instanceof _0x2e7f39) {
  3107.                            this['beginPath']();
  3108.                            for (var _0x433230 = 0x0, _0x48690b = _0xc86e0c['ops_']['length']; _0x433230 < _0x48690b; _0x433230++) {
  3109.                                var _0x5d0d8b = _0xc86e0c['ops_'][_0x433230];
  3110.                                _0x58f57c['prototype'][_0x5d0d8b['type']]['apply'](this, _0x5d0d8b['args']);
  3111.                            }
  3112.                            original_clip['apply'](this, Array['prototype']['slice']['call'](arguments, 0x1));
  3113.                        } else {
  3114.                            original_clip['apply'](this, arguments);
  3115.                        }
  3116.                    };
  3117.                    _0x58f57c['prototype']['isPointInPath'] = function(_0x5671bb) {
  3118.                        if (_0x5671bb instanceof _0x2e7f39) {
  3119.                            this['beginPath']();
  3120.                            for (var _0x5294d4 = 0x0, _0xd14329 = _0x5671bb['ops_']['length']; _0x5294d4 < _0xd14329; _0x5294d4++) {
  3121.                                var _0x2c16dd = _0x5671bb['ops_'][_0x5294d4];
  3122.                                _0x58f57c['prototype'][_0x2c16dd['type']]['apply'](this, _0x2c16dd['args']);
  3123.                            }
  3124.                            return original_is_point_in_path['apply'](this, Array['prototype']['slice']['call'](arguments, 0x1));
  3125.                        } else {
  3126.                            return original_is_point_in_path['apply'](this, arguments);
  3127.                        }
  3128.                    };
  3129.                    _0x58f57c['prototype']['isPointInStroke'] = function(_0x114ae3) {
  3130.                        if (_0x114ae3 instanceof _0x2e7f39) {
  3131.                            this['beginPath']();
  3132.                            for (var _0x170512 = 0x0, _0x5c0abe = _0x114ae3['ops_']['length']; _0x170512 < _0x5c0abe; _0x170512++) {
  3133.                                var _0x82d3b8 = _0x114ae3['ops_'][_0x170512];
  3134.                                _0x58f57c['prototype'][_0x82d3b8['type']]['apply'](this, _0x82d3b8['args']);
  3135.                            }
  3136.                            return original_is_point_in_stroke['apply'](this, Array['prototype']['slice']['call'](arguments, 0x1));
  3137.                        } else {
  3138.                            return original_is_point_in_stroke['apply'](this, arguments);
  3139.                        }
  3140.                    };
  3141.                    Path2D = _0x2e7f39;
  3142.                }());
  3143.            }
  3144.        }(typeof CanvasRenderingContext2D === 'undefined' ? undefined : CanvasRenderingContext2D, typeof require === 'undefined' ? undefined : require));
  3145.  
  3146.        // Array.find polyfill
  3147.        !Array['prototype']['find'] && Object['defineProperty'](Array['prototype'], 'find', {
  3148.            'value': function(_0x55bea1) {
  3149.                if (this == null) throw new TypeError('\x22this\x22\x20is\x20null\x20or\x20not\x20defined');
  3150.                var _0x2bea3f = Object(this),
  3151.                    _0x52404e = _0x2bea3f['length'] >>> 0x0;
  3152.                if (typeof _0x55bea1 !== 'function') throw new TypeError('predicate\x20must\x20be\x20a\x20function');
  3153.                var _0x5e3137 = arguments[0x1],
  3154.                    _0x559983 = 0x0;
  3155.                while (_0x559983 < _0x52404e) {
  3156.                    var _0x51d569 = _0x2bea3f[_0x559983];
  3157.                    if (_0x55bea1['call'](_0x5e3137, _0x51d569, _0x559983, _0x2bea3f)) return _0x51d569;
  3158.                    _0x559983++;
  3159.                }
  3160.                return undefined;
  3161.            },
  3162.            'configurable': !![],
  3163.            'writable': !![]
  3164.        });
  3165.  
  3166.        /*----- functions -----*/
  3167.        // utils
  3168.        function deg2rad(deg) {
  3169.            return deg * Math.PI / 180.0;
  3170.        }
  3171.  
  3172.        function rotateVectorRad(v, rad) {
  3173.            return [
  3174.                v[0] * Math.cos(rad) - v[1] * Math.sin(rad),
  3175.                v[0] * Math.sin(rad) + v[1] * Math.cos(rad)
  3176.            ];
  3177.        }
  3178.  
  3179.        function rotateVectorDeg(v, deg) {
  3180.            var rad = deg2rad(deg);
  3181.            return rotateVectorRad(v, rad);
  3182.        }
  3183.  
  3184.        function applyRotationRad(bbox, rad) {
  3185.            var corners = [
  3186.                [bbox.minx, bbox.miny],
  3187.                [bbox.minx, bbox.maxy],
  3188.                [bbox.maxx, bbox.miny],
  3189.                [bbox.maxx, bbox.maxy]
  3190.            ];
  3191.            corners = corners.map(function(v) {
  3192.                return rotateVectorRad(v, rad);
  3193.            });
  3194.            return {
  3195.                minx: corners.reduce(function(a, v) {
  3196.                    return Math.min(a, v[0]);
  3197.                }, Infinity),
  3198.                miny: corners.reduce(function(a, v) {
  3199.                    return Math.min(a, v[1]);
  3200.                }, Infinity),
  3201.                maxx: corners.reduce(function(a, v) {
  3202.                    return Math.max(a, v[0]);
  3203.                }, -Infinity),
  3204.                maxy: corners.reduce(function(a, v) {
  3205.                    return Math.max(a, v[1]);
  3206.                }, -Infinity),
  3207.            }
  3208.        }
  3209.  
  3210.        function applyRotationDeg(bbox, deg) {
  3211.            var rad = deg2rad(deg);
  3212.            return applyRotationRad(bbox, rad);
  3213.        }
  3214.  
  3215.        // canvas painter
  3216.        const painter = {
  3217.            ctx: null,
  3218.            save: function() {
  3219.                this.ctx.save();
  3220.            },
  3221.            restore: function() {
  3222.                this.ctx.restore();
  3223.            },
  3224.            clear: function(w, h, color) {
  3225.                this.save();
  3226.                this.ctx.setTransform(1, 0, 0, 1, 0, 0);
  3227.                if (color) {
  3228.                    this.ctx.fillStyle = color;
  3229.                    this.ctx.fillRect(0, 0, w, h);
  3230.                } else {
  3231.                    this.ctx.clearRect(0, 0, w, h);
  3232.                }
  3233.                this.restore();
  3234.            },
  3235.            line: function(x1, y1, x2, y2, lw, color) {
  3236.                this.save();
  3237.                this.setLineCapAndJoin();
  3238.                this.ctx.strokeStyle = color;
  3239.                this.ctx.lineWidth = lw;
  3240.                this.ctx.beginPath();
  3241.                this.ctx.moveTo(x1, y1);
  3242.                this.ctx.lineTo(x2, y2);
  3243.                this.ctx.stroke();
  3244.                this.restore();
  3245.            },
  3246.            strokeArc: function(cx, cy, radius, startAngle, stopAngle, ccw, lw, color) {
  3247.                this.save();
  3248.                this.setLineCapAndJoin();
  3249.                this.ctx.strokeStyle = color;
  3250.                this.ctx.lineWidth = lw;
  3251.                this.ctx.beginPath();
  3252.                this.ctx.arc(cx, cy, radius, startAngle, stopAngle, ccw);
  3253.                this.ctx.stroke();
  3254.                this.restore();
  3255.            },
  3256.            closedArc: function(cx, cy, radius, startAngle, stopAngle, ccw, lw, color) {
  3257.                this.save();
  3258.                this.setLineCapAndJoin();
  3259.                this.ctx.strokeStyle = color;
  3260.                this.ctx.lineWidth = lw;
  3261.                this.ctx.beginPath();
  3262.                this.ctx.arc(cx, cy, radius, startAngle, stopAngle, ccw);
  3263.                this.ctx.closePath();
  3264.                this.ctx.stroke();
  3265.                this.restore();
  3266.            },
  3267.            fillArc: function(cx, cy, radius, startAngle, stopAngle, ccw, color) {
  3268.                this.save();
  3269.                this.setLineCapAndJoin();
  3270.                this.ctx.fillStyle = color;
  3271.                this.ctx.beginPath();
  3272.                this.ctx.arc(cx, cy, radius, startAngle, stopAngle, ccw);
  3273.                this.ctx.fill();
  3274.                this.restore();
  3275.            },
  3276.            strokeEllipse: function(x, y, radiusX, radiusY, rotation, lw, color) {
  3277.                this.save();
  3278.                this.setLineCapAndJoin();
  3279.                this.ctx.strokeStyle = color;
  3280.                this.ctx.lineWidth = lw;
  3281.                this.ctx.beginPath();
  3282.                this.ctx.ellipse(x, y, radiusX, radiusY, rotation, 0, 2 * Math.PI, false);
  3283.                this.ctx.stroke();
  3284.                this.restore();
  3285.            },
  3286.            fillEllipse: function(x, y, radiusX, radiusY, rotation, color) {
  3287.                this.save();
  3288.                this.setLineCapAndJoin();
  3289.                this.ctx.fillStyle = color;
  3290.                this.ctx.beginPath();
  3291.                this.ctx.ellipse(x, y, radiusX, radiusY, rotation, 0, 2 * Math.PI, false);
  3292.                this.ctx.fill();
  3293.                this.restore();
  3294.            },
  3295.            strokeObround: function(x, y, width, height, rotation, lw, color) {
  3296.                if (width === height) {
  3297.                    this.strokeEllipse(x, y, width / 2, height / 2, rotation, lw, color);
  3298.                } else {
  3299.                    this.save();
  3300.                    this.ctx.translate(x, y);
  3301.                    if (rotation !== null) {
  3302.                        this.ctx.rotate(rotation);
  3303.                    }
  3304.                    this.strokePath(this.getObroundPath(width, height), lw, color);
  3305.                    this.restore();
  3306.                }
  3307.            },
  3308.            fillObround: function(x, y, width, height, rotation, color) {
  3309.                if (width === height) {
  3310.                    this.fillEllipse(x, y, width / 2, height / 2, rotation, color);
  3311.                } else {
  3312.                    this.save();
  3313.                    this.ctx.translate(x, y);
  3314.                    if (rotation !== null) {
  3315.                        this.ctx.rotate(rotation);
  3316.                    }
  3317.                    this.fillPath(this.getObroundPath(width, height), color);
  3318.                    this.restore();
  3319.                }
  3320.            },
  3321.            strokeRect: function(x, y, width, height, crad, rotation, lw, color) {
  3322.                if (crad < 0.001) {
  3323.                    this.save();
  3324.                    this.setLineCapAndJoin();
  3325.                    this.ctx.strokeStyle = color;
  3326.                    this.ctx.lineWidth = lw;
  3327.                    this.ctx.translate(x, y);
  3328.                    if (rotation !== null) {
  3329.                        this.ctx.rotate(rotation);
  3330.                    }
  3331.                    this.ctx.beginPath();
  3332.                    this.ctx.rect(-width / 2, -height / 2, width, height);
  3333.                    this.ctx.stroke();
  3334.                    this.restore();
  3335.                } else if (crad > 49.99) {
  3336.                    this.strokeObround(x, y, width, height, rotation, lw, color);
  3337.                } else {
  3338.                    this.save();
  3339.                    this.ctx.translate(x, y);
  3340.                    if (rotation !== null) {
  3341.                        this.ctx.rotate(rotation);
  3342.                    }
  3343.                    this.strokePath(this.getRoundedRectPath(width, height, crad), lw, color);
  3344.                    this.restore();
  3345.                }
  3346.            },
  3347.            fillRect: function(x, y, width, height, crad, rotation, color) {
  3348.                if (crad < 0.001) {
  3349.                    this.save();
  3350.                    this.setLineCapAndJoin();
  3351.                    this.ctx.fillStyle = color;
  3352.                    this.ctx.translate(x, y);
  3353.                    if (rotation !== null) {
  3354.                        this.ctx.rotate(rotation);
  3355.                    }
  3356.                    this.ctx.beginPath();
  3357.                    this.ctx.rect(-width / 2, -height / 2, width, height);
  3358.                    this.ctx.fill();
  3359.                    this.restore();
  3360.                } else if (crad > 49.99) {
  3361.                    this.fillObround(x, y, width, height, rotation, color);
  3362.                } else {
  3363.                    this.save();
  3364.                    this.ctx.translate(x, y);
  3365.                    if (rotation !== null) {
  3366.                        this.ctx.rotate(rotation);
  3367.                    }
  3368.                    this.fillPath(this.getRoundedRectPath(width, height, crad), color);
  3369.                    this.restore();
  3370.                }
  3371.            },
  3372.            strokeDShape: function(x, y, width, height, lw, color) {
  3373.                this.save();
  3374.                this.ctx.translate(x, y);
  3375.                this.strokePath(this.getDShapePath(width, height));
  3376.                this.restore();
  3377.            },
  3378.            fillDShape: function(x, y, width, height, color) {
  3379.                this.save();
  3380.                this.ctx.translate(x, y);
  3381.                this.fillPath(this.getDShapePath(width, height), color);
  3382.                this.restore();
  3383.            },
  3384.            strokePath: function(path, lw, color) {
  3385.                this.save();
  3386.                this.setLineCapAndJoin();
  3387.                this.ctx.strokeStyle = color;
  3388.                this.ctx.lineWidth = lw;
  3389.                this.ctx.stroke(path);
  3390.                this.restore();
  3391.            },
  3392.            fillPath: function(path, color) {
  3393.                this.save();
  3394.                this.setLineCapAndJoin();
  3395.                this.ctx.fillStyle = color;
  3396.                this.ctx.fill(path);
  3397.                this.restore();
  3398.            },
  3399.            setLineCapAndJoin: function() {
  3400.                this.ctx.lineCap = "round";
  3401.                this.ctx.lineJoin = "round";
  3402.            },
  3403.            padZero: function(str, len) {
  3404.                len = len || 2;
  3405.                var zeros = new Array(len).join('0');
  3406.                return (zeros + str).slice(-len);
  3407.            },
  3408.            invertColor: function(hex, bw) {
  3409.                if (hex.indexOf('#') === 0) {
  3410.                    hex = hex.slice(1);
  3411.                }
  3412.                // convert 3-digit hex to 6-digits.
  3413.                if (hex.length === 3) {
  3414.                    hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
  3415.                }
  3416.                if (hex.length !== 6) {
  3417.                    throw new Error('Invalid HEX color.');
  3418.                }
  3419.                var r = parseInt(hex.slice(0, 2), 16);
  3420.                var g = parseInt(hex.slice(2, 4), 16);
  3421.                var b = parseInt(hex.slice(4, 6), 16);
  3422.                if (bw) {
  3423.                    return (r * 0.299 + g * 0.587 + b * 0.114) > 186 ? '#000000' : '#FFFFFF';
  3424.                }
  3425.                // invert color components
  3426.                r = (255 - r).toString(16);
  3427.                g = (255 - g).toString(16);
  3428.                b = (255 - b).toString(16);
  3429.                // pad each with zeros and return
  3430.                return "#" + this.padZero(r) + this.padZero(g) + this.padZero(b);
  3431.            },
  3432.            getObroundPath: function(width, height) {
  3433.                var r, d;
  3434.                var path = new Path2D();
  3435.                if (width > height) {
  3436.                    r = height / 2;
  3437.                    d = width / 2;
  3438.                    path.arc(-d + r, 0, r, Math.PI / 2, 1.5 * Math.PI, false);
  3439.                    path.lineTo(d - r, -r);
  3440.                    path.arc(d - r, 0, r, 1.5 * Math.PI, Math.PI / 2, false);
  3441.                } else {
  3442.                    r = width / 2;
  3443.                    d = height / 2;
  3444.                    path.arc(0, d - r, r, 0, Math.PI, false);
  3445.                    path.lineTo(-r, -d + r);
  3446.                    path.arc(0, -d + r, r, Math.PI, 0, false);
  3447.                }
  3448.                path.closePath();
  3449.                return path;
  3450.            },
  3451.            getRoundedRectPath: function(width, height, crad) {
  3452.                var hw = width / 2;
  3453.                var hh = height / 2;
  3454.                var r = Math.min(width, height) * crad / 100;
  3455.                var path = new Path2D();
  3456.                path.arc(-hw + r, -hh + r, r, Math.PI, 1.5 * Math.PI, false);
  3457.                path.lineTo(hw - r, -hh);
  3458.                path.arc(hw - r, -hh + r, r, 1.5 * Math.PI / 2, 0, false);
  3459.                path.lineTo(hw, hh - r);
  3460.                path.arc(hw - r, hh - r, r, 0, Math.PI / 2, false);
  3461.                path.lineTo(-hw + r, hh);
  3462.                path.arc(-hw + r, hh - r, r, Math.PI / 2, Math.PI, false);
  3463.                path.closePath();
  3464.                return path;
  3465.            },
  3466.            getDShapePath: function(width, height) {
  3467.                var hw = width / 2;
  3468.                var hh = height / 2;
  3469.                var r = hw;
  3470.                var y0 = hh - r;
  3471.                var path = new Path2D();
  3472.                if (y0 < 0) {
  3473.                    path.ellipse(0, 0, r, r + y0, 0, Math.PI, 0, false);
  3474.                } else {
  3475.                    path.ellipse(0, 0, r, r, 0, Math.PI, 0, false);
  3476.                }
  3477.                path.lineTo(hw, hh);
  3478.                path.lineTo(-hw, hh);
  3479.                path.closePath();
  3480.                return path;
  3481.            }
  3482.        }
  3483.  
  3484.        // storage
  3485.        function initStorage() {
  3486.            try {
  3487.                window.localStorage.getItem("blank");
  3488.                storage = window.localStorage;
  3489.            } catch (e) {
  3490.                // localStorage not available
  3491.            }
  3492.            if (!storage) {
  3493.                try {
  3494.                    window.sessionStorage.getItem("blank");
  3495.                    storage = window.sessionStorage;
  3496.                } catch (e) {
  3497.                    // sessionStorage also not available
  3498.                }
  3499.            }
  3500.        }
  3501.  
  3502.        function readStorage(key) {
  3503.            if (storage) {
  3504.                return JSON.parse(storage.getItem(storagePrefix + key));
  3505.            } else {
  3506.                return null;
  3507.            }
  3508.        }
  3509.  
  3510.        function writeStorage(key, value) {
  3511.            if (storage) {
  3512.                storage.setItem(storagePrefix + key, JSON.stringify(value));
  3513.            }
  3514.        }
  3515.  
  3516.        // defaults
  3517.        function initDefaults() {
  3518.            var tmp;
  3519.            // settings
  3520.            // bom layout
  3521.            tmp = readStorage("bom_layout");
  3522.            if (tmp !== null) {
  3523.                settings.bom_layout = tmp;
  3524.            }
  3525.            // bom gorup
  3526.            tmp = readStorage("bom_group");
  3527.            if (tmp !== null) {
  3528.                settings.bom_group = tmp;
  3529.            }
  3530.            // canvas layout
  3531.            tmp = readStorage("canvas_layout");
  3532.            if (tmp !== null) {
  3533.                settings.canvas_layout = tmp;
  3534.            }
  3535.            // draw assy
  3536.            tmp = readStorage("draw_assy");
  3537.            if (tmp !== null) {
  3538.                settings.draw_assy = tmp;
  3539.            }
  3540.            // draw silk
  3541.            tmp = readStorage("draw_silk");
  3542.            if (tmp !== null) {
  3543.                settings.draw_silk = tmp;
  3544.            }
  3545.            // draw nets
  3546.            tmp = readStorage("draw_nets");
  3547.            if (tmp !== null) {
  3548.                settings.draw_nets = tmp;
  3549.            }
  3550.            // draw copper pours
  3551.            tmp = readStorage("draw_copper_pours");
  3552.            if (tmp !== null) {
  3553.                settings.draw_copper_pours = tmp;
  3554.            }
  3555.            // draw fiducials
  3556.            tmp = readStorage("draw_fiducials");
  3557.            if (tmp !== null) {
  3558.                settings.draw_fiducials = tmp;
  3559.            } else {
  3560.                settings.draw_fiducials = pcbdata.board.show_fiducials;
  3561.            }
  3562.            // draw pads
  3563.            tmp = readStorage("draw_pads");
  3564.            if (tmp !== null) {
  3565.                settings.draw_pads = tmp;
  3566.            }
  3567.            // draw vias
  3568.            tmp = readStorage("draw_vias");
  3569.            if (tmp !== null) {
  3570.                settings.draw_vias = tmp;
  3571.            }
  3572.            // show suppliers
  3573.            tmp = readStorage("show_suppliers");
  3574.            if (tmp !== null) {
  3575.                settings.show_suppliers = tmp;
  3576.            }
  3577.            // board rotation angle
  3578.            tmp = readStorage("board_rotation");
  3579.            if (tmp !== null) {
  3580.                settings.board_rotation = tmp;
  3581.            }
  3582.            // placed
  3583.            tmp = readStorage("placed");
  3584.            settings.placed = [];
  3585.            if (tmp !== null) {
  3586.                settings.placed = tmp;
  3587.            }
  3588.  
  3589.            // document
  3590.            var text = pcbdata.metadata.title + pcbdata.metadata.board_name;
  3591.            if (pcbdata.metadata.variant !== "") {
  3592.                text += " :: " + pcbdata.metadata.variant;
  3593.            }
  3594.            document.title = text;
  3595.            document.getElementById("board_name").innerHTML = pcbdata.metadata.board_name;
  3596.            if (pcbdata.metadata.variant !== "") {
  3597.                var elem = document.getElementById("assembly_variant");
  3598.                elem.innerHTML = "Assembly variant: " + pcbdata.metadata.variant;
  3599.                elem.style.display = "table-cell";
  3600.            }
  3601.            document.getElementById('version').innerHTML = "version " + pcbdata.metadata.version;
  3602.        }
  3603.  
  3604.        function writeAll() {
  3605.            // settings
  3606.            Object.keys(settings).forEach(function(name) {
  3607.                writeStorage(name, settings[name]);
  3608.            });
  3609.        }
  3610.  
  3611.        // render with events
  3612.        function initRender() {
  3613.            ["topcanvas", "bottomcanvas"].forEach(function(name) {
  3614.                var div = document.getElementById(name);
  3615.                div.style.backgroundColor = pcbdata.board.bgcolor;
  3616.                var canvas = canvases[name];
  3617.                var trsf = canvas.trsf;
  3618.                // context menu
  3619.                [div, canvas.bg, canvas.silk, canvas.assy, canvas.hl].forEach(function(elem) {
  3620.                    elem.addEventListener("contextmenu", function(e) {
  3621.                        e.preventDefault();
  3622.                    }, false);
  3623.                });
  3624.                // mouse down, move, up
  3625.                var isDown = false;
  3626.                div.addEventListener("pointerdown", function(e) {
  3627.                    e.preventDefault();
  3628.                    e.stopPropagation();
  3629.                    isDown = true;
  3630.                    canvas.pstate[e.pointerId] = {
  3631.                        lastX: e.offsetX,
  3632.                        lastY: e.offsetY,
  3633.                        down: e.button
  3634.                    };
  3635.                });
  3636.                div.addEventListener("pointermove", function(e) {
  3637.                    if (canvas.pstate.hasOwnProperty(e.pointerId)) {
  3638.                        if (canvas.pstate[e.pointerId].down == 2) {
  3639.                            return;
  3640.                        }
  3641.                        e.preventDefault();
  3642.                        e.stopPropagation();
  3643.                        var dx = e.offsetX - canvas.pstate[e.pointerId].lastX;
  3644.                        var dy = e.offsetY - canvas.pstate[e.pointerId].lastY;
  3645.                        canvas.pstate[e.pointerId] = {
  3646.                            lastX: e.offsetX,
  3647.                            lastY: e.offsetY
  3648.                        };
  3649.                        // simple drag
  3650.                        trsf.panx += devicePixelRatio * dx / trsf.zoom;
  3651.                        trsf.pany += devicePixelRatio * dy / trsf.zoom;
  3652.                        redrawCanvas(canvas);
  3653.                    }
  3654.                });
  3655.                div.addEventListener("pointerup", function(e) {
  3656.                    e.preventDefault();
  3657.                    e.stopPropagation();
  3658.                    delete canvas.pstate[e.pointerId];
  3659.                    // reset transformation by right click
  3660.                    if (e.button === 2) {
  3661.                        trsf.panx = 0;
  3662.                        trsf.pany = 0;
  3663.                        trsf.zoom = 1;
  3664.                    }
  3665.                    redrawCanvas(canvas);
  3666.                    isDown = false;
  3667.                });
  3668.                // mouse wheel (zoom)
  3669.                div.addEventListener("wheel", function(e) {
  3670.                    e.preventDefault();
  3671.                    e.stopPropagation();
  3672.                    if (isDown) {
  3673.                        return;
  3674.                    }
  3675.                    var wheeldelta = e.deltaY;
  3676.                    // Firefox
  3677.                    if (e.deltaMode == 1) { // The delta values are specified in lines.
  3678.  
  3679.                        wheeldelta *= 30;
  3680.                    } else if (e.deltaMode == 2) { // The delta values are specified in pages.
  3681.                        wheeldelta *= 300;
  3682.                    }
  3683.                    var m = Math.pow(1.1, -wheeldelta / 40);
  3684.                    // limit amount of zoom per tick.
  3685.                    if (m > 2) {
  3686.                        m = 2;
  3687.                    } else if (m < 0.5) {
  3688.                        m = 0.5;
  3689.                    }
  3690.                    trsf.zoom *= m;
  3691.                    var zoomd = (1 - m) / trsf.zoom;
  3692.                    trsf.panx += devicePixelRatio * e.offsetX * zoomd;
  3693.                    trsf.pany += devicePixelRatio * e.offsetY * zoomd;
  3694.                    redrawCanvas(canvas);
  3695.                });
  3696.            });
  3697.        }
  3698.  
  3699.        // layouts
  3700.        function getGutterNode(node) {
  3701.            for (var i = 0; i < node.childNodes.length; i++) {
  3702.                if (node.childNodes[i].classList && node.childNodes[i].classList.contains("gutter")) {
  3703.                    return node.childNodes[i];
  3704.                }
  3705.            }
  3706.        }
  3707.  
  3708.        function removeGutterNode(node) {
  3709.            node.removeChild(getGutterNode(node));
  3710.        }
  3711.  
  3712.        function removeGutters() {
  3713.            removeGutterNode(document.getElementById("divbottom"));
  3714.            removeGutterNode(document.getElementById("divcanvas"));
  3715.        }
  3716.  
  3717.        function destorySplitters() {
  3718.            if (bomsplit) {
  3719.                bomsplit.destroy();
  3720.                bomsplit = null;
  3721.                canvassplit.destroy();
  3722.                canvassplit = null;
  3723.            }
  3724.        }
  3725.  
  3726.        function changeBOMLayout(bomLayout) {
  3727.            Object.keys(bomButtons).forEach(function(btnName) {
  3728.                bomButtons[btnName].classList.remove("selected");
  3729.            });
  3730.            switch (bomLayout) {
  3731.                case "bom-only":
  3732.                    bomButtons.btnBOMOnly.classList.add("selected");
  3733.  
  3734.                    document.getElementById("topcanvas").classList.remove("split-horizontal");
  3735.                    document.getElementById("bottomcanvas").classList.remove("split-horizontal");
  3736.                    document.getElementById("topcanvas").style.display = "none";
  3737.                    document.getElementById("bottomcanvas").style.display = "none";
  3738.  
  3739.                    document.getElementById("divbom").classList.remove("split-horizontal");
  3740.                    document.getElementById("divbom").style.width = "";
  3741.  
  3742.                    destorySplitters();
  3743.                    break;
  3744.                case "top-bottom":
  3745.                    bomButtons.btnBOMTopBottom.classList.add("selected");
  3746.  
  3747.                    document.getElementById("divbom").classList.remove("split-horizontal");
  3748.                    document.getElementById("divbom").style.width = "";
  3749.                    document.getElementById("divbom").style.height = "";
  3750.  
  3751.                    document.getElementById("divcanvas").classList.remove("split-horizontal");
  3752.                    document.getElementById("divcanvas").style.width = "";
  3753.                    document.getElementById("divcanvas").style.height = "";
  3754.  
  3755.                    document.getElementById("topcanvas").style.display = "";
  3756.                    document.getElementById("topcanvas").classList.add("split-horizontal");
  3757.                    document.getElementById("topcanvas").style.width = "";
  3758.                    document.getElementById("topcanvas").style.height = "";
  3759.                    document.getElementById("bottomcanvas").style.display = "";
  3760.                    document.getElementById("bottomcanvas").classList.add("split-horizontal");
  3761.                    document.getElementById("bottomcanvas").style.width = "";
  3762.                    document.getElementById("bottomcanvas").style.height = "";
  3763.  
  3764.                    destorySplitters();
  3765.                    bomsplit = Split(["#divbom", "#divcanvas"], {
  3766.                        sizes: [50, 50],
  3767.                        gutterSize: 6,
  3768.                        direction: "vertical",
  3769.                        onDragEnd: resizeAll
  3770.                    });
  3771.                    canvassplit = Split(["#topcanvas", "#bottomcanvas"], {
  3772.                        sizes: [50, 50],
  3773.                        gutterSize: 6,
  3774.                        direction: "horizontal",
  3775.                        onDragEnd: resizeAll
  3776.                    });
  3777.                    break;
  3778.                case "left-right":
  3779.                    bomButtons.btnBOMLeftRight.classList.add("selected");
  3780.  
  3781.                    document.getElementById("topcanvas").style.display = "";
  3782.                    document.getElementById("bottomcanvas").style.display = "";
  3783.                    document.getElementById("topcanvas").classList.remove("split-horizontal");
  3784.                    document.getElementById("bottomcanvas").classList.remove("split-horizontal");
  3785.  
  3786.                    document.getElementById("divbom").classList.add("split-horizontal");
  3787.                    document.getElementById("divcanvas").classList.add("split-horizontal");
  3788.  
  3789.                    destorySplitters();
  3790.                    bomsplit = Split(["#divbom", "#divcanvas"], {
  3791.                        sizes: [50, 50],
  3792.                        gutterSize: 6,
  3793.                        direction: "horizontal",
  3794.                        onDragEnd: resizeAll
  3795.                    });
  3796.                    canvassplit = Split(["#topcanvas", "#bottomcanvas"], {
  3797.                        sizes: [50, 50],
  3798.                        gutterSize: 6,
  3799.                        direction: "vertical",
  3800.                        onDragEnd: resizeAll
  3801.                    });
  3802.                    break;
  3803.                default:
  3804.                    return;
  3805.            }
  3806.            settings.bom_layout = bomLayout;
  3807.            changeCanvasLayout(settings.canvas_layout);
  3808.        }
  3809.  
  3810.        function changeCanvasLayout(canvasLayout) {
  3811.            Object.keys(canvasButtons).forEach(function(btnName) {
  3812.                canvasButtons[btnName].classList.remove("selected");
  3813.            });
  3814.            switch (canvasLayout) {
  3815.                case "T":
  3816.                    canvasButtons.btnT.classList.add("selected");
  3817.                    if (settings.bom_layout !== "bom-only") {
  3818.                        canvassplit.collapse(1);
  3819.                    }
  3820.                    break;
  3821.                case "B":
  3822.                    canvasButtons.btnB.classList.add("selected");
  3823.                    if (settings.bom_layout !== "bom-only") {
  3824.                        canvassplit.collapse(0);
  3825.                    }
  3826.                    break;
  3827.                case "TB":
  3828.                default:
  3829.                    canvasButtons.btnTB.classList.add("selected");
  3830.                    if (settings.bom_layout !== "bom-only") {
  3831.                        canvassplit.setSizes([50, 50]);
  3832.                    }
  3833.            }
  3834.            if (settings.canvas_layout !== canvasLayout) {
  3835.                selectedComps = [];
  3836.            }
  3837.            settings.canvas_layout = canvasLayout;
  3838.            resizeAll();
  3839.            changeBomGroup(settings.bom_group);
  3840.        }
  3841.  
  3842.        // bom group
  3843.        function changeBomGroup(group) {
  3844.            Object.keys(groupButtons).forEach(function(btnName) {
  3845.                groupButtons[btnName].classList.remove("selected");
  3846.            });
  3847.            switch (group) {
  3848.                case "U":
  3849.                default:
  3850.                    groupButtons.btnU.classList.add("selected");
  3851.                    groupFilter = filterGUngroup;
  3852.                    break;
  3853.                case "NL":
  3854.                    groupButtons.btnNL.classList.add("selected");
  3855.                    groupFilter = null;
  3856.                    break;
  3857.                case "N":
  3858.                    groupButtons.btnN.classList.add("selected");
  3859.                    groupFilter = filterGName;
  3860.                    break;
  3861.                case "NV":
  3862.                    groupButtons.btnNV.classList.add("selected");
  3863.                    groupFilter = filterGNameValue;
  3864.                    break;
  3865.                case "NP":
  3866.                    groupButtons.btnNP.classList.add("selected");
  3867.                    groupFilter = filterGNamePattern;
  3868.                    break;
  3869.                case "NVP":
  3870.                    groupButtons.btnNVP.classList.add("selected");
  3871.                    groupFilter = filterGNameValuePattern;
  3872.                    break;
  3873.            }
  3874.            if (group !== settings.bom_group) {
  3875.                settings.bom_group = group;
  3876.                selectedComps = [];
  3877.                selectedNet = null;
  3878.                lastActive = null;
  3879.                //bomSortFunction = null;
  3880.                //currentSortColumn = null;
  3881.                //currentSortOrder = null;
  3882.                clearCanvas(canvases.topcanvas.hl, null);
  3883.                clearCanvas(canvases.bottomcanvas.hl, null);
  3884.            }
  3885.            populateBomTable();
  3886.        }
  3887.  
  3888.        // bom table
  3889.        function populateBomTable() {
  3890.            total = {};
  3891.            totalCount = {};
  3892.            populateBomTableHeader();
  3893.            populateBomTableBody();
  3894.            var currencies = Object.keys(total);
  3895.            if (settings.bom_group !== 'NL' && currencies.length > 0) {
  3896.                var cols = ['6', '3'];
  3897.                if (settings.bom_group == 'U') {
  3898.                    cols[0] = '5';
  3899.                }
  3900.                // first currency
  3901.                var tr = document.createElement('tr');
  3902.                // "Total"
  3903.                var td = document.createElement('td');
  3904.                td.setAttribute('colspan', cols[0]);
  3905.                td.innerHTML = '<strong>Total</strong>';
  3906.                tr.appendChild(td);
  3907.                // total quantity
  3908.                td = document.createElement('td');
  3909.                td.innerHTML = '<strong>' + pcbdata.components.slice().length + '</strong>';
  3910.                tr.appendChild(td);
  3911.                if (settings.show_suppliers) {
  3912.                    // supplier, price, order link
  3913.                    td = document.createElement('td');
  3914.                    td.setAttribute('colspan', cols[1]);
  3915.                    tr.appendChild(td);
  3916.                }
  3917.                bomtblbody.appendChild(tr);
  3918.                // other currencies
  3919.                if (settings.show_suppliers) {
  3920.                    for (var i = 0; i < currencies.length; ++i) {
  3921.                        tr = document.createElement('tr');
  3922.                        td = document.createElement('td');
  3923.                        td.setAttribute('colspan', cols[0]);
  3924.                        tr.appendChild(td);
  3925.                        // total quantity
  3926.                        td = document.createElement('td');
  3927.                        td.innerHTML = totalCount[currencies[i]];
  3928.                        tr.appendChild(td);
  3929.                        // supplier, price, order link
  3930.                        td = document.createElement('td');
  3931.                        td.setAttribute('colspan', cols[1]);
  3932.                        td.innerHTML = '<strong>' + total[currencies[i]] + ' ' + currencies[i] + '</strong>';
  3933.                        tr.appendChild(td);
  3934.                        bomtblbody.appendChild(tr);
  3935.                    }
  3936.                }
  3937.            }
  3938.        }
  3939.  
  3940.        // bom table: header
  3941.        function makeColumnHeader(name, cssName) {
  3942.            var th = document.createElement("th");
  3943.            th.innerHTML = name;
  3944.            if (cssName !== null) {
  3945.                th.classList.add(cssName);
  3946.            }
  3947.            return th;
  3948.        }
  3949.  
  3950.        function populateBomTableHeader() {
  3951.            while (bomtblhead.firstChild) {
  3952.                bomtblhead.removeChild(bomtblhead.firstChild);
  3953.            }
  3954.            var tr = document.createElement("tr");
  3955.            // number
  3956.            var th = document.createElement("th");
  3957.            th.classList.add("numcol");
  3958.            tr.appendChild(th);
  3959.            if (settings.bom_group === "NL") {
  3960.                th = makeColumnHeader("Net name", null);
  3961.                tr.appendChild(th);
  3962.            } else {
  3963.                // checkbox
  3964.                tr.appendChild(makeColumnHeader("Placed", "bom-checkbox"));
  3965.                // preferences
  3966.                tr.appendChild(makeColumnHeader("Reference(s)", null));
  3967.                // component name
  3968.                tr.appendChild(makeColumnHeader("Name", null));
  3969.                // value
  3970.                tr.appendChild(makeColumnHeader("Value", "value"));
  3971.                // pattern
  3972.                tr.appendChild(makeColumnHeader("Pattern", null));
  3973.                // quantity
  3974.                if (settings.bom_group !== "U") {
  3975.                    tr.appendChild(makeColumnHeader("Quantity", "quantity"));
  3976.                }
  3977.                // suppliers
  3978.                if (settings.show_suppliers == true) {
  3979.                    // supplier
  3980.                    tr.appendChild(makeColumnHeader("Supplier", null));
  3981.                    // price
  3982.                    tr.appendChild(makeColumnHeader("Price", null));
  3983.                    // link
  3984.                    tr.appendChild(makeColumnHeader("Order Link", null));
  3985.                }
  3986.            }
  3987.            bomtblhead.appendChild(tr);
  3988.        }
  3989.  
  3990.        // bom table: body
  3991.        function tildFilter(netName) {
  3992.            var prevInv = false;
  3993.            var sb = [];
  3994.            var tmp = netName.split("").map(function(token) {
  3995.                if (token !== "~" || prevInv) {
  3996.                    if (token === "~" && prevInv) {
  3997.                        sb.pop();
  3998.                    }
  3999.                    sb.push(token);
  4000.                    prevInv = false;
  4001.                    return "-";
  4002.                } else {
  4003.                    prevInv = true;
  4004.                    sb.push("!");
  4005.                    return "!";
  4006.                }
  4007.            });
  4008.            var res = sb.join("");
  4009.            var matches = res.match(/(!\w+)/g);
  4010.            for (var i in matches) {
  4011.                var n = +i;
  4012.                var match = matches[n];
  4013.                var ss = match.substring(1);
  4014.                res = res.replace(match, "<span class='net_inverse'>" + ss + "</span>");
  4015.            }
  4016.            return res;
  4017.        }
  4018.  
  4019.        function calcCount(currency, quantity) {
  4020.            if (totalCount.hasOwnProperty(currency)) {
  4021.                totalCount[currency] = totalCount[currency] + quantity;
  4022.            } else {
  4023.                totalCount[currency] = quantity;
  4024.            }
  4025.        }
  4026.  
  4027.        function calcTotal(currency, qantity, price) {
  4028.            curr_total = qantity * price;
  4029.            if (total.hasOwnProperty(currency)) {
  4030.                total[currency] = total[currency] + curr_total;
  4031.            } else {
  4032.                total[currency] = curr_total;
  4033.            }
  4034.            calcCount(currency, qantity);
  4035.        }
  4036.  
  4037.        const filterGUngroup = function(comps) {
  4038.            var res = [];
  4039.            for (var i in comps) {
  4040.                var c = comps[+i];
  4041.                var supplier = '';
  4042.                var currency = '';
  4043.                var price = 0;
  4044.                var link = '';
  4045.                if (c.hasOwnProperty('supplier')) {
  4046.                    supplier = c.supplier;
  4047.                    currency = c.currency;
  4048.                    price = c.price['gu'];
  4049.                    link = c.link;
  4050.                    calcTotal(currency, 1, price);
  4051.                }
  4052.                res.push([c.refdes, c.name, c.value, c.pattern, 1, supplier, currency, price, link]);
  4053.            }
  4054.            return res;
  4055.        }
  4056.  
  4057.        const filterGName = function(comps) {
  4058.            var res = [];
  4059.            var skip = [];
  4060.            for (var i in comps) {
  4061.                if (skip.indexOf(+i) < 0) {
  4062.                    var comp = comps[+i];
  4063.                    var group = comps.filter(function(c, index) {
  4064.                        if (skip.indexOf(index) < 0 && c["name"] === comp["name"]) {
  4065.                            skip.push(index);
  4066.                            return true;
  4067.                        }
  4068.                    });
  4069.                    var refs = group.map(function(c) {
  4070.                        return c["refdes"];
  4071.                    }).join(", ");
  4072.                    var name = comp["name"];
  4073.                    var value = group.map(function(c) {
  4074.                        return c["value"];
  4075.                    }).join(", ");
  4076.                    var pattern = group.map(function(c) {
  4077.                        return c["pattern"];
  4078.                    }).join(", ");
  4079.                    var quantity = group.length;
  4080.                    var supplier = '';
  4081.                    var currency = '';
  4082.                    var price = 0;
  4083.                    var link = '';
  4084.                    if (comp.hasOwnProperty('supplier')) {
  4085.                        supplier = comp.supplier;
  4086.                        currency = comp.currency;
  4087.                        price = comp.price['gn'];
  4088.                        link = comp.link;
  4089.                        calcTotal(currency, quantity, price);
  4090.                    }
  4091.                    res.push([refs, name, value, pattern, quantity, supplier, currency, price, link]);
  4092.                }
  4093.            }
  4094.            return res;
  4095.        }
  4096.  
  4097.        const filterGNameValue = function(comps) {
  4098.            var res = [];
  4099.            var skip = [];
  4100.            for (var i in comps) {
  4101.                if (skip.indexOf(+i) < 0) {
  4102.                    var comp = comps[+i];
  4103.                    var group = comps.filter(function(c, index) {
  4104.                        if (skip.indexOf(index) < 0 && c["name"] === comp["name"] && c["value"] === comp["value"]) {
  4105.                            skip.push(index);
  4106.                            return true;
  4107.                        }
  4108.                    });
  4109.                    var refs = group.map(function(c) {
  4110.                        return c["refdes"];
  4111.                    }).join(", ");
  4112.                    var name = comp["name"];
  4113.                    var value = comp["value"];
  4114.                    var pattern = group.map(function(c) {
  4115.                        return c["pattern"];
  4116.                    }).join(", ");
  4117.                    var quantity = group.length;
  4118.                    var supplier = '';
  4119.                    var currency = '';
  4120.                    var price = 0;
  4121.                    var link = '';
  4122.                    if (comp.hasOwnProperty('supplier')) {
  4123.                        supplier = comp.supplier;
  4124.                        currency = comp.currency;
  4125.                        price = comp.price['gnv'];
  4126.                        link = comp.link;
  4127.                        calcTotal(currency, quantity, price);
  4128.                    }
  4129.                    res.push([refs, name, value, pattern, quantity, supplier, currency, price, link]);
  4130.                }
  4131.            }
  4132.            return res;
  4133.        }
  4134.  
  4135.        const filterGNamePattern = function(comps) {
  4136.            var res = [];
  4137.            var skip = [];
  4138.            for (var i in comps) {
  4139.                if (skip.indexOf(+i) < 0) {
  4140.                    var comp = comps[+i];
  4141.                    var group = comps.filter(function(c, index) {
  4142.                        if (skip.indexOf(index) < 0 && c["name"] === comp["name"] && c["pattern"] === comp["pattern"]) {
  4143.                            skip.push(index);
  4144.                            return true;
  4145.                        }
  4146.                    });
  4147.                    var refs = group.map(function(c) {
  4148.                        return c["refdes"];
  4149.                    }).join(", ");
  4150.                    var name = comp["name"];
  4151.                    var value = group.map(function(c) {
  4152.                        return c["value"];
  4153.                    }).join(", ");
  4154.                    var pattern = comp["pattern"];
  4155.                    var quantity = group.length;
  4156.                    var supplier = '';
  4157.                    var currency = '';
  4158.                    var price = 0;
  4159.                    var link = '';
  4160.                    if (comp.hasOwnProperty('supplier')) {
  4161.                        supplier = comp.supplier;
  4162.                        currency = comp.currency;
  4163.                        price = comp.price['gnp'];
  4164.                        link = comp.link;
  4165.                        calcTotal(currency, quantity, price);
  4166.                    }
  4167.                    res.push([refs, name, value, pattern, quantity, supplier, currency, price, link]);
  4168.                }
  4169.            }
  4170.            return res;
  4171.        }
  4172.  
  4173.        const filterGNameValuePattern = function(comps) {
  4174.            var res = [];
  4175.            var skip = [];
  4176.            for (var i in comps) {
  4177.                if (skip.indexOf(+i) < 0) {
  4178.                    var comp = comps[+i];
  4179.                    var group = comps.filter(function(c, index) {
  4180.                        if (skip.indexOf(index) < 0 && c["name"] === comp["name"] && c["value"] === comp["value"] && c["pattern"] === comp["pattern"]) {
  4181.                            skip.push(index);
  4182.                            return true;
  4183.                        }
  4184.                    });
  4185.                    var refs = group.map(function(c) {
  4186.                        return c["refdes"];
  4187.                    }).join(", ");
  4188.                    var name = comp["name"];
  4189.                    var value = comp["value"];
  4190.                    var pattern = comp["pattern"];
  4191.                    var quantity = group.length;
  4192.                    var pattern = comp["pattern"];
  4193.                    var quantity = group.length;
  4194.                    var supplier = '';
  4195.                    var currency = '';
  4196.                    var price = 0;
  4197.                    var link = '';
  4198.                    if (comp.hasOwnProperty('supplier')) {
  4199.                        supplier = comp.supplier;
  4200.                        currency = comp.currency;
  4201.                        price = comp.price['gnp'];
  4202.                        link = comp.link;
  4203.                        calcTotal(currency, quantity, price);
  4204.                    }
  4205.                    res.push([refs, name, value, pattern, quantity, supplier, currency, price, link]);
  4206.                }
  4207.            }
  4208.            return res;
  4209.        }
  4210.  
  4211.        function populateNetBody() {
  4212.            var rownum = 0;
  4213.            for (var i in pcbdata.nets) {
  4214.                rownum++;
  4215.                if (pcbdata.nets[rownum - 1].name === "None") {
  4216.                    return;
  4217.                }
  4218.  
  4219.                var tr = document.createElement("tr");
  4220.                tr.id = "bomrow" + rownum;
  4221.  
  4222.                var td = document.createElement("td");
  4223.                td.textContent = rownum.toString();
  4224.                tr.appendChild(td);
  4225.  
  4226.                td = document.createElement("td");
  4227.                td.innerHTML = tildFilter(pcbdata.nets[rownum - 1].name);
  4228.                tr.appendChild(td);
  4229.  
  4230.                bomtblbody.appendChild(tr);
  4231.  
  4232.                // mouse events
  4233.                tr.addEventListener("mouseenter", function(e) {
  4234.                    if (lastActive !== null) {
  4235.                        lastActive.classList.remove("active");
  4236.                    }
  4237.                    e.currentTarget.classList.add("active");
  4238.                    selectedNet = Number(e.currentTarget.childNodes[0].innerHTML) - 1;
  4239.                    drawHLNet();
  4240.                });
  4241.                tr.addEventListener("mouseleave", function(e) {
  4242.                    lastActive = e.currentTarget;
  4243.                })
  4244.            }
  4245.        }
  4246.  
  4247.        function stylizeRefDes(refdes) {
  4248.            return '<p class="placed">' + refdes + '</p>';
  4249.        }
  4250.  
  4251.        function cleanRefDes(refdesWithStyle) {
  4252.            var a = refdesWithStyle.replace('<p class="placed">', '');
  4253.            var b = a.replace('</p>', '');
  4254.            return b;
  4255.        }
  4256.  
  4257.        function replaceRefDes(elem_td, refs) {
  4258.            var k = 0;
  4259.            var data = '';
  4260.            for (var i = 0; i < refs.length; ++i) {
  4261.                var pre = ', ';
  4262.                if (i == 0) {
  4263.                    pre = '';
  4264.                }
  4265.                if (settings.placed.indexOf(refs[i]) !== -1) {
  4266.                    k++;
  4267.                    data += pre + stylizeRefDes(refs[i]);
  4268.                } else {
  4269.                    data += pre + refs[i];
  4270.                }
  4271.            }
  4272.            elem_td.innerHTML = data;
  4273.            return (k == refs.length);
  4274.        }
  4275.  
  4276.        function populateComponentsBody() {
  4277.            var comps = pcbdata.components.slice();
  4278.            switch (settings.canvas_layout) {
  4279.                case "T":
  4280.                    comps = comps.filter(function(comp) {
  4281.                        return comp.lay === "T";
  4282.                    });
  4283.                    break;
  4284.                case "B":
  4285.                    comps = comps.filter(function(comp) {
  4286.                        return comp.lay === "B";
  4287.                    });
  4288.                    break;
  4289.                case "TB":
  4290.                    break;
  4291.                default:
  4292.                    return;
  4293.            }
  4294.            // groupping
  4295.            if (groupFilter === null) {
  4296.                return;
  4297.            }
  4298.            var groupped = groupFilter(comps);
  4299.            // create rows
  4300.            for (var i in groupped) {
  4301.                var group = groupped[+i];
  4302.                var tr = document.createElement("tr");
  4303.                // number
  4304.                var td = document.createElement("td");
  4305.                td.innerHTML = (+i + 1).toString();
  4306.                tr.appendChild(td);
  4307.                // placed
  4308.                td = document.createElement("td");
  4309.                var cb = document.createElement("input");
  4310.                cb.type = "checkbox";
  4311.                cb.setAttribute('id', (+i + 1).toString());
  4312.                cb.onclick = function() {
  4313.                    var elem_refs = document.getElementById('refs_' + this.id);
  4314.                    var refs = elem_refs.innerHTML.split(', ');
  4315.                    for (var j = 0; j < refs.length; ++j) {
  4316.                        refs[j] = cleanRefDes(refs[j]);
  4317.                    }
  4318.                    if (this.checked) {
  4319.                        refs.forEach(function(ref) {
  4320.                            if (settings.placed.indexOf(ref) == -1) {
  4321.                                settings.placed.push(ref);
  4322.                            }
  4323.                        });
  4324.                    } else {
  4325.                        refs.forEach(function(ref) {
  4326.                            var j = settings.placed.indexOf(ref);
  4327.                            if (j != -1) {
  4328.                                settings.placed.splice(j, 1);
  4329.                            }
  4330.                        });
  4331.                    }
  4332.                    replaceRefDes(elem_refs, refs);
  4333.                }
  4334.                td.appendChild(cb);
  4335.                tr.appendChild(td);
  4336.                // refdes
  4337.                td = document.createElement("td");
  4338.                td.setAttribute('id', 'refs_' + (+i + 1).toString());
  4339.                var refs = group[0].split(', ');
  4340.                cb.checked = replaceRefDes(td, refs);
  4341.                tr.appendChild(td);
  4342.                // name
  4343.                td = document.createElement("td");
  4344.                td.innerHTML = group[1];
  4345.                tr.appendChild(td);
  4346.                // value
  4347.                td = document.createElement("td");
  4348.                td.innerHTML = group[2];
  4349.                tr.appendChild(td);
  4350.                // pattern
  4351.                td = document.createElement("td");
  4352.                td.innerHTML = group[3];
  4353.                tr.appendChild(td);
  4354.                // quantity
  4355.                if (settings.bom_group !== "U") {
  4356.                    td = document.createElement("td");
  4357.                    td.innerHTML = group[4];
  4358.                    tr.appendChild(td);
  4359.                }
  4360.                // suppliers
  4361.                if (settings.show_suppliers == true) {
  4362.                    // supplier
  4363.                    td = document.createElement("td");
  4364.                    td.innerHTML = group[5];
  4365.                    tr.appendChild(td);
  4366.                    // currency + price
  4367.                    td = document.createElement("td");
  4368.                    if (group[7] > 0) {
  4369.                        td.innerHTML = group[7] + ' ' + group[6];
  4370.                    }
  4371.                    tr.appendChild(td);
  4372.                    // link
  4373.                    td = document.createElement("td");
  4374.                    if (group[8] !== '') {
  4375.                        td.innerHTML = '<a href="' + group[8] + '" target="_blank">Visit Site</a>';
  4376.                    }
  4377.                    tr.appendChild(td);
  4378.                }
  4379.  
  4380.                bomtblbody.appendChild(tr);
  4381.                // mouse events
  4382.                tr.addEventListener("mouseenter", function(e) {
  4383.                    if (lastActive !== null) {
  4384.                        lastActive.classList.remove("active");
  4385.                    }
  4386.                    e.currentTarget.classList.add("active");
  4387.                    selectedComps = [];
  4388.                    var refs = e.currentTarget.childNodes[2].innerHTML.split(", ");
  4389.                    for (var j = 0; j < refs.length; ++j) {
  4390.                        refs[j] = cleanRefDes(refs[j]);
  4391.                    }
  4392.                    while (refs.length > 0) {
  4393.                        selectedComps.push(pcbdata.components.find(function(comp) {
  4394.                            return comp.refdes === refs[0];
  4395.                        }));
  4396.                        refs.shift();
  4397.                    }
  4398.                    drawComponentsBB(selectedComps);
  4399.                });
  4400.                tr.addEventListener("mouseleave", function(e) {
  4401.                    lastActive = e.currentTarget;
  4402.                });
  4403.            }
  4404.        }
  4405.  
  4406.        function populateBomTableBody() {
  4407.            var rowname = null;
  4408.            if (settings.bom_group === "NL" && lastActive !== null) {
  4409.                rowname = lastActive.id;
  4410.            }
  4411.            while (bomtblbody.firstChild) {
  4412.                bomtblbody.removeChild(bomtblbody.firstChild);
  4413.            }
  4414.            if (settings.bom_group === "NL") {
  4415.                populateNetBody();
  4416.                if (rowname !== null) {
  4417.                    lastActive = document.getElementById(rowname);
  4418.                    lastActive.classList.add("active");
  4419.                }
  4420.            } else {
  4421.                populateComponentsBody();
  4422.            }
  4423.        }
  4424.  
  4425.        // canvas
  4426.        function recalcLayerScale(dict, width, height) {
  4427.            if (!initDone) {
  4428.                return;
  4429.            }
  4430.            var bbox = applyRotationDeg(pcbdata.board.bound_box, settings.board_rotation);
  4431.            var scaleFactor = 0.98 * Math.min(width / (bbox.maxx - bbox.minx), height / (bbox.maxy - bbox.miny));
  4432.            if (scaleFactor < 0.1) {
  4433.                scaleFactor = 1;
  4434.            }
  4435.            dict.trsf.scale = scaleFactor;
  4436.            var flip = (dict.layer == "B");
  4437.            if (flip) {
  4438.                dict.trsf.x = -((bbox.maxx + bbox.minx) * scaleFactor + width) * 0.5;
  4439.            } else {
  4440.                dict.trsf.x = -((bbox.maxx + bbox.minx) * scaleFactor - width) * 0.5;
  4441.            }
  4442.            dict.trsf.y = -((bbox.maxy + bbox.miny) * scaleFactor - height) * 0.5;
  4443.            // setup canvas size
  4444.            cnames.forEach(function(c) {
  4445.                var canvas = dict[c];
  4446.                canvas.width = width;
  4447.                canvas.height = height;
  4448.                canvas.style.width = (width / devicePixelRatio) + "px";
  4449.                canvas.style.height = (height / devicePixelRatio) + "px";
  4450.            });
  4451.        }
  4452.  
  4453.        function prepareCanvas(canvas, flip, trsf) {
  4454.            var ctx = canvas.getContext("2d");
  4455.            ctx.setTransform(1, 0, 0, 1, 0, 0);
  4456.            ctx.scale(trsf.zoom, trsf.zoom);
  4457.            ctx.translate(trsf.panx, trsf.pany);
  4458.            if (flip) {
  4459.                ctx.scale(-1, 1);
  4460.            }
  4461.            ctx.translate(trsf.x, trsf.y);
  4462.            ctx.rotate(deg2rad(settings.board_rotation));
  4463.            ctx.scale(trsf.scale, trsf.scale);
  4464.        }
  4465.  
  4466.        function prepareLayer(dict) {
  4467.            var flip = (dict.layer == "B");
  4468.            cnames.forEach(function(c) {
  4469.                prepareCanvas(dict[c], flip, dict.trsf);
  4470.            });
  4471.        }
  4472.  
  4473.        function clearCanvas(canvas, color) {
  4474.            painter.ctx = canvas.getContext("2d");
  4475.            painter.clear(canvas.width, canvas.height, color);
  4476.        }
  4477.  
  4478.        // shapes
  4479.        function drawShape(ctx, shape, color) {
  4480.            painter.ctx = ctx;
  4481.            var rotation = null;
  4482.            if (shape.hasOwnProperty("angle")) {
  4483.                rotation = -shape.angle;
  4484.            }
  4485.            switch (shape.tp) {
  4486.                case "line":
  4487.                    painter.line(shape.point[0], shape.point[1], shape.point[2], shape.point[3], shape.lw, color);
  4488.                    break;
  4489.                case "arc":
  4490.                    painter.strokeArc(shape.point[0], shape.point[1], shape.point[2], shape.point[3], shape.point[4], shape.point[5], shape.lw, color);
  4491.                    break;
  4492.                case "closedarc":
  4493.                    painter.closedArc(shape.point[0], shape.point[1], shape.point[2], shape.point[3], shape.point[4], shape.point[5], shape.lw, color);
  4494.                    break;
  4495.                case 'fillarc':
  4496.                    painter.fillArc(shape.point[0], shape.point[1], shape.point[2], shape.point[3], shape.point[4], shape.point[5], color);
  4497.                    break;
  4498.                case "rect":
  4499.                    painter.strokeRect(shape.point[0], shape.point[1], shape.point[2], shape.point[3], 0, rotation, shape.lw, color);
  4500.                    break;
  4501.                case "fillrect":
  4502.                    painter.fillRect(shape.point[0], shape.point[1], shape.point[2], shape.point[3], 0, rotation, color);
  4503.                    break;
  4504.                case "obround":
  4505.                    painter.strokeObround(shape.point[0], shape.point[1], shape.point[2], shape.point[3], rotation, shape.lw, color);
  4506.                    break;
  4507.                case "fillobround":
  4508.                    painter.fillObround(shape.point[0], shape.point[1], shape.point[2], shape.point[3], rotation, color);
  4509.                    break;
  4510.                case "text":
  4511.                    var s = 1.0; //3*25.4/96;
  4512.                    painter.save();
  4513.                    painter.ctx.translate(shape.x, shape.y);
  4514.                    painter.ctx.rotate(-shape.angle);
  4515.                    painter.ctx.scale(s, s);
  4516.                    shape.svg.forEach(function(data) {
  4517.                        var path = new Path2D(data);
  4518.                        if (shape.lw > 0) {
  4519.                            painter.strokePath(path, shape.lw, color);
  4520.                        } else {
  4521.                            painter.fillPath(path, color);
  4522.                        }
  4523.                    });
  4524.                    painter.restore();
  4525.                    break;
  4526.                case "polyline":
  4527.                case "polygon":
  4528.                    var pts = shape.point.slice();
  4529.                    var path = new Path2D();
  4530.                    path.moveTo(pts[0], pts[1]);
  4531.                    pts.shift();
  4532.                    pts.shift();
  4533.                    while (pts.length > 0) {
  4534.                        path.lineTo(pts[0], pts[1]);
  4535.                        pts.shift();
  4536.                        pts.shift();
  4537.                    }
  4538.                    if (shape.tp === "polyline") {
  4539.                        painter.strokePath(path, shape.lw, color);
  4540.                    } else {
  4541.                        path.closePath();
  4542.                        painter.fillPath(path, color);
  4543.                    }
  4544.                    break;
  4545.            }
  4546.        }
  4547.  
  4548.        // canvas: draw components
  4549.        function drawPads(canvas, pads, padColor, layer, tp) {
  4550.            var ltp = pcbdata.board[layer].tp;
  4551.            var ring = pcbdata.board[layer].ring;
  4552.            painter.ctx = canvas.getContext("2d");
  4553.            pads.forEach(function(pad) {
  4554.                var offx = 0;
  4555.                var offy = 0;
  4556.                if (!pad.surface) {
  4557.                    offx = pad.offx;
  4558.                    offy = pad.offy;
  4559.                }
  4560.                var via = (tp === "svias" || tp === "dvias");
  4561.                var block = !pad.surface && ((layer === 'T' && pad.blockTop) || (layer === 'B' && pad.blockBottom));
  4562.                painter.save();
  4563.                painter.ctx.translate(pad.x, pad.y);
  4564.                painter.ctx.rotate(-pad.angle); // ccw to cw
  4565.                painter.ctx.translate(offx, offy);
  4566.                if (!block) {
  4567.                    if (ltp === "signal" || pad.surface || via) {
  4568.                        switch (pad.ctype) {
  4569.                            case "ellipse":
  4570.                                painter.fillEllipse(0, 0, pad.width / 2, pad.height / 2, 0, padColor);
  4571.                                break;
  4572.                            case "obround":
  4573.                                painter.fillObround(0, 0, pad.width, pad.height, 0, padColor);
  4574.                                break;
  4575.                            case "rect":
  4576.                                painter.fillRect(0, 0, pad.width, pad.height, pad.crad, 0, padColor);
  4577.                                break;
  4578.                            case "dshape":
  4579.                                painter.fillDShape(0, 0, pad.width, pad.height, padColor);
  4580.                                break;
  4581.                            case "polygon":
  4582.                                var path = new Path2D();
  4583.                                var pts = pad.point.slice();
  4584.                                path.moveTo(pts[0], pts[1]);
  4585.                                pts.shift();
  4586.                                pts.shift();
  4587.                                while (pts.length > 0) {
  4588.                                    path.lineTo(pts[0], pts[1]);
  4589.                                    pts.shift();
  4590.                                    pts.shift();
  4591.                                }
  4592.                                path.closePath();
  4593.                                painter.fillPath(path, padColor);
  4594.                                break;
  4595.                            default:
  4596.                                break;
  4597.                        }
  4598.                    } else if (ltp === "pads" && !pad.surface) {
  4599.                        var minv = Math.min(pad.width, pad.height);
  4600.                        painter.fillObround(0, 0, minv, minv, 0, padColor);
  4601.                    } else if (ltp === "ring" && !pad.surface) {
  4602.                        var diam = Infinity;
  4603.                        switch (pad.htype) {
  4604.                            case "round":
  4605.                                diam = pad.ctw + ring * 2;
  4606.                                break;
  4607.                            case "obround":
  4608.                                diam = Math.min(pad.ctw, pad.cth) + ring * 2;
  4609.                                break;
  4610.                            case "rect":
  4611.                                diam = Math.hypot(pad.ctw, pad.cth) + ring * 2;
  4612.                                break;
  4613.                            default:
  4614.                                break;
  4615.                        }
  4616.                        if (isFinite(diam)) {
  4617.                            painter.fillObround(0, 0, diam, diam, 0, padColor);
  4618.                        }
  4619.                    }
  4620.                }
  4621.                if (!pad.surface) {
  4622.                    painter.ctx.translate(-offx, -offy);
  4623.                    if (!(via && block)) {
  4624.                        switch (pad.htype) {
  4625.                            case "round":
  4626.                                painter.fillEllipse(0, 0, pad.ctw / 2, pad.ctw / 2, 0, pcbdata.board.bgcolor);
  4627.                                break;
  4628.                            case "obround":
  4629.                                painter.fillObround(0, 0, pad.ctw, pad.cth, 0, pcbdata.board.bgcolor);
  4630.                                break;
  4631.                            case "rect":
  4632.                                painter.fillRect(0, 0, pad.ctw, pad.cth, -1, 0, pcbdata.board.bgcolor);
  4633.                                break;
  4634.                            default:
  4635.                                break;
  4636.                        }
  4637.                    }
  4638.                }
  4639.                painter.restore();
  4640.            });
  4641.        }
  4642.  
  4643.        function drawComponents(tp, canvas, layer) {
  4644.            var padColor = pcbdata.colors[layer].pads;
  4645.            pcbdata[tp].forEach(function(comp) {
  4646.                var pads = comp.pads.filter(function(pad) {
  4647.                    if (pad.surface) {
  4648.                        return comp.lay === layer && !pad.sided;
  4649.                    } else {
  4650.                        return true;
  4651.                    }
  4652.                });
  4653.                drawPads(canvas, pads, padColor, layer, tp);
  4654.                if (comp.hasOwnProperty("holes") && comp.holes.length > 0) {
  4655.                    painter.ctx = canvas.getContext("2d");
  4656.                    var pts = comp.holes.slice();
  4657.                    while (pts.length > 0) {
  4658.                        painter.fillEllipse(pts[0], pts[1], pts[2], pts[2], 0, pcbdata.board.bgcolor);
  4659.                        pts = pts.slice(3);
  4660.                    }
  4661.                }
  4662.                if (comp.hasOwnProperty("shapes")) {
  4663.                    var shapes = comp.shapes.filter(function(shape) {
  4664.                        return shape.lay === layer;
  4665.                    });
  4666.                    var ctx = canvas.getContext("2d");
  4667.                    ctx.save();
  4668.                    ctx.translate(comp.x, comp.y);
  4669.                    ctx.rotate(-comp.angle);
  4670.                    shapes.forEach(function(shape) {
  4671.                        drawShape(ctx, shape, padColor);
  4672.                    });
  4673.                    ctx.restore();
  4674.                }
  4675.            });
  4676.        }
  4677.  
  4678.        function drawComponentsBB(comps) {
  4679.            clearCanvas(canvases.topcanvas.hl, null);
  4680.            clearCanvas(canvases.bottomcanvas.hl, null);
  4681.            comps.forEach(function(comp) {
  4682.                var cname = {
  4683.                    "T": "topcanvas",
  4684.                    "B": "bottomcanvas"
  4685.                }[comp.lay];
  4686.                var canvas = canvases[cname].hl;
  4687.                var lw = 1.27 / canvases[cname].trsf.zoom;
  4688.                var rbb = applyRotationRad(comp.bound_box, comp.angle);
  4689.                var x = (comp.bound_box.minx + comp.bound_box.maxx) / 2;
  4690.                var y = (comp.bound_box.miny + comp.bound_box.maxy) / 2;
  4691.                var w = rbb.maxx - rbb.minx;
  4692.                var h = rbb.maxy - rbb.miny;
  4693.                painter.ctx = canvas.getContext("2d");
  4694.                painter.save();
  4695.                painter.ctx.translate(x, y);
  4696.                painter.ctx.rotate(comp.rotate);
  4697.                painter.strokeRect(0, 0, w, h, 0, 0, lw, hlColor);
  4698.                painter.restore();
  4699.            });
  4700.        }
  4701.  
  4702.        // canvas: mounting holes
  4703.        function drawMTHoles(canvas) {
  4704.            pcbdata.mtholes.forEach(function(hole) {
  4705.                var pts = hole.point.slice();
  4706.                painter.ctx = canvas.getContext("2d");
  4707.                while (pts.length > 0) {
  4708.                    painter.fillEllipse(pts[0], pts[1], pts[2], pts[2], 0, pcbdata.board.bgcolor);
  4709.                    pts = pts.slice(3);
  4710.                }
  4711.            });
  4712.        }
  4713.  
  4714.        // canvas: draw board outline
  4715.        function drawBoardOutline(canvas, scale) {
  4716.            var color = pcbdata.board.color;
  4717.            var ctx = canvas.getContext("2d");
  4718.            // edges
  4719.            pcbdata.board.outline.forEach(function(shape) {
  4720.                var lw = null;
  4721.                if (shape.hasOwnProperty("lw")) {
  4722.                    lw = shape.lw;
  4723.                    shape.lw = Math.max(1.27 / scale, lw);
  4724.                }
  4725.                drawShape(ctx, shape, color);
  4726.                if (lw !== null) {
  4727.                    shape.lw = lw;
  4728.                }
  4729.            });
  4730.            var shapes = [];
  4731.            // holes
  4732.            shapes = pcbdata.board.cutout.filter(function(shape) {
  4733.                return !shape.hasOwnProperty("lw");
  4734.            });
  4735.            shapes.forEach(function(shape) {
  4736.                drawShape(ctx, shape, pcbdata.board.bgcolor);
  4737.            });
  4738.            // edges
  4739.            shapes = pcbdata.board.cutout.filter(function(shape) {
  4740.                return shape.hasOwnProperty("lw");
  4741.            });
  4742.            shapes.forEach(function(shape) {
  4743.                var lw = shape.lw;
  4744.                shape.lw = Math.max(1.27 / scale, lw);
  4745.                drawShape(ctx, shape, color);
  4746.                shape.lw = lw;
  4747.            });
  4748.        }
  4749.  
  4750.        // canvas: draw nets
  4751.        function drawNetPlains(canvas, plains, color) {
  4752.            var cxt = canvas.getContext("2d");
  4753.            plains.forEach(function(plain) {
  4754.                plain.lines.forEach(function(line, index) {
  4755.                    var lw = null;
  4756.                    if (index > 0 && index < plain.lines.length - 1 && line.hasOwnProperty("lw")) {
  4757.                        lw = line.lw;
  4758.                        line.lw -= (lw - 4 * Math.round(lw * 100 / 4 + 0.5) / 100) * 8;
  4759.                    }
  4760.                    drawShape(cxt, line, color);
  4761.                    if (lw) {
  4762.                        line.lw = lw;
  4763.                    }
  4764.                });
  4765.            });
  4766.        }
  4767.  
  4768.        function drawNetHLPlains(canvas, plains, color, zoom) {
  4769.            painter.ctx = canvas.getContext("2d");
  4770.            var lw = 1.27 / zoom
  4771.            plains.forEach(function(plain) {
  4772.                var pts = plain.contour.point.slice();
  4773.                var path = new Path2D();
  4774.                path.moveTo(pts[0], pts[1]);
  4775.                pts.shift();
  4776.                pts.shift();
  4777.                while (pts.length > 0) {
  4778.                    path.lineTo(pts[0], pts[1]);
  4779.                    pts.shift();
  4780.                    pts.shift();
  4781.                }
  4782.                path.closePath();
  4783.                painter.strokePath(path, lw, color);
  4784.            });
  4785.        }
  4786.  
  4787.        function drawNetLines(canvas, lines, color) {
  4788.            var ctx = canvas.getContext("2d");
  4789.            lines.forEach(function(line) {
  4790.                drawShape(ctx, line, color);
  4791.            });
  4792.        }
  4793.  
  4794.        function drawNets(canvas, layer, color) {
  4795.            if (!("nets" in pcbdata))
  4796.                return;
  4797.            pcbdata.nets.forEach(function(net) {
  4798.                if (!("lines" in net))
  4799.                    return;
  4800.                var lines = net.lines.filter(function(line) {
  4801.                    return line.lay === layer;
  4802.                });
  4803.                drawNetLines(canvas, lines, color);
  4804.            });
  4805.        }
  4806.  
  4807.        function drawPlains(canvas, layer, color) {
  4808.            if (!("nets" in pcbdata))
  4809.                return;
  4810.            pcbdata.nets.forEach(function(net) {
  4811.                var plains = net.plains.filter(function(plain) {
  4812.                    return plain.lay === layer;
  4813.                });
  4814.                drawNetPlains(canvas, plains, color);
  4815.            });
  4816.        }
  4817.  
  4818.        function drawHLNet() {
  4819.            var net = pcbdata.nets[selectedNet];
  4820.            ["T", "B"].forEach(function(layer) {
  4821.                var cname = {
  4822.                    "T": "topcanvas",
  4823.                    "B": "bottomcanvas"
  4824.                }[layer];
  4825.                var canvas = canvases[cname].hl;
  4826.                clearCanvas(canvas, null);
  4827.                // lines
  4828.                if (settings.draw_nets && ("lines" in net)) {
  4829.                    var lines = net.lines.filter(function(line) {
  4830.                        return line.lay == layer;
  4831.                    });
  4832.                    drawNetLines(canvas, lines, hlColor);
  4833.                }
  4834.                // plains
  4835.                if ("plains" in net) {
  4836.                    var plains = [];
  4837.                    plains = net.plains.filter(function(plain) {
  4838.                        return plain.lay === layer;
  4839.                    });
  4840.                    drawNetHLPlains(canvas, plains, hlPlainColor, canvases[cname].trsf.zoom);
  4841.                }
  4842.                // free shapes
  4843.                if ("freeshapes" in pcbdata) {
  4844.                    var freeshapes = [];
  4845.                    freeshapes = pcbdata.freeshapes.filter(function(shape) {
  4846.                        return (shape.lay === layer && shape.net === selectedNet);
  4847.                    });
  4848.                    freeshapes.forEach(function(shape) {
  4849.                        var ctx = canvas.getContext("2d");
  4850.                        drawShape(ctx, shape, hlColor);
  4851.                    });
  4852.                }
  4853.                // pads
  4854.                var comps = [];
  4855.                if (settings.draw_pads) {
  4856.                    comps.push("components");
  4857.                    comps.push("freepads");
  4858.                }
  4859.                if (settings.draw_fiducials) {
  4860.                    comps.push("fiducials");
  4861.                }
  4862.                if (settings.draw_vias) {
  4863.                    comps.push("sviases");
  4864.                    comps.push("dviases");
  4865.                }
  4866.                comps.forEach(function(tp) {
  4867.                    if (pcbdata[tp] === undefined) {
  4868.                        return;
  4869.                    }
  4870.                    pcbdata[tp].forEach(function(comp) {
  4871.                        var pads = comp.pads.filter(function(pad) {
  4872.                            if (pad.net === selectedNet) {
  4873.                                if (pad.surface) {
  4874.                                    return (comp.lay === layer && !pad.sided);
  4875.                                } else {
  4876.                                    return true;
  4877.                                }
  4878.                            } else {
  4879.                                return false;
  4880.                            }
  4881.                        });
  4882.                        if (pads.length > 0) {
  4883.                            drawPads(canvas, pads, hlColor, layer, tp);
  4884.                        }
  4885.                    });
  4886.                });
  4887.            });
  4888.        }
  4889.  
  4890.        // canvas: draw background layers
  4891.        function drawBack(dict, clear) {
  4892.            if (clear) {
  4893.                clearCanvas(dict.bg, null);
  4894.                clearCanvas(dict.silk, null);
  4895.                clearCanvas(dict.assy, null);
  4896.            }
  4897.            var color = pcbdata.colors[dict.layer].pads;
  4898.            if (settings.draw_nets) {
  4899.                drawNets(dict.bg, dict.layer, color);
  4900.            }
  4901.            if (settings.draw_copper_pours) {
  4902.                drawPlains(dict.bg, dict.layer, color);
  4903.            }
  4904.            // draw free shapes
  4905.            var freeshapes = pcbdata.freeshapes.filter(function(shape) {
  4906.                return shape.lay === dict.layer;
  4907.            });
  4908.            freeshapes.forEach(function(shape) {
  4909.                var ctx = dict.bg.getContext("2d");
  4910.                drawShape(ctx, shape, color);
  4911.            });
  4912.            // components, free pads, fiducials, viases
  4913.            var comps = [];
  4914.            if (settings.draw_pads) {
  4915.                comps.push("components");
  4916.                comps.push("freepads");
  4917.            }
  4918.            if (settings.draw_fiducials) {
  4919.                comps.push("fiducials");
  4920.            }
  4921.            if (settings.draw_vias) {
  4922.                comps.push("svias");
  4923.                comps.push("dvias");
  4924.            }
  4925.            comps.forEach(function(tp) {
  4926.                drawComponents(tp, dict.bg, dict.layer);
  4927.            });
  4928.            drawMTHoles(dict.bg);
  4929.            drawBoardOutline(dict.bg, dict.trsf.zoom);
  4930.            // silk
  4931.            if (settings.draw_silk) {
  4932.                var shapes = pcbdata.silk.filter(function(shape) {
  4933.                    return (shape.lay === dict.layer);
  4934.                });
  4935.                var ctx = dict.silk.getContext("2d");
  4936.                shapes.forEach(function(shape) {
  4937.                    drawShape(ctx, shape, pcbdata.colors[dict.layer].silk);
  4938.                });
  4939.            }
  4940.            // assy
  4941.            if (settings.draw_assy) {
  4942.                var ctx = dict.assy.getContext("2d");
  4943.                var assyColor = pcbdata.colors[dict.layer].assy;
  4944.  
  4945.                var shapes = pcbdata.assy.filter(function(shape) {
  4946.                    return (shape.lay === dict.layer);
  4947.                });
  4948.                shapes.forEach(function(shape) {
  4949.                    drawShape(ctx, shape, assyColor);
  4950.                });
  4951.                if (pcbdata.board.pads_on_assy) {
  4952.                    comps = [];
  4953.                    comps.push("components");
  4954.                    comps.push("freepads");
  4955.                    comps.push("fiducials");
  4956.                    comps.forEach(function(tp) {
  4957.                        pcbdata[tp].forEach(function(comp) {
  4958.                            var pads = comp.pads.filter(function(pad) {
  4959.                                if (pad.surface) {
  4960.                                    return comp.lay === dict.layer && !pad.sided;
  4961.                                } else {
  4962.                                    return true;
  4963.                                }
  4964.                            });
  4965.                            drawPads(dict.assy, pads, assyColor, dict.layer, tp);
  4966.                        });
  4967.                    });
  4968.                }
  4969.            }
  4970.        }
  4971.  
  4972.        // canvas: draw highlight on layer
  4973.        function drawHLOnLayer(dict) {
  4974.            if (selectedComps.length > 0) {
  4975.                drawComponentsBB(selectedComps);
  4976.            }
  4977.            if (selectedNet !== null && selectedNet < pcbdata.nets.length) {
  4978.                drawHLNet();
  4979.            }
  4980.        }
  4981.  
  4982.        function redrawCanvas(dict) {
  4983.            prepareLayer(dict);
  4984.            drawBack(dict, true);
  4985.            drawHLOnLayer(dict);
  4986.        }
  4987.  
  4988.        function redrawIfInitDone() {
  4989.            if (initDone) {
  4990.                redrawCanvas(canvases.topcanvas);
  4991.                redrawCanvas(canvases.bottomcanvas);
  4992.            }
  4993.        }
  4994.  
  4995.        // resizers
  4996.        function resizeCanvas(dict) {
  4997.            var divcanvasid = {
  4998.                "T": "topcanvas",
  4999.                "B": "bottomcanvas"
  5000.            }[dict.layer];
  5001.            var divcanvas = document.getElementById(divcanvasid);
  5002.            var width = divcanvas.clientWidth * devicePixelRatio;
  5003.            var height = divcanvas.clientHeight * devicePixelRatio;
  5004.            recalcLayerScale(dict, width, height);
  5005.            redrawCanvas(dict);
  5006.        }
  5007.  
  5008.        function resizeAll() {
  5009.            resizeCanvas(canvases.topcanvas);
  5010.            resizeCanvas(canvases.bottomcanvas);
  5011.        }
  5012.  
  5013.        /*----- prefs functions -----*/
  5014.        function setDisplayAssy(val) {
  5015.            settings.draw_assy = val;
  5016.            setTimeout(function() {
  5017.                redrawIfInitDone();
  5018.            }, 20);
  5019.        }
  5020.  
  5021.        function setDisplaySilk(val) {
  5022.            settings.draw_silk = val;
  5023.            setTimeout(function() {
  5024.                redrawIfInitDone();
  5025.            }, 20);
  5026.        }
  5027.  
  5028.        function setDisplayNets(val) {
  5029.            settings.draw_nets = val;
  5030.            setTimeout(function() {
  5031.                redrawIfInitDone();
  5032.            }, 20);
  5033.        }
  5034.  
  5035.        function setDisplayCopperPours(val) {
  5036.            settings.draw_copper_pours = val;
  5037.            setTimeout(function() {
  5038.                redrawIfInitDone();
  5039.            }, 20);
  5040.        }
  5041.  
  5042.        function setDisplayFiducials(val) {
  5043.            settings.draw_fiducials = val;
  5044.            setTimeout(function() {
  5045.                redrawIfInitDone();
  5046.            }, 20);
  5047.        }
  5048.  
  5049.        function setDisplayPads(val) {
  5050.            settings.draw_pads = val;
  5051.            setTimeout(function() {
  5052.                redrawIfInitDone();
  5053.            }, 20);
  5054.        }
  5055.  
  5056.        function setDisplayVias(val) {
  5057.            settings.draw_vias = val;
  5058.            setTimeout(function() {
  5059.                redrawIfInitDone();
  5060.            }, 20);
  5061.        }
  5062.  
  5063.        function setDisplaySuppliers(val) {
  5064.            settings.show_suppliers = val;
  5065.            setTimeout(function() {
  5066.                // switch bom group
  5067.                changeBomGroup(settings.bom_group);
  5068.            }, 20);
  5069.        }
  5070.  
  5071.        function setBoardRotation(degree) {
  5072.            settings.board_rotation = degree * 5;
  5073.            document.getElementById("boardRotationDegree").textContent = settings.board_rotation.toString();
  5074.            setTimeout(function() {
  5075.                resizeAll();
  5076.            }, 20);
  5077.        }
  5078.  
  5079.        function setupPrefs() {
  5080.            // setup prefs checkboxes
  5081.            document.getElementById("cbDisplayAssy").checked = settings.draw_assy;
  5082.            document.getElementById("cbDisplaySilk").checked = settings.draw_silk;
  5083.            document.getElementById("cbDisplayNets").checked = settings.draw_nets;
  5084.            document.getElementById("cbDisplayCopperPours").checked = settings.draw_copper_pours;
  5085.            document.getElementById("cbDisplayFiducials").checked = settings.draw_fiducials;
  5086.            document.getElementById("cbDisplayPads").checked = settings.draw_pads;
  5087.            document.getElementById("cbDisplayVias").checked = settings.draw_vias;
  5088.            document.getElementById("cbDisplaySuppliers").checked = settings.show_suppliers;
  5089.            // board rotation slider
  5090.            document.getElementById("boardRotation").value = (settings.board_rotation / 5.0).toString();
  5091.            document.getElementById("boardRotationDegree").textContent = settings.board_rotation.toString();
  5092.        }
  5093.  
  5094.        /*----- event handlers -----*/
  5095.  
  5096.        // window events
  5097.        function onWindowLoadHandler(e) {
  5098.            try {
  5099.                var bin = "";
  5100.                pcbdata = JSON.parse(LZString.decompressFromBase64(bin));
  5101.  
  5102.                storagePrefix = "DipTrace_BOM_" + pcbdata.metadata.board_name + "__#";
  5103.                initStorage();
  5104.                initDefaults();
  5105.                writeAll();
  5106.                initRender();
  5107.  
  5108.                setupPrefs();
  5109.                removeGutters();
  5110.  
  5111.                // hide Netlist button, if no nets
  5112.                hideNetListBnt = !("nets" in pcbdata) || (pcbdata.nets.length == 1 && pcbdata.nets[0].name === 'None')
  5113.                if (hideNetListBnt) {
  5114.                    if (settings.bom_group === "NL") {
  5115.                        settings.bom_group = "U";
  5116.                    }
  5117.                    document.getElementById("btnGNetlist").style.display = "none";
  5118.                }
  5119.  
  5120.                initDone = true;
  5121.  
  5122.                // switch bom layout
  5123.                changeBOMLayout(settings.bom_layout);
  5124.            } catch (e) {
  5125.                var ediv = document.createElement("div");
  5126.                ediv.innerHTML = "<h2 style='text-align: center; color: red;'>PCB data is incorrect or corrupted.</h2>";
  5127.                document.body.insertBefore(ediv, document.body.childNodes[0]);
  5128.            }
  5129.        }
  5130.  
  5131.        function onWindowResizeHandler(e) {
  5132.            resizeAll();
  5133.        }
  5134.  
  5135.        function onWindowBeforeUnload(e) {
  5136.            writeAll();
  5137.        }
  5138.  
  5139.        /*----- entry point -----*/
  5140.        // variables
  5141.        var initDone = false;
  5142.        var pcbdata = null;
  5143.        var storagePrefix = null;
  5144.        var storage = null;
  5145.        var lastActive = null;
  5146.        var selectedComps = [];
  5147.        var selectedNet = null;
  5148.        var hlColor = "#df4056";
  5149.        var hlPlainColor = "#ed6f15";
  5150.        var settings = {
  5151.            bom_layout: "left-right",
  5152.            bom_group: "U",
  5153.            canvas_layout: "TB",
  5154.            draw_silk: true,
  5155.            draw_assy: false,
  5156.            draw_nets: true,
  5157.            draw_copper_pours: false,
  5158.            draw_fiducials: true,
  5159.            draw_pads: true,
  5160.            draw_vias: true,
  5161.            show_suppliers: true,
  5162.            board_rotation: 0,
  5163.            placed: null
  5164.        }
  5165.        var bomsplit;
  5166.        var canvassplit;
  5167.        var cnames = ["bg", "silk", "assy", "hl"];
  5168.        var canvases = {
  5169.            topcanvas: {
  5170.                layer: "T",
  5171.                bg: document.getElementById("topBG"),
  5172.                silk: document.getElementById("topSILK"),
  5173.                assy: document.getElementById("topASSY"),
  5174.                hl: document.getElementById("topHL"),
  5175.                trsf: {
  5176.                    x: 0,
  5177.                    y: 0,
  5178.                    scale: 1,
  5179.                    panx: 0,
  5180.                    pany: 0,
  5181.                    zoom: 1
  5182.                },
  5183.                pstate: {}
  5184.            },
  5185.            bottomcanvas: {
  5186.                layer: "B",
  5187.                bg: document.getElementById("bottomBG"),
  5188.                silk: document.getElementById("bottomSILK"),
  5189.                assy: document.getElementById("bottomASSY"),
  5190.                hl: document.getElementById("bottomHL"),
  5191.                trsf: {
  5192.                    x: 0,
  5193.                    y: 0,
  5194.                    scale: 1,
  5195.                    panx: 0,
  5196.                    pany: 0,
  5197.                    zoom: 1
  5198.                },
  5199.                pstate: {}
  5200.            }
  5201.        };
  5202.        var canvasButtons = {
  5203.            btnT: document.getElementById("btnCanvasTop"),
  5204.            btnTB: document.getElementById("btnCanvasTopBottom"),
  5205.            btnB: document.getElementById("btnCanvasBottom")
  5206.        }
  5207.        var bomButtons = {
  5208.            btnBOMOnly: document.getElementById("btnBOMOnly"),
  5209.            btnBOMLeftRight: document.getElementById("btnBOMLeftRight"),
  5210.            btnBOMTopBottom: document.getElementById("btnBOMTopBottom")
  5211.        };
  5212.        var groupButtons = {
  5213.            btnU: document.getElementById("btnGUngroup"),
  5214.            btnNL: document.getElementById("btnGNetlist"),
  5215.            btnN: document.getElementById("btnGName"),
  5216.            btnNV: document.getElementById("btnGNameValue"),
  5217.            btnNP: document.getElementById("btnGNamePattern"),
  5218.            btnNVP: document.getElementById("btnGNameValuePattern")
  5219.        };
  5220.        var bomtblhead = document.getElementById("tblhead");
  5221.        var bomtblbody = document.getElementById("tblbody");
  5222.        var groupFilter = null;
  5223.        var total = {};
  5224.        var totalCount = {};
  5225.  
  5226.        // window events
  5227.        window.addEventListener("load", onWindowLoadHandler);
  5228.        window.addEventListener("resize", onWindowResizeHandler);
  5229.        window.addEventListener("beforeunload", onWindowBeforeUnload);
  5230.    </script>
  5231. </body>
  5232.  
  5233. </htm
  5234.