Source: galerie.js

/*
Copyright (C) 2021 Velometrik GmbH
<http://www.velometrik.de/>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* 
    Created on : 16.04.2021, 22:02:29
    Author     : Peter Bauer
*/

const host = location.origin;
const ws = host.replace("http", "ws");
const app = "satteldruckanalyse";

var sessionID;
if(getFromLocalStorage('session')){
    if(getFromLocalStorage('session').split(" ")[0]=='restart'){
        sessionID = getFromLocalStorage('session').split(" ")[1]
    } 
} else {
    sessionID = getFromLocalStorage('new_session')
}

if(getFromLocalStorage('sessionID')){
    sessionID = getFromLocalStorage('sessionID')
}
try {
  var sattelanalyse = new WebSocket(`${ws}/apps/${app}`, ["soap", "wamp"]);
} catch (error) {
  getError(error)
}
var onsqlresult = null;
//var load_num;
var galerie_image_info = {};
//var galerie_info= {}
var recID;
var recData = {};
//var img1;
//var img2;
var chk1;
var chk1;
//var ch, cw;
//var chart_a;
//var chart_b;
var DelImg;


let sda_frame3 = `${host}/sattelbild?image=blank`;

_name();
_satteldruckanalyse();

/**
 * It gets the name from local storage and puts it in the right places
 */
function _name() {
  let name = getFromLocalStorage("client_name").split(" ");
  let infos = document.getElementById('galerie_info');
  infos.innerHTML = `${name[1]} ${name[0]} - ${getFromLocalStorage('session_note')||""}`;

}

/**
 * It opens a websocket connection to the server, and sends a few commands to it
 */
function _satteldruckanalyse() {
  sattelanalyse.onopen = (e) => {
    rec_cancel(1);
    rec_cancel(2);
    onsqlresult = RowImg;
    sattelanalyse.send(
      `sql select * from recordings where session_id=${sessionID} and analysis='2'`
    );
    sattelanalyse.send(`session restart ${sessionID}`);
    sattelanalyse.send("set compare on");
    sattelanalyse.send(`analysis ["sitbones","anamnesis","x1"]`);

    PrintLog([
      "_satteldruckanalyse",
      `sql select * from recordings where session_id=${sessionID} and analysis='2'`,
    ]);
    PrintLog(["_satteldruckanalyse", `session restart ${sessionID}`]);
    PrintLog(["_satteldruckanalyse", `set compare on`]);
    PrintLog(["_satteldruckanalyse", `analysis ["sitbones","anamnesis","x1"]`]);
  };
}

function setCompareMode(param){
  sattelanalyse.send(`set compare ${param}`)
}

/**
 * The function `rec_cancel` sends a message and logs a recording cancellation with a given number.
 * @param {Number}num - The parameter "num" is a number that represents the recording number that needs to be
 * cancelled.
 */
function rec_cancel(num) {
  sattelanalyse.send(`recording cancel ${num}`);
  PrintLog([`recording cancel ${num}`]);
}

/**
 * It takes a parameter, and logs it to the console
 * @param params - {
 */
function getLog(params) {
  console.log(params);
}

