diff --git a/data/js/controls.js b/data/js/controls.js index 36fabe3..84b001b 100644 --- a/data/js/controls.js +++ b/data/js/controls.js @@ -60,6 +60,8 @@ const UPDATE_SEPARATOR = 119; const UI_TIME = 20; const UPDATE_TIME = 120; +const UI_FRAGMENT = 21; + const UP = 0; const DOWN = 1; const LEFT = 2; @@ -77,6 +79,8 @@ const C_ALIZARIN = 6; const C_DARK = 7; const C_NONE = 255; +var controlAssemblyArray = new Object(); +var FragmentAssemblyTimer = new Object(); var graphData = new Array(); var hasAccel = false; var sliderContinuous = false; @@ -190,6 +194,12 @@ function restart() { } function conStatusError() { + FragmentAssemblyTimer.forEach(element => { + clearInterval(element); + }); + FragmentAssemblyTimer = new Object(); + controlAssemblyArray = new Object(); + if (true === websockConnected) { websockConnected = false; websock.close(); @@ -210,17 +220,20 @@ function handleVisibilityChange() { } function start() { + let location = window.location.hostname; + let port = window.location.port; +// let location = "192.168.10.229"; +// let port = ""; + document.addEventListener("visibilitychange", handleVisibilityChange, false); if ( - window.location.port != "" || - window.location.port != 80 || - window.location.port != 443 + port != "" || + port != 80 || + port != 443 ) { - websock = new WebSocket( - "ws://" + window.location.hostname + ":" + window.location.port + "/ws" - ); + websock = new WebSocket( "ws://" + location + ":" + port + "/ws" ); } else { - websock = new WebSocket("ws://" + window.location.hostname + "/ws"); + websock = new WebSocket("ws://" + location + "/ws"); } // is the timer running? @@ -241,33 +254,54 @@ function start() { $("#conStatus").addClass("color-green"); $("#conStatus").text("Connected"); websockConnected = true; + FragmentAssemblyTimer.forEach(element => { + clearInterval(element); + }); + FragmentAssemblyTimer = new Object(); + controlAssemblyArray = new Object(); }; websock.onclose = function (evt) { + // console.log("Close evt: '" + evt + "'"); + // console.log("Close reason: '" + evt.reason + "'"); + // console.log("Close code: '" + evt.code + "'"); console.log("websock close"); conStatusError(); + FragmentAssemblyTimer.forEach(element => { + clearInterval(element); + }); + FragmentAssemblyTimer = new Object(); + controlAssemblyArray = new Object(); }; websock.onerror = function (evt) { console.log("websock Error"); - console.log(evt); + // console.log("Error evt: '" + evt + "'"); + // console.log("Error data: '" + evt.data + "'"); restart(); + FragmentAssemblyTimer.forEach(element => { + clearInterval(element); + }); + FragmentAssemblyTimer = new Object(); + controlAssemblyArray = new Object(); }; var handleEvent = function (evt) { - console.log(evt); + // console.log("handleEvent:Data evt: '" + evt + "'"); + // console.log("handleEvent:Data data: '" + evt.data + "'"); try { var data = JSON.parse(evt.data); } catch (Event) { console.error(Event); - // start the update over again + // console.info("start the update over again"); websock.send("uiok:" + 0); return; } var e = document.body; var center = ""; + // console.info("data.type: '" + data.type + "'"); switch (data.type) { case UI_INITIAL_GUI: @@ -279,7 +313,9 @@ function start() { if (data.sliderContinuous) { sliderContinuous = data.sliderContinuous; } + // console.info("UI_INITIAL_GUI:data record: '" + data + "'"); data.controls.forEach(element => { + // console.info("element: '" + JSON.stringify(element) + "'"); var fauxEvent = { data: JSON.stringify(element), }; @@ -295,7 +331,9 @@ function start() { break; case UI_EXTEND_GUI: + // console.info("UI_EXTEND_GUI data record: '" + data + "'"); data.controls.forEach(element => { + // console.info("UI_EXTEND_GUI:element: '" + JSON.stringify(element) + "'"); var fauxEvent = { data: JSON.stringify(element), }; @@ -601,6 +639,88 @@ function start() { websock.send("time:" + rv + ":" + data.id); break; + case UI_FRAGMENT: + let FragmentLen = data.length; + let FragementOffset = data.offset; + let NextFragmentOffset = FragementOffset + FragmentLen; + let Total = data.total; + let Arrived = (FragmentLen + FragementOffset); + let FragmentFinal = Total === Arrived; + // console.info("UI_FRAGMENT:FragmentLen '" + FragmentLen + "'"); + // console.info("UI_FRAGMENT:FragementOffset '" + FragementOffset + "'"); + // console.info("UI_FRAGMENT:NextFragmentOffset '" + NextFragmentOffset + "'"); + // console.info("UI_FRAGMENT:Total '" + Total + "'"); + // console.info("UI_FRAGMENT:Arrived '" + Arrived + "'"); + // console.info("UI_FRAGMENT:FragmentFinal '" + FragmentFinal + "'"); + + if (!data.hasOwnProperty('control')) + { + console.error("UI_FRAGMENT:Missing control record, skipping control"); + break; + } + let control = data.control; + StopFragmentAssemblyTimer(data.control.id); + + // is this the first fragment? + if(0 === FragementOffset) + { + // console.info("Found first fragment"); + controlAssemblyArray[control.id] = data; + // console.info("Value: " + controlAssemblyArray[control.id].control.value); + controlAssemblyArray[control.id].offset = NextFragmentOffset; + StartFragmentAssemblyTimer(control.id); + let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : NextFragmentOffset }); + websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":"); + // console.info("asked for fragment 2"); + break; + } + + // not first fragment. are we assembling this control? + if("undefined" === typeof controlAssemblyArray[control.id]) + { + // it looks like we missed the first fragment. Start the control over + console.error("Missing first fragment for control: " + control.id); + StartFragmentAssemblyTimer(control.id); + let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : 0 }); + websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":"); + // console.info("asked for fragment 1"); + break; + } + + // is this the expected next fragment + if(FragementOffset !== controlAssemblyArray[control.id].offset) + { + console.error("Wrong next fragment. Expected: " + controlAssemblyArray[control.id].offset + " Got: " + FragementOffset); + StartFragmentAssemblyTimer(control.id); + let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : controlAssemblyArray[control.id].length + controlAssemblyArray[control.id].offset }); + websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":"); + // console.info("asked for the expected fragment"); + break; + } + + // console.info("Add to existing fragment"); + controlAssemblyArray[control.id].control.value += control.value; + controlAssemblyArray[control.id].offset = NextFragmentOffset; + // console.info("Value: " + controlAssemblyArray[control.id].control.value); + + if(true === FragmentFinal) + { + var fauxEvent = { + data: JSON.stringify(controlAssemblyArray[control.id].control), + }; + handleEvent(fauxEvent); + controlAssemblyArray[control.id] = null; + // console.info("Found last fragment"); + } + else + { + // console.info("Ask for next fragment."); + StartFragmentAssemblyTimer(control.id); + let TotalRequest = JSON.stringify({ 'id' : control.id, 'offset' : NextFragmentOffset}); + websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":"); + } + break; + default: console.error("Unknown type or event"); break; @@ -650,6 +770,36 @@ function start() { websock.onmessage = handleEvent; } +function StartFragmentAssemblyTimer(Id) +{ + StopFragmentAssemblyTimer(Id); + FragmentAssemblyTimer[Id] = setInterval(function(_Id) + { + // does the fragment assembly still exist? + if("undefined" !== typeof controlAssemblyArray[_Id]) + { + if(null !== controlAssemblyArray[_Id]) + { + // we have a valid control that is being assembled + // ask for the next part + let TotalRequest = JSON.stringify({ 'id' : controlAssemblyArray[_Id].control.id, 'offset' : controlAssemblyArray[_Id].offset}); + websock.send("uifragmentok:" + 0 + ": " + TotalRequest + ":"); + } + } + }, 1000, Id); +} + +function StopFragmentAssemblyTimer(Id) +{ + if("undefined" !== typeof FragmentAssemblyTimer[Id]) + { + if(FragmentAssemblyTimer[Id]) + { + clearInterval(FragmentAssemblyTimer[Id]); + } + } +} + function sliderchange(number) { var val = $("#sl" + number).val(); websock.send("slvalue:" + val + ":" + number); diff --git a/data/js/controls.min.js b/data/js/controls.min.js index 48be64b..520ba7c 100644 --- a/data/js/controls.min.js +++ b/data/js/controls.min.js @@ -1,107 +1,128 @@ -const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;const UI_EXTEND_GUI=210;const UI_TITEL=0;const UI_PAD=1;const UPDATE_PAD=101;const UI_CPAD=2;const UPDATE_CPAD=102;const UI_BUTTON=3;const UPDATE_BUTTON=103;const UI_LABEL=4;const UPDATE_LABEL=104;const UI_SWITCHER=5;const UPDATE_SWITCHER=105;const UI_SLIDER=6;const UPDATE_SLIDER=106;const UI_NUMBER=7;const UPDATE_NUMBER=107;const UI_TEXT_INPUT=8;const UPDATE_TEXT_INPUT=108;const UI_GRAPH=9;const ADD_GRAPH_POINT=10;const CLEAR_GRAPH=109;const UI_TAB=11;const UPDATE_TAB=111;const UI_SELECT=12;const UPDATE_SELECT=112;const UI_OPTION=13;const UPDATE_OPTION=113;const UI_MIN=14;const UPDATE_MIN=114;const UI_MAX=15;const UPDATE_MAX=115;const UI_STEP=16;const UPDATE_STEP=116;const UI_GAUGE=17;const UPDATE_GAUGE=117;const UI_ACCEL=18;const UPDATE_ACCEL=118;const UI_SEPARATOR=19;const UPDATE_SEPARATOR=119;const UI_TIME=20;const UPDATE_TIME=120;const UP=0;const DOWN=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_DARK=7;const C_NONE=255;var graphData=new Array();var hasAccel=false;var sliderContinuous=false;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_DARK:case C_NONE:return"dark";default:return"";}} -var websock;var websockConnected=false;var WebSocketTimer=null;function requestOrientationPermission(){} -function saveGraphData(){localStorage.setItem("espuigraphs",JSON.stringify(graphData));} -function restoreGraphData(id){var savedData=localStorage.getItem("espuigraphs",graphData);if(savedData!=null){savedData=JSON.parse(savedData);let idData=savedData[id];return Array.isArray(idData)?idData:[];} -return[];} -function restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();} -function conStatusError(){if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}} -function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}} -function start(){document.addEventListener("visibilitychange",handleVisibilityChange,false);if(window.location.port!=""||window.location.port!=80||window.location.port!=443){websock=new WebSocket("ws://"+window.location.hostname+":"+window.location.port+"/ws");}else{websock=new WebSocket("ws://"+window.location.hostname+"/ws");} -if(null===WebSocketTimer){WebSocketTimer=setInterval(function(){if(websock.readyState===3){restart();}},5000);} -websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;};websock.onclose=function(evt){console.log("websock close");conStatusError();};websock.onerror=function(evt){console.log("websock Error");console.log(evt);restart();};var handleEvent=function(evt){console.log(evt);try{var data=JSON.parse(evt.data);} -catch(Event){console.error(Event);websock.send("uiok:"+0);return;} -var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:$("#row").html("");$("#tabsnav").html("");$("#tabscontent").html("");if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;} -data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>(data.controls.length-1)){websock.send("uiok:"+(data.controls.length-1));} -break;case UI_EXTEND_GUI:data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>data.startindex+(data.controls.length-1)){websock.send("uiok:"+(data.startindex+(data.controls.length-1)));} -break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:case UI_NUMBER:case UI_TEXT_INPUT:case UI_SELECT:case UI_GAUGE:case UI_SEPARATOR:if(data.visible)addToHTML(data);break;case UI_BUTTON:if(data.visible){addToHTML(data);$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});} -break;case UI_SWITCHER:if(data.visible){addToHTML(data);switcher(data.id,data.value);} -break;case UI_CPAD:case UI_PAD:if(data.visible){addToHTML(data);$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});} -break;case UI_SLIDER:if(data.visible){addToHTML(data);rangeSlider(!sliderContinuous);} -break;case UI_TAB:if(data.visible){$("#tabsnav").append("
  • "+data.value+"
  • ");$("#tabscontent").append("
    ");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");} -e.preventDefault();});} -break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append("");} -break;case UI_MIN:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("min",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("min",data.value);}} -break;case UI_MAX:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("max",data.value);}else if($('#text'+data.parentControl).length){$('#text'+data.parentControl).attr("maxlength",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("max",data.value);}} -break;case UI_STEP:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("step",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("step",data.value);}} -break;case UI_GRAPH:if(data.visible){addToHTML(data);graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);} -break;case ADD_GRAPH_POINT:var ts=new Date().getTime();graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_ACCEL:if(hasAccel)break;hasAccel=true;if(data.visible){addToHTML(data);requestOrientationPermission();} -break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);if(data.hasOwnProperty('elementStyle')){$("#l"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_SLIDER:$("#sl"+data.id).attr("value",data.value) -slider_move($("#sl"+data.id).parent().parent(),data.value,"100",false);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#num"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#text"+data.id).attr("style",data.elementStyle);} -if(data.hasOwnProperty('inputType')){$("#text"+data.id).attr("type",data.inputType);} -break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#select"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_BUTTON:$("#btn"+data.id).val(data.value);$("#btn"+data.id).text(data.value);if(data.hasOwnProperty('elementStyle')){$("#btn"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#gauge"+data.id).attr("style",data.elementStyle);} -break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;default:console.error("Unknown type or event");break;} -if(data.type>=UI_TITEL&&data.type=UPDATE_OFFSET&&data.type0){var parent=data.hasOwnProperty('parentControl')?$("#tab"+data.parentControl):$("#row");var html="";switch(data.type){case UI_LABEL:case UI_BUTTON:case UI_SWITCHER:case UI_CPAD:case UI_PAD:case UI_SLIDER:case UI_NUMBER:case UI_TEXT_INPUT:case UI_SELECT:case UI_GRAPH:case UI_GAUGE:case UI_ACCEL:html="
    "+data.label+"

    "+ -elementHTML(data)+ -"
    ";break;case UI_SEPARATOR:html="
    "+ -"
    "+data.label+"

    ";break;case UI_TIME:break;} -parent.append(html);}else{var parent=$("#id"+data.parentControl);parent.append(elementHTML(data));}} -var elementHTML=function(data){var id=data.id -var elementStyle=data.hasOwnProperty('elementStyle')?" style='"+data.elementStyle+"' ":"";var inputType=data.hasOwnProperty('inputType')?" type='"+data.inputType+"' ":"";switch(data.type){case UI_LABEL:return""+data.value+"";case UI_BUTTON:return"";case UI_SWITCHER:return"";case UI_CPAD:case UI_PAD:return"";case UI_SLIDER:return"
    "+ -""+ -data.value+"
    ";case UI_NUMBER:return"";case UI_TEXT_INPUT:return"";case UI_SELECT:return"";case UI_ACCEL:return"ACCEL // Not implemented fully!
    ";default:return"";}}
    -var processEnabled=function(data){switch(data.type){case UI_SWITCHER:case UPDATE_SWITCHER:if(data.enabled){$("#sl"+data.id).removeClass('disabled');$("#s"+data.id).prop("disabled",false);}else{$("#sl"+data.id).addClass('disabled');$("#s"+data.id).prop("disabled",true);}
    -break;case UI_SLIDER:case UPDATE_SLIDER:$("#sl"+data.id).prop("disabled",!data.enabled);break;case UI_NUMBER:case UPDATE_NUMBER:$("#num"+data.id).prop("disabled",!data.enabled);break;case UI_TEXT_INPUT:case UPDATE_TEXT_INPUT:$("#text"+data.id).prop("disabled",!data.enabled);break;case UI_SELECT:case UPDATE_SELECT:$("#select"+data.id).prop("disabled",!data.enabled);break;case UI_BUTTON:case UPDATE_BUTTON:$("#btn"+data.id).prop("disabled",!data.enabled);break;case UI_PAD:case UI_CPAD:case UPDATE_PAD:case UPDATE_CPAD:if(data.enabled){$("#id"+data.id+" nav").removeClass('disabled');}else{$("#id"+data.id+" nav").addClass('disabled');}
    +const UI_INITIAL_GUI=200;const UI_RELOAD=201;const UPDATE_OFFSET=100;const UI_EXTEND_GUI=210;const UI_TITEL=0;const UI_PAD=1;const UPDATE_PAD=101;const UI_CPAD=2;const UPDATE_CPAD=102;const UI_BUTTON=3;const UPDATE_BUTTON=103;const UI_LABEL=4;const UPDATE_LABEL=104;const UI_SWITCHER=5;const UPDATE_SWITCHER=105;const UI_SLIDER=6;const UPDATE_SLIDER=106;const UI_NUMBER=7;const UPDATE_NUMBER=107;const UI_TEXT_INPUT=8;const UPDATE_TEXT_INPUT=108;const UI_GRAPH=9;const ADD_GRAPH_POINT=10;const CLEAR_GRAPH=109;const UI_TAB=11;const UPDATE_TAB=111;const UI_SELECT=12;const UPDATE_SELECT=112;const UI_OPTION=13;const UPDATE_OPTION=113;const UI_MIN=14;const UPDATE_MIN=114;const UI_MAX=15;const UPDATE_MAX=115;const UI_STEP=16;const UPDATE_STEP=116;const UI_GAUGE=17;const UPDATE_GAUGE=117;const UI_ACCEL=18;const UPDATE_ACCEL=118;const UI_SEPARATOR=19;const UPDATE_SEPARATOR=119;const UI_TIME=20;const UPDATE_TIME=120;const UI_FRAGMENT=21;const UP=0;const DOWN=1;const LEFT=2;const RIGHT=3;const CENTER=4;const C_TURQUOISE=0;const C_EMERALD=1;const C_PETERRIVER=2;const C_WETASPHALT=3;const C_SUNFLOWER=4;const C_CARROT=5;const C_ALIZARIN=6;const C_DARK=7;const C_NONE=255;var controlAssemblyArray=new Object();var FragmentAssemblyTimer=new Object();var graphData=new Array();var hasAccel=false;var sliderContinuous=false;function colorClass(colorId){colorId=Number(colorId);switch(colorId){case C_TURQUOISE:return"turquoise";case C_EMERALD:return"emerald";case C_PETERRIVER:return"peterriver";case C_WETASPHALT:return"wetasphalt";case C_SUNFLOWER:return"sunflower";case C_CARROT:return"carrot";case C_ALIZARIN:return"alizarin";case C_DARK:case C_NONE:return"dark";default:return"";}}
    +var websock;var websockConnected=false;var WebSocketTimer=null;function requestOrientationPermission(){}
    +function saveGraphData(){localStorage.setItem("espuigraphs",JSON.stringify(graphData));}
    +function restoreGraphData(id){var savedData=localStorage.getItem("espuigraphs",graphData);if(savedData!=null){savedData=JSON.parse(savedData);let idData=savedData[id];return Array.isArray(idData)?idData:[];}
    +return[];}
    +function restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();}
    +function conStatusError(){FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}}
    +function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
    +function start(){let location=window.location.hostname;let port=window.location.port;document.addEventListener("visibilitychange",handleVisibilityChange,false);if(port!=""||port!=80||port!=443){websock=new WebSocket("ws://"+location+":"+port+"/ws");}else{websock=new WebSocket("ws://"+location+"/ws");}
    +if(null===WebSocketTimer){WebSocketTimer=setInterval(function(){if(websock.readyState===3){restart();}},5000);}
    +websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onclose=function(evt){console.log("websock close");conStatusError();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onerror=function(evt){console.log("websock Error");restart();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};var handleEvent=function(evt){try{var data=JSON.parse(evt.data);}
    +catch(Event){console.error(Event);websock.send("uiok:"+0);return;}
    +var e=document.body;var center="";switch(data.type){case UI_INITIAL_GUI:$("#row").html("");$("#tabsnav").html("");$("#tabscontent").html("");if(data.sliderContinuous){sliderContinuous=data.sliderContinuous;}
    +data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>(data.controls.length-1)){websock.send("uiok:"+(data.controls.length-1));}
    +break;case UI_EXTEND_GUI:data.controls.forEach(element=>{var fauxEvent={data:JSON.stringify(element),};handleEvent(fauxEvent);});if(data.totalcontrols>data.startindex+(data.controls.length-1)){websock.send("uiok:"+(data.startindex+(data.controls.length-1)));}
    +break;case UI_RELOAD:window.location.reload();break;case UI_TITEL:document.title=data.label;$("#mainHeader").html(data.label);break;case UI_LABEL:case UI_NUMBER:case UI_TEXT_INPUT:case UI_SELECT:case UI_GAUGE:case UI_SEPARATOR:if(data.visible)addToHTML(data);break;case UI_BUTTON:if(data.visible){addToHTML(data);$("#btn"+data.id).on({touchstart:function(e){e.preventDefault();buttonclick(data.id,true);},touchend:function(e){e.preventDefault();buttonclick(data.id,false);},});}
    +break;case UI_SWITCHER:if(data.visible){addToHTML(data);switcher(data.id,data.value);}
    +break;case UI_CPAD:case UI_PAD:if(data.visible){addToHTML(data);$("#pf"+data.id).on({touchstart:function(e){e.preventDefault();padclick(UP,data.id,true);},touchend:function(e){e.preventDefault();padclick(UP,data.id,false);},});$("#pl"+data.id).on({touchstart:function(e){e.preventDefault();padclick(LEFT,data.id,true);},touchend:function(e){e.preventDefault();padclick(LEFT,data.id,false);},});$("#pr"+data.id).on({touchstart:function(e){e.preventDefault();padclick(RIGHT,data.id,true);},touchend:function(e){e.preventDefault();padclick(RIGHT,data.id,false);},});$("#pb"+data.id).on({touchstart:function(e){e.preventDefault();padclick(DOWN,data.id,true);},touchend:function(e){e.preventDefault();padclick(DOWN,data.id,false);},});$("#pc"+data.id).on({touchstart:function(e){e.preventDefault();padclick(CENTER,data.id,true);},touchend:function(e){e.preventDefault();padclick(CENTER,data.id,false);},});}
    +break;case UI_SLIDER:if(data.visible){addToHTML(data);rangeSlider(!sliderContinuous);}
    +break;case UI_TAB:if(data.visible){$("#tabsnav").append("
  • "+data.value+"
  • ");$("#tabscontent").append("
    ");tabs=$(".tabscontent").tabbedContent({loop:true}).data("api");$("a").filter(function(){return $(this).attr("href")==="#click-to-switch";}).on("click",function(e){var tab=prompt("Tab to switch to (number or id)?");if(!tabs.switchTab(tab)){alert("That tab does not exist :\\");} +e.preventDefault();});} +break;case UI_OPTION:if(data.parentControl){var parent=$("#select"+data.parentControl);parent.append("");} +break;case UI_MIN:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("min",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("min",data.value);}} +break;case UI_MAX:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("max",data.value);}else if($('#text'+data.parentControl).length){$('#text'+data.parentControl).attr("maxlength",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("max",data.value);}} +break;case UI_STEP:if(data.parentControl){if($('#sl'+data.parentControl).length){$('#sl'+data.parentControl).attr("step",data.value);}else if($('#num'+data.parentControl).length){$('#num'+data.parentControl).attr("step",data.value);}} +break;case UI_GRAPH:if(data.visible){addToHTML(data);graphData[data.id]=restoreGraphData(data.id);renderGraphSvg(graphData[data.id],"graph"+data.id);} +break;case ADD_GRAPH_POINT:var ts=new Date().getTime();graphData[data.id].push({x:ts,y:data.value});saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case CLEAR_GRAPH:graphData[data.id]=[];saveGraphData();renderGraphSvg(graphData[data.id],"graph"+data.id);break;case UI_ACCEL:if(hasAccel)break;hasAccel=true;if(data.visible){addToHTML(data);requestOrientationPermission();} +break;case UPDATE_LABEL:$("#l"+data.id).html(data.value);if(data.hasOwnProperty('elementStyle')){$("#l"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_SWITCHER:switcher(data.id,data.value=="0"?0:1);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_SLIDER:$("#sl"+data.id).attr("value",data.value) +slider_move($("#sl"+data.id).parent().parent(),data.value,"100",false);if(data.hasOwnProperty('elementStyle')){$("#sl"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_NUMBER:$("#num"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#num"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_TEXT_INPUT:$("#text"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#text"+data.id).attr("style",data.elementStyle);} +if(data.hasOwnProperty('inputType')){$("#text"+data.id).attr("type",data.inputType);} +break;case UPDATE_SELECT:$("#select"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#select"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_BUTTON:$("#btn"+data.id).val(data.value);$("#btn"+data.id).text(data.value);if(data.hasOwnProperty('elementStyle')){$("#btn"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_PAD:case UPDATE_CPAD:break;case UPDATE_GAUGE:$("#gauge"+data.id).val(data.value);if(data.hasOwnProperty('elementStyle')){$("#gauge"+data.id).attr("style",data.elementStyle);} +break;case UPDATE_ACCEL:break;case UPDATE_TIME:var rv=new Date().toISOString();websock.send("time:"+rv+":"+data.id);break;case UI_FRAGMENT:let FragmentLen=data.length;let FragementOffset=data.offset;let NextFragmentOffset=FragementOffset+FragmentLen;let Total=data.total;let Arrived=(FragmentLen+FragementOffset);let FragmentFinal=Total===Arrived;if(!data.hasOwnProperty('control')) +{console.error("UI_FRAGMENT:Missing control record, skipping control");break;} +let control=data.control;StopFragmentAssemblyTimer(data.control.id);if(0===FragementOffset) +{controlAssemblyArray[control.id]=data;controlAssemblyArray[control.id].offset=NextFragmentOffset;StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':NextFragmentOffset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;} +if("undefined"===typeof controlAssemblyArray[control.id]) +{console.error("Missing first fragment for control: "+control.id);StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':0});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;} +if(FragementOffset!==controlAssemblyArray[control.id].offset) +{console.error("Wrong next fragment. Expected: "+controlAssemblyArray[control.id].offset+" Got: "+FragementOffset);StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':controlAssemblyArray[control.id].length+controlAssemblyArray[control.id].offset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");break;} +controlAssemblyArray[control.id].control.value+=control.value;controlAssemblyArray[control.id].offset=NextFragmentOffset;if(true===FragmentFinal) +{var fauxEvent={data:JSON.stringify(controlAssemblyArray[control.id].control),};handleEvent(fauxEvent);controlAssemblyArray[control.id]=null;} +else +{StartFragmentAssemblyTimer(control.id);let TotalRequest=JSON.stringify({'id':control.id,'offset':NextFragmentOffset});websock.send("uifragmentok:"+0+": "+TotalRequest+":");} +break;default:console.error("Unknown type or event");break;} +if(data.type>=UI_TITEL&&data.type=UPDATE_OFFSET&&data.type0){var parent=data.hasOwnProperty('parentControl')?$("#tab"+data.parentControl):$("#row");var html="";switch(data.type){case UI_LABEL:case UI_BUTTON:case UI_SWITCHER:case UI_CPAD:case UI_PAD:case UI_SLIDER:case UI_NUMBER:case UI_TEXT_INPUT:case UI_SELECT:case UI_GRAPH:case UI_GAUGE:case UI_ACCEL:html="
    "+data.label+"

    "+ +elementHTML(data)+ +"
    ";break;case UI_SEPARATOR:html="
    "+ +"
    "+data.label+"

    ";break;case UI_TIME:break;} +parent.append(html);}else{var parent=$("#id"+data.parentControl);parent.append(elementHTML(data));}} +var elementHTML=function(data){var id=data.id +var elementStyle=data.hasOwnProperty('elementStyle')?" style='"+data.elementStyle+"' ":"";var inputType=data.hasOwnProperty('inputType')?" type='"+data.inputType+"' ":"";switch(data.type){case UI_LABEL:return""+data.value+"";case UI_BUTTON:return"";case UI_SWITCHER:return"";case UI_CPAD:case UI_PAD:return"";case UI_SLIDER:return"
    "+ +""+ +data.value+"
    ";case UI_NUMBER:return"";case UI_TEXT_INPUT:return"";case UI_SELECT:return"";case UI_ACCEL:return"ACCEL // Not implemented fully!
    ";default:return"";}}
    +var processEnabled=function(data){switch(data.type){case UI_SWITCHER:case UPDATE_SWITCHER:if(data.enabled){$("#sl"+data.id).removeClass('disabled');$("#s"+data.id).prop("disabled",false);}else{$("#sl"+data.id).addClass('disabled');$("#s"+data.id).prop("disabled",true);}
    +break;case UI_SLIDER:case UPDATE_SLIDER:$("#sl"+data.id).prop("disabled",!data.enabled);break;case UI_NUMBER:case UPDATE_NUMBER:$("#num"+data.id).prop("disabled",!data.enabled);break;case UI_TEXT_INPUT:case UPDATE_TEXT_INPUT:$("#text"+data.id).prop("disabled",!data.enabled);break;case UI_SELECT:case UPDATE_SELECT:$("#select"+data.id).prop("disabled",!data.enabled);break;case UI_BUTTON:case UPDATE_BUTTON:$("#btn"+data.id).prop("disabled",!data.enabled);break;case UI_PAD:case UI_CPAD:case UPDATE_PAD:case UPDATE_CPAD:if(data.enabled){$("#id"+data.id+" nav").removeClass('disabled');}else{$("#id"+data.id+" nav").addClass('disabled');}
     break;}}
    \ No newline at end of file
    diff --git a/src/dataControlsJS.h b/src/dataControlsJS.h
    index 175b696..fdb89ab 100644
    --- a/src/dataControlsJS.h
    +++ b/src/dataControlsJS.h
    @@ -7,7 +7,7 @@ return[];}
     function restart(){$(document).add("*").off();$("#row").html("");conStatusError();start();}
     function conStatusError(){FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();if(true===websockConnected){websockConnected=false;websock.close();$("#conStatus").removeClass("color-green");$("#conStatus").addClass("color-red");$("#conStatus").html("Error / No Connection ↻");$("#conStatus").off();$("#conStatus").on({click:restart,});}}
     function handleVisibilityChange(){if(!websockConnected&&!document.hidden){restart();}}
    -function start(){let location=window.location.hostname;let port=window.location.port;document.addEventListener("visibilitychange",handleVisibilityChange,false);if(port!=""||port!=80||port!=443){websock=new WebSocket("ws://"+location+"/ws");}else{websock=new WebSocket("ws://"+location+"/ws");}
    +function start(){let location=window.location.hostname;let port=window.location.port;document.addEventListener("visibilitychange",handleVisibilityChange,false);if(port!=""||port!=80||port!=443){websock=new WebSocket("ws://"+location+":"+port+"/ws");}else{websock=new WebSocket("ws://"+location+"/ws");}
     if(null===WebSocketTimer){WebSocketTimer=setInterval(function(){if(websock.readyState===3){restart();}},5000);}
     websock.onopen=function(evt){console.log("websock open");$("#conStatus").addClass("color-green");$("#conStatus").text("Connected");websockConnected=true;FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onclose=function(evt){console.log("websock close");conStatusError();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};websock.onerror=function(evt){console.log("websock Error");restart();FragmentAssemblyTimer.forEach(element=>{clearInterval(element);});FragmentAssemblyTimer=new Object();controlAssemblyArray=new Object();};var handleEvent=function(evt){try{var data=JSON.parse(evt.data);}
     catch(Event){console.error(Event);websock.send("uiok:"+0);return;}
    @@ -129,4 +129,4 @@ break;case UI_SLIDER:case UPDATE_SLIDER:$("#sl"+data.id).prop("disabled",!data.e
     break;}}
     )=====";
     
    -const uint8_t JS_CONTROLS_GZIP[4837] PROGMEM = { 31,139,8,0,112,220,0,101,2,255,213,60,107,119,218,72,178,223,253,43,100,101,78,128,107,130,33,153,100,51,96,57,135,96,146,176,107,27,95,27,111,230,108,38,215,71,160,198,104,45,36,173,36,252,88,134,255,126,171,171,31,234,214,3,176,61,185,59,247,75,12,213,213,213,245,234,238,170,234,34,147,192,143,19,227,114,112,53,56,29,140,6,221,227,171,207,151,3,235,117,179,217,153,136,129,243,254,241,176,123,4,176,150,128,157,29,117,71,253,171,225,167,79,23,253,145,213,82,113,251,191,142,250,167,71,140,70,75,129,143,6,163,254,177,165,0,206,128,98,134,30,130,210,69,6,87,61,10,121,173,35,245,24,214,235,20,235,227,229,104,52,60,181,222,232,120,28,218,106,190,73,49,143,187,31,129,137,159,117,68,6,108,53,127,78,241,46,190,14,70,189,47,253,115,235,173,142,42,225,173,230,91,5,251,120,112,4,176,119,25,92,6,109,53,223,165,152,167,151,39,31,1,246,23,29,147,67,91,205,191,40,234,2,61,130,65,206,46,71,214,123,29,91,25,105,53,223,167,51,62,159,119,207,190,88,191,112,64,247,232,136,65,174,206,134,131,83,138,202,7,122,199,253,238,57,71,110,53,127,81,86,236,126,180,90,25,131,48,152,98,144,139,254,113,191,7,212,50,54,17,224,150,98,149,225,217,104,64,245,159,49,139,0,183,20,179,156,12,0,144,177,10,194,90,138,77,78,186,191,90,173,140,61,16,214,82,77,49,234,159,89,173,172,37,16,216,82,236,240,185,123,249,185,111,181,50,118,224,208,150,98,134,110,175,71,125,35,99,2,14,109,189,87,21,115,214,61,239,142,134,96,198,95,178,186,145,35,45,85,221,131,147,62,236,168,140,190,41,176,245,90,217,37,159,206,187,159,79,250,96,192,215,169,105,228,46,58,26,126,61,149,123,232,184,255,105,36,247,202,249,224,243,151,145,220,17,61,32,0,14,38,148,217,187,26,93,158,255,247,229,112,112,209,151,164,122,87,253,147,254,121,247,56,221,147,189,171,179,62,204,58,31,252,29,166,190,150,192,175,253,81,247,226,236,75,247,88,33,127,117,113,121,250,233,120,248,85,91,163,215,61,63,31,142,228,14,234,93,117,143,7,255,232,158,131,89,223,73,208,81,247,252,111,114,55,244,174,78,135,167,160,147,183,111,59,183,118,100,0,48,137,2,175,27,199,100,62,246,30,186,81,100,63,88,62,185,51,134,227,127,146,73,82,173,33,214,167,200,190,158,19,63,17,104,35,119,78,162,60,218,117,100,135,179,35,59,177,113,8,105,241,145,153,29,119,39,19,226,89,83,219,139,9,130,98,207,117,72,212,131,245,93,127,17,44,98,62,52,93,248,147,196,13,124,224,204,11,162,158,103,199,113,21,63,14,156,218,146,127,176,78,23,243,49,137,36,188,19,223,185,201,100,166,224,217,49,81,13,208,142,72,178,136,124,19,254,249,215,34,112,99,98,118,56,10,183,135,64,32,32,151,237,57,114,56,53,142,192,8,73,66,162,200,189,37,145,68,74,141,37,144,238,72,98,199,225,204,246,18,137,36,141,39,112,226,133,63,245,130,59,133,14,179,165,24,159,216,81,20,164,243,133,93,197,176,237,185,255,182,35,215,151,8,212,202,109,254,153,154,88,32,58,118,116,99,118,28,50,181,23,94,34,128,102,103,181,218,161,86,184,35,227,56,152,220,116,148,207,96,18,31,108,74,28,197,88,95,201,248,2,134,72,194,45,191,240,188,212,82,17,249,215,130,196,201,48,114,193,69,108,10,58,35,209,220,141,99,248,84,173,45,87,59,18,51,182,111,201,103,225,36,48,228,5,19,219,187,72,2,112,47,210,136,73,50,72,200,188,106,146,56,92,184,232,75,177,89,255,235,197,240,180,17,39,32,233,181,59,125,168,74,23,171,213,58,10,225,8,214,15,34,133,182,11,94,128,94,6,43,58,232,146,218,90,215,133,107,165,196,59,238,180,42,167,238,162,188,181,101,74,11,153,10,237,40,38,41,86,173,227,145,196,112,25,130,132,126,115,157,239,29,166,116,182,33,26,110,204,54,6,195,172,125,96,127,219,223,190,131,60,12,17,63,106,162,217,17,108,177,229,79,85,39,152,44,232,62,172,53,108,199,169,154,255,101,214,26,193,116,10,123,236,167,170,249,34,10,238,224,251,44,153,123,85,211,172,209,237,126,1,214,88,196,125,240,163,8,112,56,25,149,118,22,103,89,184,209,27,211,32,234,219,176,191,136,71,232,160,117,184,156,120,196,142,6,62,108,133,91,219,19,112,32,93,235,108,113,84,108,62,115,64,251,73,180,32,150,101,101,125,178,182,44,241,82,14,110,76,188,0,172,194,52,34,197,3,189,68,100,30,220,18,118,158,152,120,80,188,186,142,8,241,205,60,42,232,86,195,139,136,83,128,197,20,141,138,51,246,141,211,192,224,28,81,189,190,124,241,254,221,155,183,157,130,89,169,185,52,168,95,5,149,186,147,155,54,183,118,29,52,185,82,12,53,179,125,199,35,127,119,99,119,236,122,110,242,208,3,192,53,136,185,4,77,237,102,53,242,242,229,174,112,148,198,204,117,28,226,215,150,210,139,52,178,194,179,168,231,210,253,65,129,214,157,235,59,193,93,67,124,111,204,130,56,241,237,57,65,255,14,131,40,201,97,80,96,71,46,9,234,235,223,194,135,99,55,78,136,15,199,180,121,43,249,158,32,223,102,189,88,158,58,154,18,205,79,73,238,90,166,249,251,239,236,211,251,166,248,244,243,207,111,164,19,160,215,200,179,169,106,222,197,237,253,125,115,79,48,182,103,238,223,129,122,59,43,2,100,31,59,103,7,184,160,251,30,156,80,63,253,106,203,204,105,72,15,46,177,21,132,106,153,105,132,83,70,196,118,30,168,181,169,75,191,209,173,81,127,219,108,54,233,122,2,57,240,131,144,248,150,164,68,110,19,122,243,249,113,224,17,208,249,53,176,204,48,13,138,183,133,255,150,249,121,66,238,65,126,233,54,128,145,219,91,116,23,118,254,36,135,194,170,147,106,8,119,249,54,42,66,196,162,211,240,79,40,20,161,172,109,35,20,202,0,66,165,110,244,167,145,134,5,123,116,115,227,25,144,145,38,137,30,240,86,118,50,151,40,12,54,28,188,67,87,59,176,13,129,101,156,157,138,143,170,225,64,169,177,152,248,112,9,46,220,224,166,109,238,53,107,252,154,237,176,192,134,88,242,64,26,7,206,3,11,118,9,149,28,78,21,17,48,210,53,27,201,67,72,120,200,168,167,231,237,130,91,149,130,18,123,28,251,246,109,17,152,170,8,22,81,135,224,24,192,101,178,241,46,196,19,217,8,184,16,15,228,65,56,215,126,92,96,85,42,27,132,119,247,76,229,75,138,222,206,196,77,194,212,245,85,71,49,79,85,206,66,31,16,172,38,65,98,123,98,189,195,170,190,188,71,252,235,100,246,170,85,147,167,176,110,136,82,116,16,100,12,7,225,77,71,168,58,45,98,180,255,179,18,50,189,211,173,4,23,27,185,223,123,146,196,219,204,207,235,128,21,125,218,217,27,53,34,94,96,59,176,163,116,108,44,239,180,165,99,39,110,226,17,230,53,158,61,38,30,186,225,220,118,253,47,112,223,64,98,193,189,48,69,200,210,195,162,76,91,124,99,21,18,249,53,45,129,72,16,171,64,200,175,152,202,43,131,60,5,111,11,45,227,189,239,145,26,92,72,163,224,203,232,228,184,202,54,185,206,4,43,33,229,38,45,179,179,168,112,227,196,55,247,16,13,2,124,12,155,146,96,49,153,161,238,219,233,89,83,91,146,70,24,17,106,246,35,150,248,80,85,46,146,132,222,28,16,102,85,57,137,58,189,223,192,40,117,164,2,54,125,10,13,30,180,172,48,102,203,152,87,148,178,54,75,199,78,36,136,150,4,89,134,110,123,200,96,134,44,173,206,73,189,211,207,91,41,47,156,62,89,119,161,237,48,161,47,207,234,79,213,93,17,13,85,119,200,162,247,124,22,105,137,230,249,76,106,84,114,108,70,207,103,19,139,71,207,231,83,39,147,99,116,252,124,70,105,253,235,249,124,106,84,114,108,78,158,207,38,43,191,61,159,209,12,157,181,187,27,139,207,155,55,95,68,147,155,11,188,215,171,187,185,56,32,71,118,212,253,152,167,169,7,30,118,24,226,13,116,224,185,135,7,182,17,248,115,160,68,22,161,85,1,28,38,135,212,232,158,89,171,24,179,136,76,173,10,165,160,192,43,135,252,11,30,51,123,230,193,190,125,120,176,15,36,11,35,26,185,166,227,222,26,174,131,75,105,196,14,246,97,132,206,165,243,44,32,208,208,9,192,183,49,113,122,236,123,117,233,5,65,216,166,102,90,213,48,248,171,154,118,232,178,149,109,192,158,186,30,4,107,106,66,197,203,40,63,85,147,153,27,3,63,73,2,185,37,21,204,172,65,90,5,185,13,149,251,85,18,188,98,103,169,9,23,62,117,38,19,225,102,93,117,0,26,79,0,59,86,24,5,243,16,146,160,145,61,54,146,192,96,19,233,39,72,253,104,137,209,128,228,30,124,242,3,139,227,118,169,60,13,134,4,51,170,240,21,98,2,219,35,17,37,49,179,19,74,211,112,2,18,27,126,144,24,228,30,50,96,163,253,219,111,152,78,22,248,92,129,75,177,194,189,52,63,132,199,48,163,199,34,9,198,54,3,81,245,190,136,33,230,153,36,220,6,58,106,135,125,77,141,22,132,152,241,83,187,177,143,230,222,142,176,221,142,89,49,208,5,172,138,128,50,143,160,3,2,194,22,35,20,251,80,192,48,168,0,192,193,62,163,121,104,230,37,58,25,148,138,3,224,159,170,149,23,177,87,41,18,129,199,77,212,245,203,113,152,19,204,93,223,212,47,76,154,241,27,156,62,152,114,243,2,165,72,101,43,228,228,236,254,250,227,229,180,239,215,200,73,243,249,205,43,148,99,201,53,24,250,143,214,104,78,150,220,241,58,234,159,253,112,149,198,9,9,127,176,164,5,75,100,69,197,151,194,205,23,137,44,80,127,227,91,247,187,149,171,124,139,123,20,210,97,72,70,34,28,184,184,189,174,230,231,214,77,132,165,87,175,190,119,51,143,155,109,60,51,99,76,248,129,12,169,214,104,21,157,150,9,170,69,140,53,194,69,60,171,46,239,219,73,92,127,104,167,194,195,153,151,121,5,120,10,163,10,155,202,83,107,187,64,63,223,190,255,193,235,137,247,74,106,45,241,172,85,99,227,242,149,11,203,102,155,195,130,181,239,38,153,131,84,121,69,199,186,132,26,40,167,89,30,247,47,177,52,48,52,188,243,207,162,32,132,43,234,161,90,225,57,242,69,242,224,145,74,141,5,21,42,33,225,175,48,204,29,86,157,81,204,146,76,113,214,100,48,112,59,55,205,15,205,118,235,113,172,197,207,230,141,5,104,37,180,144,53,109,99,238,176,224,236,138,62,21,84,115,179,216,230,174,166,31,148,169,117,179,213,108,154,74,1,251,255,78,72,158,182,83,90,112,16,41,196,104,137,239,169,94,161,83,122,10,91,74,249,0,99,73,184,118,254,32,222,50,164,54,51,87,70,220,245,195,69,50,122,8,215,83,166,245,65,78,88,78,40,113,55,86,30,201,133,102,207,21,56,71,236,41,246,224,101,150,124,21,37,203,89,30,3,31,10,158,202,188,78,234,41,156,167,197,142,180,55,169,157,71,99,213,40,186,228,181,189,184,38,127,144,238,179,180,158,34,0,187,47,10,182,200,224,164,143,215,106,116,171,94,171,73,48,184,24,94,96,97,179,154,173,118,39,112,223,182,205,189,232,118,207,108,151,222,79,162,157,165,77,95,236,68,97,255,152,248,188,84,136,145,75,71,140,33,243,195,233,52,38,9,27,15,240,51,142,159,130,225,197,124,142,146,153,178,167,144,199,41,35,90,89,181,210,34,43,2,187,216,49,225,88,85,5,123,47,67,169,214,81,185,253,228,250,64,134,17,179,44,62,31,115,176,66,203,241,90,43,24,109,39,243,102,96,170,250,56,161,151,171,127,45,186,94,140,136,76,130,200,169,27,241,141,27,134,202,128,41,52,186,218,161,76,113,168,165,150,117,59,23,73,16,22,62,154,104,213,95,180,14,176,221,4,41,178,2,35,171,185,23,149,111,233,204,239,184,98,103,19,22,183,152,149,183,22,48,105,71,73,49,151,42,131,210,112,231,44,36,177,50,181,245,101,197,117,42,237,116,70,189,194,150,172,180,243,107,174,242,15,52,83,142,192,30,106,192,115,33,169,84,151,163,190,156,106,28,180,101,46,32,66,155,186,62,113,76,208,27,61,128,131,169,177,73,13,121,211,11,115,79,221,8,18,113,193,133,49,13,100,223,19,229,68,85,196,15,215,87,243,143,80,79,198,145,118,45,107,75,23,201,171,232,107,20,128,130,124,176,162,212,79,195,232,223,135,152,234,43,218,217,68,121,207,52,62,7,9,157,144,219,214,63,92,167,27,89,100,39,222,182,162,60,219,66,27,215,17,159,89,145,197,210,190,62,103,183,167,109,51,218,49,10,86,223,226,253,108,91,174,215,60,176,109,60,206,176,111,108,181,67,19,236,157,229,255,167,179,73,220,234,162,141,46,123,199,248,55,126,112,231,27,244,164,162,37,67,172,243,233,123,86,62,53,31,90,226,33,239,229,75,9,60,208,122,189,107,203,48,10,38,36,142,251,190,13,153,163,83,21,111,227,25,58,234,28,141,152,246,140,205,202,134,226,45,149,198,52,174,163,132,14,101,193,80,104,251,196,211,66,33,117,90,65,28,148,78,88,23,115,243,108,152,210,228,40,223,36,12,142,240,220,58,241,44,184,131,40,8,93,38,55,56,131,108,173,154,85,140,101,105,217,95,109,201,69,215,91,192,88,166,247,74,118,132,242,126,212,87,188,3,84,124,77,219,61,5,36,237,237,20,16,217,201,41,0,172,117,83,124,147,157,154,84,10,34,90,164,116,54,232,57,43,219,93,121,252,0,223,107,162,119,169,80,132,148,119,193,180,194,173,202,166,228,143,51,182,142,163,82,62,118,74,124,146,214,249,241,129,227,21,79,158,175,240,155,89,107,16,250,134,175,212,239,121,225,254,91,243,59,175,10,232,149,124,150,142,211,252,131,65,233,165,84,229,197,141,66,76,86,64,87,26,104,230,192,30,92,62,150,114,60,169,221,142,107,14,156,129,83,163,7,82,89,68,71,123,140,11,71,190,13,224,84,43,236,255,186,66,146,122,44,179,187,62,150,129,41,223,217,28,122,78,150,221,234,28,235,81,199,98,158,66,99,235,139,20,177,159,121,51,174,86,171,122,171,217,108,214,7,78,77,183,200,26,141,151,107,175,212,20,108,206,186,97,189,1,170,28,147,178,172,244,73,162,103,179,230,69,254,50,196,78,85,32,98,137,34,14,135,99,182,153,85,84,236,161,207,130,142,224,47,166,110,28,187,243,232,237,163,23,175,178,123,138,63,42,73,206,217,50,107,56,199,66,207,58,214,253,50,206,149,85,104,129,96,205,26,172,172,178,110,145,100,155,69,196,203,102,225,18,244,45,114,237,10,246,120,139,53,88,165,101,157,161,121,41,102,173,177,183,88,72,109,36,97,195,117,55,118,32,134,192,107,145,127,212,201,142,41,76,161,134,207,20,25,148,69,88,188,156,124,221,166,59,168,158,95,80,220,172,108,4,130,121,222,223,102,199,252,174,113,220,24,143,125,56,117,151,178,207,142,119,209,41,13,116,236,241,188,93,38,66,56,217,44,67,56,209,132,208,170,38,229,132,167,91,16,158,150,17,166,189,9,229,164,183,208,123,56,46,35,77,219,72,202,73,123,91,144,246,202,72,99,231,71,57,237,104,11,218,81,1,109,237,220,19,37,125,238,49,49,109,97,70,135,137,89,51,51,251,97,4,45,203,100,79,193,212,117,128,192,228,134,121,78,102,159,216,176,202,45,209,15,67,141,136,210,201,44,136,232,205,220,130,18,164,57,155,104,233,63,0,72,201,201,231,62,46,82,43,45,203,175,99,35,139,3,209,81,152,142,139,246,147,12,237,102,158,118,9,91,27,200,139,174,20,214,235,170,244,151,164,13,183,110,124,228,198,19,216,171,188,221,1,145,172,210,235,70,249,77,214,100,108,41,215,142,118,247,233,119,16,156,24,84,128,208,179,39,164,186,255,63,191,29,237,237,95,215,77,12,204,88,207,11,246,242,96,209,188,93,112,145,169,1,30,133,240,27,108,181,226,29,51,165,55,96,201,196,14,30,100,42,131,19,219,243,198,246,228,230,130,64,54,182,107,153,212,42,38,243,87,85,61,98,82,202,173,80,196,74,248,155,138,194,116,161,225,236,148,175,91,231,171,118,86,43,209,32,45,31,2,83,61,99,52,189,76,83,40,107,99,78,246,193,52,48,251,162,61,27,153,252,107,143,182,109,180,77,179,131,160,59,96,179,152,28,29,161,132,232,95,196,47,173,175,106,239,218,149,218,239,191,203,59,183,252,109,252,176,169,53,172,108,67,247,195,58,178,105,59,54,235,50,7,235,175,111,229,214,187,91,249,251,71,174,51,179,180,167,50,211,229,245,244,46,89,124,154,46,238,153,101,47,3,76,20,217,87,165,164,184,104,201,61,213,178,198,132,30,21,86,37,185,11,232,79,36,23,115,63,22,24,212,140,20,193,142,28,35,97,189,238,180,123,167,56,163,195,134,173,217,91,209,1,198,58,121,204,131,125,0,29,204,162,125,218,226,195,115,195,244,197,26,59,125,176,199,43,243,224,144,182,254,62,69,148,152,253,106,10,73,10,153,104,107,26,172,182,134,193,98,78,240,73,69,148,93,244,30,40,202,154,216,206,153,70,42,201,230,218,38,170,156,62,228,1,172,140,100,183,52,29,6,77,112,37,168,216,107,246,185,254,16,149,219,233,234,176,220,235,184,144,120,159,180,54,189,119,2,77,172,149,8,146,114,72,210,219,180,175,248,47,73,15,98,48,41,218,26,110,43,97,101,141,193,29,105,104,180,161,129,255,190,186,139,236,48,223,127,72,137,29,154,217,214,112,177,20,11,154,113,49,124,85,44,91,142,183,67,210,0,8,48,149,72,155,77,169,27,120,59,211,94,55,83,109,157,44,194,100,23,109,229,80,239,139,3,78,25,178,194,171,60,80,4,183,76,90,202,108,188,89,53,188,243,80,252,152,64,116,77,180,204,15,242,210,7,163,192,14,44,169,170,193,31,23,110,29,52,44,253,242,74,132,110,6,159,103,242,29,69,119,38,95,211,245,57,12,141,207,253,1,87,27,7,247,21,198,185,96,60,240,123,84,47,130,81,250,171,62,166,33,140,0,177,75,112,3,231,166,216,178,7,251,168,25,69,117,185,163,87,168,16,178,16,193,172,120,225,59,60,88,120,140,107,173,245,149,217,90,109,49,55,116,99,83,14,77,197,216,133,168,220,218,40,58,237,150,103,125,173,47,95,252,242,238,109,179,147,118,199,110,90,157,245,100,111,203,64,6,91,227,33,122,50,15,216,191,190,45,11,58,178,198,129,247,100,14,176,227,123,91,14,116,100,141,131,241,90,14,246,153,59,104,229,95,230,81,31,76,96,45,245,158,169,27,205,43,37,172,242,158,239,45,121,229,216,197,220,78,4,183,195,191,81,70,197,238,59,216,7,95,86,79,11,22,84,8,71,87,118,165,26,157,167,219,106,139,13,207,103,232,219,157,109,109,253,16,98,27,29,215,169,24,115,23,20,209,132,191,246,189,85,105,53,155,74,39,176,122,224,161,54,244,123,167,136,97,158,78,192,46,197,107,161,16,3,41,22,156,168,120,246,139,91,61,19,109,9,61,49,113,248,109,136,129,76,123,12,217,199,77,199,40,185,26,169,228,88,226,226,109,206,76,118,150,85,149,138,10,151,0,134,248,2,145,39,63,76,127,96,232,125,133,65,37,254,211,153,4,236,244,78,125,36,199,172,96,150,237,204,46,99,82,169,190,21,178,200,227,81,121,97,99,9,235,177,74,20,133,47,206,84,186,186,86,50,43,92,159,5,192,98,249,169,123,189,136,8,210,228,93,150,252,215,3,48,48,177,121,27,121,38,230,83,134,240,11,16,80,233,99,72,205,233,127,29,28,31,27,31,251,70,215,64,176,81,238,50,76,46,222,223,243,163,220,131,5,248,156,55,252,98,236,211,255,45,0,246,228,60,100,106,38,142,49,133,75,244,97,87,61,5,108,218,71,74,162,96,78,95,116,24,167,8,146,156,30,170,216,99,200,55,165,30,217,37,27,130,142,139,104,5,139,4,244,145,34,135,168,202,178,255,30,68,127,243,201,198,182,229,33,98,38,187,202,116,138,138,215,58,194,200,22,244,65,170,85,145,138,168,61,86,120,89,68,109,201,196,178,136,44,78,202,186,8,207,217,179,221,149,162,142,243,24,146,188,146,83,252,211,159,109,154,77,179,4,119,53,217,51,249,139,150,93,110,232,239,124,20,225,92,158,186,77,151,230,163,86,208,210,222,205,13,145,143,162,173,37,239,27,250,25,31,69,88,141,60,123,217,70,195,194,198,195,66,231,213,242,92,94,60,47,243,225,212,57,139,102,21,250,168,240,190,213,234,127,1,218,94,66,97,71,78,0,0 };
    +const uint8_t JS_CONTROLS_GZIP[4844] PROGMEM = { 31,139,8,0,34,4,123,101,2,255,213,60,107,119,218,72,178,223,253,43,100,101,78,128,107,130,33,153,100,51,96,57,135,96,146,176,107,27,95,27,111,230,108,38,215,71,160,198,104,45,36,173,36,252,88,134,255,126,171,171,31,234,214,3,176,61,185,59,247,75,12,213,213,213,245,234,238,170,234,34,147,192,143,19,227,114,112,53,56,29,140,6,221,227,171,207,151,3,235,117,179,217,153,136,129,243,254,241,176,123,4,176,150,128,157,29,117,71,253,171,225,167,79,23,253,145,213,82,113,251,191,142,250,167,71,140,70,75,129,143,6,163,254,177,165,0,206,128,98,134,30,130,210,69,6,87,61,10,121,173,35,245,24,214,235,20,235,227,229,104,52,60,181,222,232,120,28,218,106,190,73,49,143,187,31,129,137,159,117,68,6,108,53,127,78,241,46,190,14,70,189,47,253,115,235,173,142,42,225,173,230,91,5,251,120,112,4,176,119,25,92,6,109,53,223,165,152,167,151,39,31,1,246,23,29,147,67,91,205,191,40,234,2,61,130,65,206,46,71,214,123,29,91,25,105,53,223,167,51,62,159,119,207,190,88,191,112,64,247,232,136,65,174,206,134,131,83,138,202,7,122,199,253,238,57,71,110,53,127,81,86,236,126,180,90,25,131,48,152,98,144,139,254,113,191,7,212,50,54,17,224,150,98,149,225,217,104,64,245,159,49,139,0,183,20,179,156,12,0,144,177,10,194,90,138,77,78,186,191,90,173,140,61,16,214,82,77,49,234,159,89,173,172,37,16,216,82,236,240,185,123,249,185,111,181,50,118,224,208,150,98,134,110,175,71,125,35,99,2,14,109,189,87,21,115,214,61,239,142,134,96,198,95,178,186,145,35,45,85,221,131,147,62,236,168,140,190,41,176,245,90,217,37,159,206,187,159,79,250,96,192,215,169,105,228,46,58,26,126,61,149,123,232,184,255,105,36,247,202,249,224,243,151,145,220,17,61,32,0,14,38,148,217,187,26,93,158,255,247,229,112,112,209,151,164,122,87,253,147,254,121,247,56,221,147,189,171,179,62,204,58,31,252,29,166,190,150,192,175,253,81,247,226,236,75,247,88,33,127,117,113,121,250,233,120,248,85,91,163,215,61,63,31,142,228,14,234,93,117,143,7,255,232,158,131,89,223,73,208,81,247,252,111,114,55,244,174,78,135,167,160,147,183,111,59,183,118,100,0,48,137,2,175,27,199,100,62,246,30,186,81,100,63,88,62,185,51,134,227,127,146,73,82,173,33,214,167,200,190,158,19,63,17,104,35,119,78,162,60,218,117,100,135,179,35,59,177,113,8,105,241,145,153,29,119,39,19,226,89,83,219,139,9,130,98,207,117,72,212,131,245,93,127,17,44,98,62,52,93,248,147,196,13,124,224,204,11,162,158,103,199,113,21,63,14,156,218,146,127,176,78,23,243,49,137,36,188,19,223,185,201,100,166,224,217,49,81,13,208,142,72,178,136,124,19,254,249,215,34,112,99,98,118,56,10,183,135,64,32,32,151,237,57,114,56,53,142,192,8,73,66,162,200,189,37,145,68,74,141,37,144,238,72,98,199,225,204,246,18,137,36,141,39,112,226,133,63,245,130,59,133,14,179,165,24,159,216,81,20,164,243,133,93,197,176,237,185,255,182,35,215,151,8,212,202,109,254,153,154,88,32,58,118,116,99,118,28,50,181,23,94,34,128,102,103,181,218,161,86,184,35,227,56,152,220,116,148,207,96,18,31,108,74,28,197,88,95,201,248,2,134,72,194,45,191,240,188,212,82,17,249,215,130,196,201,48,114,193,69,108,10,58,35,209,220,141,99,248,84,173,45,87,59,18,51,182,111,201,103,225,36,48,228,5,19,219,187,72,2,112,47,210,136,73,50,72,200,188,106,146,56,92,184,232,75,177,89,255,235,197,240,180,17,39,32,233,181,59,125,168,74,23,171,213,58,10,225,8,214,15,34,133,182,11,94,128,94,6,43,58,232,146,218,90,215,133,107,165,196,59,238,180,42,167,238,162,188,181,101,74,11,153,10,237,40,38,41,86,173,227,145,196,112,25,130,132,126,115,157,239,29,166,116,182,33,26,110,204,54,6,195,172,125,96,127,219,223,190,131,60,12,17,63,106,162,217,17,108,177,229,79,85,39,152,44,232,62,172,53,108,199,169,154,255,101,214,26,193,116,10,123,236,167,170,249,34,10,238,224,251,44,153,123,85,211,172,209,237,126,1,214,88,196,125,240,163,8,112,56,25,149,118,22,103,89,184,209,27,211,32,234,219,176,191,136,71,232,160,117,184,156,120,196,142,6,62,108,133,91,219,19,112,32,93,235,108,113,84,108,62,115,64,251,73,180,32,150,101,101,125,178,182,44,241,82,14,110,76,188,0,172,194,52,34,197,3,189,68,100,30,220,18,118,158,152,120,80,188,186,142,8,241,205,60,42,232,86,195,139,136,83,128,197,20,141,138,51,246,141,211,192,224,28,81,189,190,124,241,254,221,155,183,157,130,89,169,185,52,168,95,5,149,186,147,155,54,183,118,29,52,185,82,12,53,179,125,199,35,127,119,99,119,236,122,110,242,208,3,192,53,136,185,4,77,237,102,53,242,242,229,174,112,148,198,204,117,28,226,215,150,210,139,52,178,194,179,168,231,210,253,65,129,214,157,235,59,193,93,67,124,111,204,130,56,241,237,57,65,255,14,131,40,201,97,80,96,71,46,9,234,235,223,194,135,99,55,78,136,15,199,180,121,43,249,158,32,223,102,189,88,158,58,154,18,205,79,73,238,90,166,249,251,239,236,211,251,166,248,244,243,207,111,164,19,160,215,200,179,169,106,222,197,237,253,125,115,79,48,182,103,182,205,61,58,107,207,220,191,3,61,119,86,4,232,111,61,153,207,217,1,118,232,1,0,222,168,31,131,181,101,230,88,164,39,152,216,19,66,199,204,70,194,59,35,98,59,15,212,236,212,183,223,232,102,169,191,109,54,155,116,61,129,28,248,65,72,124,75,82,34,183,9,189,2,253,56,240,8,40,255,26,88,102,152,6,197,219,194,145,203,28,62,33,247,32,191,244,31,192,200,109,50,186,29,59,127,146,211,97,213,73,53,132,219,125,27,21,33,98,209,177,248,39,20,138,80,214,182,17,10,101,0,161,82,55,250,211,72,195,162,62,186,203,241,48,200,72,147,68,15,120,61,59,153,219,20,6,27,14,94,166,171,29,216,134,192,50,206,78,197,71,213,112,160,212,88,76,124,184,13,23,110,112,3,251,189,89,227,247,109,135,69,56,196,146,39,211,56,112,30,88,212,75,168,228,112,188,136,200,145,174,217,72,30,66,194,99,71,61,79,111,23,92,175,20,148,216,227,216,183,111,139,192,84,69,176,136,58,4,199,0,46,147,13,124,33,176,200,134,194,133,120,32,15,194,185,246,227,2,171,82,217,32,206,187,103,42,95,82,244,118,38,128,18,166,174,175,58,138,121,170,114,22,250,128,96,53,9,18,219,19,235,29,86,245,229,61,226,95,39,179,87,173,154,60,142,117,67,148,162,131,32,99,56,8,111,58,66,213,105,53,163,253,159,149,144,233,157,110,37,184,225,200,253,222,147,36,222,102,126,94,7,172,250,211,206,94,173,17,241,2,219,129,29,165,99,99,157,167,45,29,59,113,19,143,48,175,241,236,49,241,208,13,231,182,235,127,129,251,6,50,12,238,133,41,66,150,30,86,103,218,226,27,43,149,200,175,105,45,68,130,88,41,66,126,197,156,94,25,228,185,120,91,104,25,3,0,143,212,224,66,26,5,95,70,39,199,85,182,201,117,38,88,45,41,55,105,153,157,69,133,27,39,190,185,135,104,16,233,99,252,148,4,139,201,12,117,223,78,207,154,218,146,52,194,136,80,179,31,177,12,136,170,114,145,36,244,230,128,120,171,202,73,212,233,253,6,70,169,35,21,176,233,83,104,240,232,101,133,193,91,198,188,162,166,181,89,58,118,34,65,216,36,200,50,116,219,67,6,51,100,105,153,78,234,157,126,222,74,121,225,244,201,186,11,109,135,9,125,121,86,127,170,238,138,104,168,186,67,22,189,231,179,72,107,53,207,103,82,163,146,99,51,122,62,155,88,69,122,62,159,58,153,28,163,227,231,51,74,11,97,207,231,83,163,146,99,115,242,124,54,89,29,238,249,140,102,232,172,221,221,88,133,222,188,249,34,154,229,92,224,189,94,221,205,197,1,57,178,163,238,199,60,77,61,240,176,195,16,111,160,3,207,61,60,176,141,192,159,3,37,178,8,173,10,224,48,57,164,70,247,204,90,197,152,69,100,106,85,40,5,5,94,57,228,95,240,152,217,51,15,246,237,195,131,125,32,89,24,209,200,53,29,247,214,112,29,92,74,35,118,176,15,35,116,46,157,103,1,129,134,78,0,190,141,137,211,99,223,171,75,47,8,194,54,53,211,170,134,193,95,213,180,67,151,173,108,3,246,212,245,32,88,83,19,42,94,79,249,169,154,204,220,24,248,73,18,72,50,169,96,102,13,210,42,200,109,168,220,175,146,224,21,59,75,77,184,240,169,51,153,8,55,235,170,3,208,120,2,216,177,194,40,152,135,144,4,141,236,177,145,4,6,155,72,63,65,234,71,107,141,6,100,249,224,147,31,88,28,183,75,229,105,48,36,152,81,133,175,16,19,216,30,137,40,137,153,157,80,154,134,19,144,216,240,131,196,32,247,144,10,27,237,223,126,195,116,178,192,231,10,92,138,85,240,165,249,33,60,134,25,61,22,73,48,182,25,136,170,247,69,12,49,207,36,225,54,208,81,59,236,107,106,180,32,196,212,159,218,141,125,52,247,118,132,237,118,204,138,129,46,96,85,4,148,121,4,29,16,16,182,24,161,216,135,2,134,65,5,0,14,246,25,205,67,51,47,209,201,160,84,28,0,255,84,173,188,136,189,74,145,8,60,110,162,174,95,142,195,156,96,238,250,166,126,97,210,140,223,224,244,193,148,155,23,40,69,42,91,33,39,103,247,215,31,47,167,125,191,70,78,154,207,111,94,161,28,75,174,193,208,127,180,70,115,178,228,142,215,81,255,236,135,171,52,78,72,248,131,37,45,88,34,43,42,62,25,110,190,72,100,165,250,27,223,186,223,173,92,9,92,220,163,144,14,67,50,18,225,192,197,237,117,53,63,183,110,34,44,189,122,245,189,155,121,229,108,227,153,25,99,194,15,100,72,181,70,203,233,180,76,80,45,98,172,17,46,226,89,117,121,223,78,226,250,67,59,21,30,206,188,204,115,192,83,24,85,216,84,222,92,219,5,250,249,246,253,15,94,79,60,92,82,107,137,247,173,26,27,151,207,93,88,54,219,28,22,172,125,64,201,28,164,202,115,58,214,37,212,64,57,205,242,184,127,137,165,129,161,225,157,127,22,5,33,92,81,15,213,10,207,145,47,146,7,143,84,106,44,168,80,9,9,127,133,97,238,176,234,140,98,150,100,138,179,38,131,129,219,185,105,126,104,182,91,143,99,45,126,54,111,44,64,43,161,133,172,105,27,115,135,5,103,87,244,205,160,154,155,197,54,119,53,253,160,76,173,155,173,102,211,84,42,217,255,119,66,242,180,157,210,130,131,72,33,70,75,124,79,245,10,157,210,83,216,82,202,7,24,75,194,181,243,7,241,150,33,181,153,185,50,226,174,31,46,146,209,67,184,158,50,173,15,114,194,114,66,137,187,177,242,72,46,52,123,174,192,57,98,79,177,7,47,179,228,171,40,89,206,242,24,248,80,240,84,230,117,82,79,225,60,45,118,164,77,74,237,60,26,171,70,209,37,175,237,197,53,249,131,116,159,165,245,20,1,216,125,81,176,69,6,39,125,188,86,163,91,245,90,77,130,193,197,240,2,11,155,213,108,181,59,129,251,182,109,238,69,183,248,200,85,114,63,137,190,150,54,125,186,19,133,253,99,226,243,82,33,70,46,29,49,134,204,15,167,211,152,36,108,60,192,207,56,126,10,134,23,243,57,74,102,202,158,66,30,167,140,104,101,213,74,139,172,8,236,98,235,132,99,85,21,236,189,12,165,90,71,229,246,147,235,3,25,70,204,178,248,124,204,193,10,45,199,107,173,96,180,157,204,155,129,169,234,227,132,94,174,254,181,104,127,49,34,50,9,34,167,110,196,55,110,24,42,3,166,208,232,106,135,50,197,161,150,90,214,237,92,36,65,88,248,104,162,85,127,209,58,192,118,19,164,200,10,140,172,230,94,84,190,165,51,191,227,138,157,77,88,220,98,86,222,90,192,164,29,37,197,92,170,12,74,195,157,179,144,196,202,212,214,151,21,215,169,180,211,25,245,10,91,178,210,206,175,185,202,63,208,76,57,2,123,168,1,207,133,164,82,93,142,250,114,170,113,208,150,185,128,8,109,234,250,196,49,65,111,244,0,14,166,198,38,53,228,77,47,204,61,117,35,72,196,5,23,198,52,144,13,80,148,19,85,17,63,92,95,205,63,66,61,25,71,218,181,172,45,93,36,175,162,175,81,0,10,242,193,138,82,63,13,163,127,31,98,170,175,104,103,19,229,61,211,248,28,36,116,66,110,91,255,112,157,110,100,145,157,120,219,138,242,108,11,109,92,71,124,102,69,22,75,251,250,156,221,158,246,207,104,199,40,88,125,139,247,179,109,185,94,243,192,182,241,56,195,6,178,213,14,77,176,119,150,255,159,206,38,113,171,139,126,186,236,29,227,223,248,193,157,111,208,147,138,150,12,177,206,167,239,89,249,212,124,104,137,135,188,151,47,37,240,64,107,250,174,45,195,40,152,144,56,238,251,54,100,142,78,85,188,141,103,232,168,115,52,98,218,51,54,43,27,138,183,84,26,211,184,142,18,58,148,5,67,161,237,19,79,11,133,212,105,5,113,80,58,97,93,204,205,179,97,74,147,163,124,147,48,56,194,115,235,196,179,224,14,162,32,116,153,220,224,12,178,181,106,86,49,150,165,101,127,181,37,23,93,239,5,99,153,222,43,217,26,202,27,83,95,241,86,80,241,53,237,251,20,144,180,201,83,64,100,75,167,0,176,30,78,241,77,182,108,82,41,136,232,149,210,217,160,231,172,236,123,229,241,3,124,175,137,222,165,66,17,82,222,5,211,10,183,42,155,146,63,206,216,58,142,74,249,216,41,241,73,90,231,199,7,142,87,60,121,190,194,111,102,173,65,232,27,190,82,191,231,133,251,111,205,239,188,42,160,87,242,89,58,78,243,15,6,165,151,82,149,23,55,10,49,89,1,93,105,160,153,3,123,112,249,88,202,241,164,182,61,174,57,112,6,78,141,30,72,101,17,29,109,54,46,28,249,54,128,83,173,176,255,235,10,73,234,177,204,238,250,88,6,166,124,103,115,232,57,89,118,171,115,172,71,29,139,121,10,141,173,47,82,196,126,230,205,184,90,173,234,173,102,179,89,31,56,53,221,34,107,52,94,174,189,82,83,176,57,235,134,245,6,168,114,76,202,178,210,48,137,158,205,186,24,249,203,16,59,85,129,136,37,138,56,28,142,217,102,86,81,177,135,62,11,58,130,191,152,186,113,236,206,163,183,143,94,188,202,238,41,254,168,36,57,103,203,172,225,28,11,61,235,88,247,203,56,87,86,161,5,130,53,107,176,178,202,186,69,146,109,22,17,47,155,133,75,208,183,200,181,43,216,227,45,214,96,149,150,117,134,230,165,152,181,198,222,98,33,181,145,132,13,215,221,216,129,24,2,175,69,254,81,39,59,166,48,133,26,62,83,100,80,22,97,241,114,242,117,155,238,160,122,126,65,113,179,178,17,8,230,121,127,155,29,243,187,198,113,99,60,246,225,212,93,202,62,59,222,69,167,52,208,177,199,243,118,153,8,225,100,179,12,225,68,19,66,171,154,148,19,158,110,65,120,90,70,152,246,38,148,147,222,66,239,225,184,140,52,109,35,41,39,237,109,65,218,43,35,141,157,31,229,180,163,45,104,71,5,180,181,115,79,148,244,185,199,196,180,133,25,29,38,102,205,204,236,23,18,180,44,147,61,5,83,215,1,2,147,27,230,57,153,125,98,195,42,183,68,63,12,53,34,74,39,179,32,162,55,115,11,74,144,230,108,162,165,255,18,32,37,39,159,251,184,72,173,180,44,191,142,141,44,14,68,71,97,58,46,218,79,50,180,155,121,218,37,108,109,32,47,186,82,88,175,171,210,95,146,54,220,186,241,145,27,79,96,175,242,118,7,68,178,74,175,27,229,199,89,147,177,165,92,59,218,221,167,223,65,112,98,80,1,66,207,158,144,234,254,255,252,118,180,183,127,93,55,49,48,99,61,47,216,203,131,69,243,118,193,69,166,6,120,20,194,111,176,213,138,119,204,148,222,128,37,19,59,120,144,169,12,78,108,207,27,219,147,155,11,2,217,216,174,101,82,171,152,204,95,85,245,136,73,41,183,66,17,43,225,111,42,10,211,133,134,179,83,190,110,157,175,218,89,173,68,131,180,124,8,76,245,140,209,244,50,77,161,172,141,57,217,7,211,192,236,139,246,108,100,242,175,61,218,182,209,54,205,14,130,238,128,205,98,114,116,132,18,162,127,17,191,180,190,170,189,107,87,106,191,255,46,239,220,242,183,241,195,166,214,176,178,13,221,15,235,200,166,237,216,172,203,28,172,191,190,149,91,239,110,229,239,31,185,206,204,210,158,202,76,151,215,211,187,100,241,105,186,184,103,150,189,12,48,81,100,95,149,146,226,162,37,247,84,203,26,19,122,84,88,149,228,46,160,191,149,92,204,253,88,96,80,51,82,4,59,114,140,132,245,186,211,238,157,226,140,14,27,182,102,111,69,7,24,235,228,49,15,246,1,116,48,139,246,105,139,15,207,13,211,23,107,236,244,193,30,175,204,131,67,218,250,251,20,81,98,246,243,41,36,41,100,162,173,105,176,218,26,6,139,57,193,39,21,81,118,209,123,160,40,107,98,59,103,26,169,36,155,107,155,168,114,250,144,7,176,50,146,221,210,116,24,52,193,149,160,98,175,217,231,250,67,84,110,167,171,195,114,175,227,66,226,125,210,218,244,222,9,52,177,86,34,72,202,33,73,111,211,190,226,63,41,61,136,193,164,104,107,184,173,132,149,53,6,119,164,161,209,134,6,254,251,234,46,178,195,124,255,33,37,118,104,102,91,195,197,82,44,104,198,197,240,85,177,108,57,222,14,73,3,32,192,84,34,109,54,165,110,224,237,76,123,221,76,181,117,178,8,147,93,180,149,67,189,47,14,56,101,200,10,175,242,64,17,220,50,105,41,179,241,102,213,240,206,67,241,99,2,209,53,209,50,63,200,75,31,140,2,59,176,164,170,6,127,92,184,117,208,176,244,203,43,17,186,25,124,158,201,119,20,221,153,124,77,215,231,48,52,62,247,7,92,109,28,220,87,24,231,130,241,192,239,81,189,8,70,233,207,251,152,134,48,2,196,46,193,13,156,155,98,203,30,236,163,102,20,213,229,142,94,161,66,200,66,4,179,226,133,239,240,96,225,49,174,181,214,87,102,107,181,197,220,208,141,77,57,52,21,99,23,162,114,107,163,232,180,91,158,245,181,190,124,241,203,187,183,205,78,218,29,187,105,117,214,147,189,45,3,25,108,141,135,232,201,60,96,255,250,182,44,232,200,26,7,222,147,57,192,142,239,109,57,208,145,53,14,198,107,57,216,103,238,160,149,127,153,71,125,48,129,181,212,123,166,110,52,175,148,176,202,123,190,183,228,149,99,23,115,59,17,220,14,255,70,25,21,187,239,96,31,124,89,61,45,88,80,33,28,93,217,149,106,116,158,110,171,45,54,60,159,161,111,119,182,181,245,67,136,109,116,92,167,98,204,93,80,68,19,254,218,247,86,165,213,108,42,157,192,234,129,135,218,208,239,157,34,134,121,58,1,187,20,175,133,66,12,164,88,112,162,226,217,47,110,245,76,180,37,244,196,196,225,183,33,6,50,237,49,100,31,55,29,163,228,106,164,146,99,137,139,183,57,51,217,89,86,85,42,42,92,2,24,226,11,68,158,252,48,253,129,161,247,21,6,149,248,79,103,18,176,211,59,245,145,28,179,130,89,182,51,187,140,73,165,250,86,200,34,143,71,229,133,141,37,172,199,42,81,20,190,56,83,233,234,90,201,172,112,125,22,0,139,229,167,238,245,34,34,72,147,119,89,242,95,15,192,192,196,230,109,228,153,152,79,25,194,47,64,64,165,143,33,53,167,255,117,112,124,108,124,236,27,93,3,193,70,185,203,48,185,120,127,207,143,114,15,22,224,115,222,240,139,177,79,255,219,0,216,147,243,144,169,153,56,198,20,46,209,135,93,245,20,176,105,31,41,137,130,57,125,209,97,156,34,72,114,122,168,98,143,33,223,148,122,100,151,108,8,58,46,162,21,44,18,208,71,138,28,162,42,203,254,159,16,253,205,39,27,219,150,135,136,153,236,42,211,41,42,94,235,8,35,91,208,7,169,86,69,42,162,246,88,225,101,17,181,37,19,203,34,178,56,41,235,34,60,103,207,118,87,138,58,206,99,72,242,74,78,241,79,127,182,105,54,205,18,220,213,100,207,228,47,90,118,185,161,191,243,81,132,115,121,234,54,93,154,143,90,65,75,123,55,55,68,62,138,182,150,188,111,232,103,124,20,97,53,242,236,101,27,13,11,27,15,11,157,87,203,115,121,241,188,204,135,83,231,44,154,85,232,163,194,251,86,171,255,5,143,65,176,228,80,78,0,0 };