sattelanalyse.onmessage = (e) => {
  let data = JSON.parse(e.data);
  if (log) console.log("sattelanalyse.onmessage", data);
  // console.log(data);

  if (data.wsevent === "result3") {
    // console.log(data)
    galerie_image_info = data;
  }
  if (data.wsevent === "sqlresult") {
    // console.log(data)
    try {
      onsqlresult(data.rows);
    } catch (error) {
      getError(error)
    }
  }
  if (data.wsevent === "sda_int3") {
    // console.log('sda_int3');
    let img = document.getElementsByClassName("imgGal1")[fi - 1];
    // let a = document.getElementsByClassName('imgGal2')[fi-1];
    sda_frame3 = `${host}/sattelbild?image=sda_int3&rnd=${new Date().getTime()}`;
    img.src = sda_frame3;
    img.setAttribute("onclick", `OpenChart(${recID[fi - 1]});hide()`);
    img.id = recID[fi - 1];
    recData[recID[fi - 1]] = JSON.stringify(galerie_image_info);
    // a.setAttribute('onclick',`sattelanalyse.send('recording retrieve ${recID[fi-1]} ${load_num}')`)
    if (galerie_image_info.pelvisrotation)
      pel = `${galerie_image_info.pelvisrotation.width || ""}:${
        galerie_image_info.pelvisrotation.height || ""
      }`;
    else pel = "-";
    document.getElementsByClassName("info_img")[fi - 1].innerHTML = `
     <ul class="uk-list uk-list-collapse">
     <li key="pro_satteldruck_veloscore">Veloscore</li>
     <li key="pro_satteldruck_becken">Rotation</li>
     <li key="pro_satteldruck_leftright">Lins/Rechts</li>
     <li key="pro_satteldruck_frontback">Vorn/Hinten</li>
     </ul>
     <ul class="uk-list uk-list-collapse">
     <li id="veloscore_${recID[fi - 1]}">${galerie_image_info.veloscore}</li>
     <li id="becken_${recID[fi - 1]}" >${pel}</li>
     <li id="leftright_${recID[fi - 1]}">${galerie_image_info.left_right}</li>
     <li id="frontback_${recID[fi - 1]}">${galerie_image_info.front_rear}</li>
     </ul>
     <textarea id="info_${recID[fi - 1]}" readonly class="uk-textarea" style="width:180px;height: 60px;margin-left:40px ">${galerie_image_info.notes}</textarea>`;
    document.getElementsByClassName("name_img")[fi - 1].innerHTML = `
     <h2 id="label_${recID[fi-1]}" class="uk-text-center">${
       galerie_image_info.product_label || "(no Typ)"
     }</h2>
     <p class="uk-text-center"><small id="marke_${recID[fi-1]}">${
       galerie_image_info.product ||
       "(no " + aLangKeys[lang]["pro_satteldruck_marke"] + ")"
     }</small></p>`;
    if (recID[fi]) {
      console.log("sda_init3 send");
      sattelanalyse.send(`recording retrieve ${recID[fi]}`);
      fi++;
    }
    translatejs()
  }
  if (data.wsevent === "appquestions") {
    console.log(data.appquestions);
  }
};


/**
 * The function `open_img` opens a modal window to display an image.
 * @param params - The `params` parameter is used to specify the ID of the image that you want to open
 * in the modal.
 */
function open_img(params) {
  UIkit.modal($(`#modal-center-load${params}`)).show();
}

/**
 * The load function sends a request to retrieve a recording with a specific ID and parameters, and
 * logs the request if the log variable is true.
 * @param params - The `params` parameter is a string that contains additional information or
 * instructions for the `load` function. It is used as part of the message sent to the `sattelanalyse`
 * object.
 * @param id - The `id` parameter is used to specify the identifier of the recording that needs to be
 * retrieved.
 */
function load(params, id) {
  sattelanalyse.send(`recording retrieve ${id} ${params}`);
  if (log) {
    console.log("load", `recording retrieve ${id} ${params}`);
  }
}

/**
 * The function `openDelDialog` opens a dialog box with a warning message and options to delete an
 * image or cancel the operation.
 * @param params - The `params` parameter is an object that contains the information about the image to
 * be deleted. It is passed as an argument to the `openDelDialog` function.
 */
function openDelDialog(params) {
  DelImg = params;
  OpenModDialog({
    type: "warn",
    title: ["del_img_title"],
    msg: ["del_img"],
    master_btn: ["button_delete", "del_img()"],
    slave_btn: ["button_cancel"],
  });
}

/**
 * The function `del_img()` sends a SQL query to delete a record from the "recordings" table, logs the
 * query if a variable `log` is true, and then reloads the current page.
 */
function del_img() {
  sattelanalyse.send(`sql DELETE FROM recordings WHERE recording_id=${DelImg}`);
  if (log) {
    console.log(
      "del img",
      `sql DELETE FROM recordings WHERE recording_id=${DelImg}`
    );
  }
  location.reload();
}

/**
 * The function `result_1` updates the content of specific HTML elements with values from the `params`
 * object.
 * @param params - The `params` object contains the following properties:
 */
function result_1(params) {
  if (log) console.log("result_1", params);
  document.getElementById("S1").innerHTML = params.product;
  document.getElementById("T1").innerHTML = params.product_label;
  document.getElementById("v1").innerHTML = params.front_rear;
  document.getElementById("l1").innerHTML = params.left_right;
  document.getElementById("V1").innerHTML = params.veloscore;
  if (params.pelvisrotation)
    document.getElementById("B1").innerHTML =
      `${params.pelvisrotation.center.x || ""}x${
        params.pelvisrotation.center.y || ""
      }` || "";
  document.getElementById("N1").innerHTML = params.notes;
}

/**
 * The function "result_2" updates the HTML elements with the values from the "params" object.
 * @param params - The `params` object contains the following properties:
 */
function result_2(params) {
  if (log) console.log("result_2", params);
  document.getElementById("S2").innerHTML = params.product;
  document.getElementById("T2").innerHTML = params.product_label;
  document.getElementById("v2").innerHTML = params.front_rear;
  document.getElementById("l2").innerHTML = params.left_right;
  document.getElementById("V2").innerHTML = params.veloscore;
  if (params.pelvisrotation)
    document.getElementById("B2").innerHTML =
      `${params.pelvisrotation.center.x || ""}x${
        params.pelvisrotation.center.y || ""
      }` || "";
  document.getElementById("N2").innerHTML = params.notes;
}


/**
 * The function `RowImg` is used to dynamically create and display rows of images on a webpage.
 * @param params - The `params` parameter is an array of objects. Each object in the array represents a
 * row of data and contains the following properties:
 */
function RowImg(params) {
  fi = 0;
  recID = [];
  onsqlresult = null;
  var append1 = document.getElementById("img_list2");
  append1.innerHTML = "";
  //var ap = (document.getElementById("imagelist").innerHTML = "");
  params.forEach((element) => {
    if (fi === 0) {
      console.log("RowImg send");
      sattelanalyse.send(`recording retrieve ${element.recording_id} 3`);
      fi++;
    }
    recID.push(element.recording_id);

    let master = document.createElement("div");
    //master.classList.add('hover');
    //master.id = `img_${element.recording_id}`
    //master.setAttribute('onclick','selectImg(this)')
    append1.append(master);

    let div = document.createElement("div");
    div.classList.add("flex-column-center");
    div.setAttribute(
      "style",
      "border:1px solid green;padding:5px; width:200px;margin:0 10px 0 0;"
    );
    master.append(div);

    let del = document.createElement("div");
    del.classList.add("adba","del_img", "mdi", "mdi-trash-can-outline");
    del.setAttribute("onclick", `openDelDialog(${element.recording_id})`);
    master.append(del);

    let date = document.createElement("p");
    date.classList.add("uk-text-center");
    date.innerHTML = element.finished;
    master.append(date);

    let div_name = document.createElement("div");
    div_name.classList.add(
      "name_img"
    );
    div_name.id = `img_${element.recording_id}`;
    //div_name.setAttribute("onclick", "selectImg(this)");
    div.append(div_name);
    // let a = document.createElement('a')
    // a.href = '#modal_dialog'
    // a.classList.add('imgGal2')

    let img = document.createElement("img");
    img.width = 150;
    img.height = 100;
    img.classList.add("imgGal1","cur");
    div.append(img);

    let div2 = document.createElement("div");
    div2.setAttribute("style", "width: 200px");
    div.append(div2);

    let div_info = document.createElement("div");
    div_info.classList.add("uk-grid", "uk-child-width-1-2", "info_img");
    div_info.setAttribute("style", "margin: 0 -30px;");
    div2.append(div_info);
    // append1.append(a)
  });

}

var max=0;

var SetMax=false;
var newMax=0

/**
 * The function "setMax" sets a variable "newMax" to the value of the parameter passed in.
 * @param params - The `params` parameter is a value that will be assigned to the `newMax` variable.
 */
function setMax(params) {
  SetMax = true
  newMax = params
}

  var dom = document.getElementById('chart-container');
  var myChartX = echarts.init(dom, 'dark', {
    renderer: 'canvas',
    useDirtyRect: false
  });

var open_chartID;

/**
 * The function `OpenChart` opens a chart modal and sends a SQL query to retrieve pressure values for a
 * specific recording ID.
 * @param id - The `id` parameter is the identifier of the chart that you want to open. It is used to
 * retrieve the pressure values from the database for that specific chart.
 */
function OpenChart(id) {
    console.log(`%c loaded id = ${id}`,'background: #222;color:#5cbc40;padding:1em');
    open_chartID = id
    onsqlresult = heatchart
    sattelanalyse.send(`sql select pressure_values from recordings where recording_id = ${id}`)
    UIkit.modal('#chart_modal').show();
}

/**
 * The function `PDFgenGal` generates a PDF document containing a gallery of images.
 */
function PDFgenGal(){
    let name = getFromLocalStorage('client_name').split(' ')

    var content = [
        {text: `${aLangKeys[lang]['pro_tab_galerie']} - ${name[1]} ${name[0]}`, style: 'header'},
        '\n',
        {canvas: [ { type: 'line', x1: 0, y1: 0, x2: 515, y2: 0, lineWidth: 1 } ]},
        '\n']

    content = [];

  let text = script_setting.UserEinleitung && script_setting.UserEinleitung !== "" ? script_setting.UserEinleitung : aLangKeys[lang]['pro_einleitung']

//DECKBLATT
  content.push({text:`${aLangKeys[lang]['pro_tab_galerie']}`,style:['header','bold','center']})
  //content.push({text:`${aLangKeys[lang]['pro_head']}`,style:['header','bold','center']})
  content.push('\n')
  content.push({text:`${getFromLocalStorage('client_forenames')} ${getFromLocalStorage('client_surename')}`, style: ['XXL','bold','center']})
  if(getFromLocalStorage('session_note') !== ''){
    content.push({text:`${getFromLocalStorage('session_note')}`, style: ['bigger','bold','center']})   
  }
  content.push({text:`${new Date().toISOString().split('T')[0]}`,style:['small','center']})
  content.push('\n')
    //content.push({text:`${text}`})
    content.push('\n')
  if(script_setting.UserCompany){
    content.push({text:`${script_setting.UserCompany}`,style:['center','bigger','bold']})
  }
  if(script_setting.UserStreet || script_setting.UserCity){
    content.push('\n')
  }
  if(script_setting.UserStreet){
    content.push({text:`${script_setting.UserStreet}`,style:'center'})
  }
  if(script_setting.UserCity){
    content.push({text:`${script_setting.UserCity}`,style:'center'})
  }
  if(script_setting.UserMail || script_setting.UserWeb){
    content.push('\n')
  }
  if(script_setting.UserMail){
    content.push({text:`${script_setting.UserMail}`,style:'center'})
  }
  if(script_setting.UserWeb){
    content.push({text:`${script_setting.UserWeb}`,style:'center'})
    content.push('\n')
    content.push({ qr: `${script_setting.UserWeb}`,fit:50,style:'center' })
  }
  content.push({text:"",pageBreak: 'after'})

    let contentObj = {}
    let columns = []
    let row = 0;
    let row2= 0;
    let tmp = {}
    for (const i of document.getElementsByClassName('imgGal1')) {
        // let canvasGal = new fabric.Canvas("canvas_3");
        // createCanvas(canvasGal)
        let image = i
        let toDataURL = () => {
            let canvas = document.createElement('canvas');
            console.log(i);
            // We use naturalWidth and naturalHeight to get the real image size vs the size at which the image is shown on the page
            canvas.width = image.naturalWidth;
            canvas.height = image.naturalHeight;
    
            // We get the 2d drawing context and draw the image in the top left
            canvas.getContext('2d').drawImage(image, 0, 0);
    
            // Convert canvas to DataURL and log to console
            let dataURL = canvas.toDataURL();
            // console.log(dataURL);
            // logs data:image/png;base64,wL2dvYWwgbW9yZ...
            let x = new Object();
            x.image = dataURL
            x.width = 100

            //content.push({ qr: `${script_setting.UserWeb}`,fit:50,style:'center' })
            let y = new Object();
            y.text =  `${document.getElementById(`label_${i.id}`).innerHTML}\n`
            y.text += `${document.getElementById(`marke_${i.id}`).innerHTML}\n`
            y.text += '\n'
            y.text += `${aLangKeys[lang]['pro_satteldruck_veloscore']}: ${document.getElementById(`veloscore_${i.id}`).innerHTML}\n`
            y.text += `${aLangKeys[lang]['pro_satteldruck_becken']}: ${document.getElementById(`becken_${i.id}`).innerHTML}\n`
            y.text += `${aLangKeys[lang]['pro_satteldruck_leftright']}: ${document.getElementById(`leftright_${i.id}`).innerHTML}\n`
            y.text += `${aLangKeys[lang]['pro_satteldruck_frontback']}: ${document.getElementById(`frontback_${i.id}`).innerHTML}\n`
            y.text += `${aLangKeys[lang]['pro_satteldruck_note']}:\n ${document.getElementById(`info_${i.id}`).value}\n`
            y.style = "XXS"
            //y.fit =150

            if(row == 3){
              row2++
              console.log(row,y);
              y.pageBreak = 'before'
              if(row2==2){
                row = 0
                row2= 0
              }
            }

            columns.push(x)
            columns.push(y)

            //console.log(columns.length);
            if(columns.length%4==0){
                //tmp.alignment = "justify"
                row++
                tmp.columns = columns
                content.push(tmp)
                content.push(`\n`)
                tmp={}
                columns=[]

            }

        };
        // If the image has already loaded, let's go!
        if (image.complete) toDataURL(image);
        // Wait for the image to load before converting
        else image.onload = toDataURL;

    }
    contentObj.alignment = "justify"
    contentObj.columns = columns
    console.log("A",content);
    content.push(contentObj)
    console.log("B",content);

    // console.log(content);
   var dd = {
      // a string or { width: number, height: number }
      pageSize: 'LETTER',
      // by default we use portrait, you can change it to landscape if you wish
      pageOrientation: 'portrait',
      // [left, top, right, bottom] or [horizontal, vertical] or just a number for equal margins
      pageMargins: [ 40, 90, 40, 50 ],
      // watermark: { text: 'Velometrik Gmbh', fontSize: 20 },
      styles: {
          header: {
              fontSize: 18
          },
          center:{
              alignment: 'center'
          },
          left:{
              alignment: 'left'
          },
          right:{
              alignment: 'right'
          },
          XXL:{
              fontSize:48
          },
          bold:{
              bold: true
          },
          bigger: {
              fontSize: 15,
              italics: true
          },
          small:{
              fontSize:10
          },
          XXS:{
              fontSize:7
          }
      },
      defaultStyle: {
          columnGap: 20
      },
      info: {
          title: `${aLangKeys[lang]['pro_head']} - ${name[1]} ${name[0]}.pdf`,
          filename:`${aLangKeys[lang]['pro_head']} - ${name[1]} ${name[0]}.pdf`,
      },

      images: {
          Velologo: {
            url: `${location.origin}/production/images/Logo-mit-Schriftzug.png`,
          }
        },

      //background: function(currentPage, pageSize) {
      //    return `page ${currentPage} with size ${pageSize.width} x ${pageSize.height}`
      //  },

      header(currentPage, pageCount, pageSize) {
        // computations...
        let company = "";
        let street = "";
        let city = "";
        let phone= "";
        let mail="";
        let web="";
        let name2="";

        if(script_setting.UserCompany){
            company = script_setting.UserCompany
        }
        if(script_setting.UserStreet){
            street = script_setting.UserStreet
        }
        if(script_setting.UserCity){
            city = script_setting.UserCity
        }
        if(script_setting.UserPhone){
            phone = script_setting.UserPhone
        }
        if(script_setting.UserMail){
            mail = script_setting.UserMail
        }
        if(script_setting.UserWeb){
            web = script_setting.UserWeb
        }
        if(script_setting.UserName){
            name2 = script_setting.UserName
        }

        if(currentPage === 1){
            return
        }
        return [
            { text:"\n"},
            { text: `${company}`, style:['right','bigger'], margin:[40,0]/* extra style attributes */},
            { text:`${street} | ${city} | ${phone}`,style:['right','XXS'],margin:[40,0]},
            { text:`${mail} | ${web}`,style:['right','XXS'],margin:[40,0]},
          //  { text:"",style:['right'],margin:[40,0]},
            { text:`Bike Fitter: ${name2}`,style:['right','XXS'],margin:[40,0]},
            { text:`${getFromLocalStorage('client_forenames')} ${getFromLocalStorage('client_surename')}`,style:['left','bigger','bold'],margin:[40,0]},
            { text:`${aLangKeys[lang]['pro_bikefit']} ${aLangKeys[lang]['pro_head']} ${new Date().toISOString().split('T')[0]}`,style:['left','XXS'],margin:[40,0]}
            
          //  {canvas: [ { type: 'line', x1: 40, y1: 0, x2: 515, y2: 0, lineWidth: 1 } ]}
          //  { text:`${new Date().toISOString().split('T')[0]}`,style:['small','left'],margin:[40,0]}
          ]
          //content.push({text:`${aLangKeys[lang]['pro_bikefit']}`,style:['header','bold','center']})
          //content.push({text:`${aLangKeys[lang]['pro_head']}`,style:['header','bold','center']})
      },

      background(currentPage, pageSize) {
          return [
              {image: 'Velologo',style:['left'],width:150,margin:[40,pageSize.height - 60]},
          ]
      },

      footer(currentPage, pageCount, pageSize) {
          return [
              {text: `Velometrik GmbH`,style: ['bigger','bold','right'],margin:[40,0]},
              {text:`Breunsdorfer Str. 48a | 04575 Neukieritzsch | Germany | info@velometrik.de | www.velometrik.com`,style:['XXS','right'],margin:[40,0]},
              {text: `\n${currentPage}/${pageCount}`,style:['XXS','center'],margin:[40,0]}
          ]    
      },

      //watermark: { text: 'unlicensed', color: 'blue', opacity: 0.3, bold: true, italics: false },

      content: content
      
  }
  pdfMake.createPdf(dd).download(`${aLangKeys[lang]['pro_tab_galerie']} - ${name[1]} ${name[0]}.pdf`);
  //pdfMake.createPdf(dd).open();
        
}
var numRows = 28;
var numCols = 16;
// Create an empty 2D array with the specified dimensions
var data2D = new Array(numRows);
var Cdata;
var  tmp;

/**
 * The `heatchart` function generates a 3D bar chart using the provided data and displays it on a
 * webpage.
 * @param data - The `data` parameter is an array of objects. Each object represents a data point and
 * has the following properties:
 */
function heatchart (data){
    let saddle = JSON.parse(recData[open_chartID])
    data.forEach(e=> {
      tmp = e.pressure_values.split(' ')
    })

      for (var i = 0; i < numRows; i++) {
        data2D[i] = new Array(numCols);
      }
      // Fill the 2D array with your data
      for (var i = 0; i < tmp.length; i++) {
        var row = Math.floor(i / numCols);
        var col = i % numCols;
          if(Number(tmp[i]) > max){
            max = tmp[i]
          }
          data2D[row][col] = [col, row, tmp[i]];
      }
      //console.log(data2D.flat());
    var option;
    var ColorRange = ['#00000000','#0000ff','#00ff00','#ffff00','#ff0000']

    
    $.getScript(
      '/production/js/chart/simplex-noise.js'
    ).done(function () {
      //max = 100;
      //Cdata = generateData(dd);
      myChartX.setOption(
        (option = {
            backgroundColor: '#ffffffff',
          visualMap: {
            show: false, //true
            calculable: true,
            min: 0,
            max: max,
            inRange: {
                color: ColorRange,
            },
          },
          xAxis3D: {
            type: 'category',
            //data: Array.from(Array(numCols).keys()),
          },
          yAxis3D: {
            type: 'category',
            //data: Array.from(Array(numRows).keys()),
          },
          zAxis3D: {
            type: 'value',
            max: max*2,
            min: 0
          },
          toolbox: { 
            show: true, 
            orient: 'vertical', 
            itemsize: 16,
            iconStyle: {
                //color: '#000'
                borderColor: '#999',
                borderWidth: 1 ,
            },
            left:10,
            feature: {
                //magicType: {
                //    type: ["line3D", "bar3D","scatter3D","surface"]
                //}, 
                //dataZoom: { show: true }, 
                //dataView: { show: true },
                saveAsImage: { 
                    show: true, 
                    name: `${saddle.product||'NO_PRODUCT'}-${saddle.product_label||'NO_TYPE'}`, 
                    type: 'png',
                    pixelRatio:2 
                }
            } 
          },
          grid3D: {
                boxWidth: 16*10,
                boxDepth: 28*10,
            axisLine: {
              lineStyle: { color: '#99999900' }
            },
            axisPointer: {
              lineStyle: { color: '#99999900' }
            },
            viewControl: {
                distance:300,
                alpha:35,
                beta:220 //270
            },
            //light: {
            //  main: {
            //    shadow: true,
            //    intensity: 1
            //  }
            //}
            light: {
                main: {
                  intensity: 1.2,
                  shadow: true,
                },
                ambient: {
                  intensity: 0.3,
                },
              },
          },
          series: [
            {
              type: 'bar3D',//line3D, bar3D,scatter3D,surface
              data: data2D.flat(),
              shading: 'lambert', //color,lambert,realistic
              //symbolSize(value) {
              //  console.log(value);
              //  // Customize the size of the data points based on the values
              //  return Math.abs(value[2]) + 10; // Use the absolute value of the Z coordinate
              //},
            //  animation:false,
              label: {
                fontSize: 16,
                borderWidth: 1,
                show:false
              },
              emphasis: {
                label: {
                  fontSize: 20,
                  color: '#00000000',
                  show: true,
                },
                itemStyle: {
                    color: '#000000'
                }
              }
            }
          ]
        })
      );
    });
    
    if (option && typeof option === 'object') {
      myChartX.setOption(option);
    }
    
    window.addEventListener('resize', myChartX.resize);
}

/**
 * The function `setChartType` sets the type of chart to be displayed in a charting library and updates
 * the chart with the new type.
 * @param params - The `params` parameter is the type of chart that you want to set. It can be one of
 * the following values:
 */
function setChartType(params) {

    myChartX.setOption((option = {
        series: [
            {
                type: params,
                data:data2D.flat(),
                symbolSize:15,
                shading: 'lambert', //color,lambert,realistic
                //symbolSize(value) {
                //  Customize the size of the data points based on the values
                //  console.log(value[2]);
                //  return Math.abs(value[2]) + 2; // Use the absolute value of the Z coordinate
                //},
              //  animation:false,
                label: {
                  fontSize: 16,
                  borderWidth: 1,
                  show:false
                },
                emphasis: {
                  label: {
                    fontSize: 20,
                    color: '#00000000',
                    show: true,
                  }
                }
            }
          ]
    }))
    
}

/**
 * `ClientInfo` is a function that takes a single parameter, `params`, and stores it in local storage
 * @param params - {
 */
function ClientInfo(params) {
    onsqlresult = getLog;
    saveToLocalStorage('client_info',JSON.stringify(params));
  }
  /**
   * It takes three arguments, sends a query to the database, and then creates a table with the results
   * of the query
   * @param {number}client_id - The client's ID
   * @param {string}name - The name of the client
   * @param {string}mail - The email address of the user.
   */
  function info(client_id,name,fname,lname,mail,fc) {
    onsqlresult = ClientInfo
    sattelanalyse.send(`sql select * from sessions where client_id=${client_id}`);
    let inter = setInterval(()=> {
        saveToLocalStorage('client_fc',fc)
        saveToLocalStorage('client_name',name)
        saveToLocalStorage('client_mail',mail)
        saveToLocalStorage('client_id',client_id)
        saveToLocalStorage('client_forenames',fname)
        saveToLocalStorage('client_surename',lname)
        location.href = "/production/client.tcls"
        clearInterval(inter);
      }, 500);
  
  }

  function setView(x,y) {
    myChartX.setOption((option = {
        grid3D: {
          boxWidth: 16*10,
          boxDepth: 28*10,
        axisLine: {
          lineStyle: { color: '#99999900' }
        },
        axisPointer: {
          lineStyle: { color: '#99999900' }
        },
        viewControl: {
            distance:300,
            alpha:x,
            beta:y
        },
        //light: {
        //  main: {
        //    shadow: true,
        //    intensity: 1
        //  }
        //}
        light: {
            main: {
              intensity: 1.2,
              shadow: true,
            },
            ambient: {
              intensity: 0.3,
            },
          },
      }
    }))
}