/* MIT-Licence: Copyright (c)2016 oliver.reimann@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*! This is the utils library for LESIM: lesim.de This library provide utils for lib_sym1.js */ "use strict"; if (jsPlumb === undefined) var jsPlumb = window.jsPlumb; if (LeSim === undefined) var LeSim = window.LeSim; /* Error handling * https://stackoverflow.com/questions/5328154/catch-all-javascript-errors-and-send-them-to-server */ window.onerror = function(message, source, lineno, colno, error) { let msg = navigator.userAgent + '\n' + error.stack; // ga('send', 'event', 'window.onerror', message, navigator.userAgent); let loc = window.location.pathname; console.log(loc); $.post("/cgi-bin/saveMsg.php", { "date": new Date().toJSON(),//.slice(0, 10).replace(/-/g, '/'), "loc": loc, "msg": msg, }).done(function(data) { console.log("Data Loaded: " + data); }).fail(function(data) { console.log("error"); console.log(data); }); return false; }; /*! \brief abstrakte definition eines Simulationsbausteines */ var SimBlockUtil = { abc:function() { return {a:0,b:0,c:0}; }, ab:function() { return {a:0,b:0}; }, limitVal: function ( x, lowerLimit, upperLimit , callerString ) { let xt = x * 1.0; let opt = LeSim.KPA_opt; let t = opt.t1; if ( t === undefined ) t = opt.t0; let Blocks = LeSim.Blocks; if (isNaN(xt)) { try { xt = eval(x); } catch (e) { let ss = ""; if ( callerString !== undefined) ss += callerString; throw new Error( "couldnt perform eval(" + x + "): " + ss ); } } if (isNaN(xt)) { throw new Error( "eval(" + x + ") is NAN" ); } if ( xt === undefined ) { xt = 0; } if (xt < lowerLimit) xt = lowerLimit; if (xt > upperLimit) xt = upperLimit; return xt; }, /*! \brief ueberprueft einen Flot Datensatz und loescht zu alte Daten */ checkOutputDat: function(o) { if (o.data[0] === undefined) return; if (o.data[0][0] > o.tmin) return; let nmax = o.data.length-1; // startindex auf die Hälfte legen let nStart = Math.round(nmax /2); // doublecheck if (nStart <= 0 || nStart > nmax) { nStart = 0; return; } // let nDiff = nStart/2; for (let k = 0; k < 20; k++) { let tx = o.data[nStart][0]; if (tx > o.tmin) { nStart -= nDiff; } else { nStart += nDiff; } nStart = Math.round(nStart); nDiff = nDiff / 2; if (nDiff <= 2) { //console.log( "checkOutputDat: nDiff <= 2 , k = " + k + " , nStart = " + nStart ); break; } if (nStart < 0) { nStart = nmax; console.warn("checkOutputDat: nStart < 0 for channel " + o.label); break; } if (nStart > nmax) { nStart = nmax; console.warn("checkOutputDat: nStart > nmax for channel " + o.label); break; } } if (nStart>0) { //console.log("loesche Daten fuer " + o.label + " nStart=" + nStart ); } o.data.splice(0, nStart); }, /*! \brief erzeugt eine neue FLOT Variable, bzw weisst dieser einen neuen Eintrang zu */ push: function(obj, name, dat) { if (! $.isNumeric(dat[0] * dat[1])) { console.error(obj); throw new Error("the value for this output Block is not valid: " + name + " with values: " + JSON.stringify(dat)); } // fullname of the variable var fnam = "out_" + name; // falls die Variable noch nicht existiert, erzeugen! if (obj[fnam] === undefined) obj[fnam] = {}; if (obj[fnam].data === undefined) obj[fnam].data = []; if (obj[fnam].label === undefined) obj[fnam].label = obj.id + "_" + name; // zuweisen des Wertepaars obj[fnam].data.push(dat); }, /*! helper for optional arguments: http://stackoverflow.com/questions/894860/set-a-default-parameter-value-for-a-javascript-function*/ pick: function(arg, def) { return(typeof arg === 'undefined' ? def: arg); }, /*! \brief erzeugt einen Standartconnector und hängt ihn an die Connectoren an * SimBlockUtil.makeStdEndpoint(this.Connectors, htmlobj, [0.25, 0, 0, -1]); * \position [x, y, dx, dy] (von oben links gerechnet) https://jsplumbtoolkit.com/community/doc/anchors.html */ makeStdEndpoint: function(connectors, htmlobj, position) { let number = connectors.length; // quasi durchzaehlen let Connector = jsPlumb.addEndpoint(htmlobj, { isSource: true, isTarget: true, maxConnections: 5, parameters: { "portnr": number }, anchor: position }); Connector.anchor_orig = jQuery.extend(true, {}, Connector.anchor); connectors.push(Connector); }, /*! \brief erzeugt einen Standartconnector-Output und hängt ihn an die Connectoren an */ makeStdOutEndpoint: function(connectors, htmlobj, position) { var number = connectors.length; // quasi durchzaehlen var Connector = jsPlumb.addEndpoint(htmlobj, { isSource: true, isTarget: false, maxConnections: 5, parameters: { "portnr": number }, anchor: position }); Connector.anchor_orig = jQuery.extend(true, {}, Connector.anchor); connectors.push(Connector); }, /*! \brief erzeugt einen Standartconnector-Input und hängt ihn an die Connectoren an */ makeStdInEndpoint: function(connectors, htmlobj, position) { var number = connectors.length; // quasi durchzaehlen var Connector = jsPlumb.addEndpoint(htmlobj, { isSource: false, isTarget: true, maxConnections: 1, parameters: { "portnr": number }, anchor: position }); Connector.anchor_orig = jQuery.extend(true, {}, Connector.anchor); connectors.push(Connector); }, /*! \brief erzeugt einen versteckten Endpoint und haengr ihn an die Connectoren an*/ makeHiddenEndpoint: function(connectors, htmlobj) { var number = connectors.length; // quasi durchzaehlen var Connector = jsPlumb.addEndpoint(htmlobj, { isSource: false, isTarget: false, maxConnections: 0, parameters: { "portnr": number }, anchor: "Center", cssClass: 'hidden-endpoint' }); Connector.anchor_orig = jQuery.extend(true, {}, Connector.anchor); connectors.push(Connector); }, /*! \brief helper fuer zweipole */ getStdEndpoint_Zweipol: function(htmlobj) { let Connectors = []; SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, "TopCenter"); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, "BottomCenter"); return Connectors; }, /*! \brief erzeugt einen versteckten Endpoint*/ getHiddenEndpoint: function(myobj, nmb) { var Connector = jsPlumb.addEndpoint(myobj, { isSource: false, isTarget: false, maxConnections: 0, parameters: { "portnr": nmb }, anchor: "Center", cssClass: 'hidden-endpoint' }); Connector.anchor_orig = jQuery.extend(true, {}, Connector.anchor); return Connector; }, /*! \brief helper fuer Drehstromobjekte ohne Null: also 3 Konnektoren! */ getStdEndpoint_3AC: function(htmlobj) { let Connectors = []; SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.25, 1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.5, 1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.75, 1, 0]); return Connectors; }, /*! \brief helper fuer Drehstromobjekte mit Null: also 4 Konnektoren! */ getStdEndpoint_3ACNull: function(htmlobj) { let Connectors = []; SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0, 0.75, -1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.25, 1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.5, 1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [1, 0.75, 1, 0]); return Connectors; }, /*! \brief helper fuer Drehstromobjekte mit plus und minus: also 5 Konnektoren! */ getStdEndpoint_B6x: function(htmlobj) { let Connectors = []; SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, "TopCenter"); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0, 0.25, -1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0, 0.5, -1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0, 0.75, -1, 0]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, "BottomCenter"); return Connectors; }, /*! \brief helper fuer Drehstromobjekte mit 3x oben und 3x unten! */ getStdEndpoint_3AC_6pol: function(htmlobj) { let Connectors = []; SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.25, 0, 0, -1]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.5, 0, 0, -1]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.75, 0, 0, -1]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.25, 1, 0, 1]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.5, 1, 0, 1]); SimBlockUtil.makeStdEndpoint( Connectors, htmlobj, [0.75, 1, 0, 1]); return Connectors; }, flipXConnectors: function(Connectors) { for (let k = 0; k < Connectors.length; k++) { let c = Connectors[k]; //console.log(c); // die Werte sind auf oben links bezogen und muessen auf mitte gerechnet werden let x = c.anchor_orig.x - 0.5; let y = c.anchor_orig.y - 0.5; let x2 = -x; let y2 = y; c.anchor.x = x2 + 0.5; c.anchor.y = y2 + 0.5; let dx = c.anchor_orig.orientation[0]; let dy = c.anchor_orig.orientation[1]; let dx2 = -dx; let dy2 = dy; c.anchor.orientation[0] = Math.round(dx2); c.anchor.orientation[1] = Math.round(dy2); } }, rotateConnectors: function(Connectors, angleDeg) { for (let k = 0; k < Connectors.length; k++) { let c = Connectors[k]; //console.log(c); let x = c.anchor_orig.x - 0.5; let y = c.anchor_orig.y - 0.5; let cosphi = Math.cos(angleDeg / 180 * Math.PI); let sinphi = Math.sin(angleDeg / 180 * Math.PI); let x2 = cosphi * x - sinphi * y; let y2 = sinphi * x + cosphi * y; c.anchor.x = x2 + 0.5; c.anchor.y = y2 + 0.5; let dx = c.anchor_orig.orientation[0]; let dy = c.anchor_orig.orientation[1]; let dx2 = cosphi * dx - sinphi * dy; let dy2 = sinphi * dx + cosphi * dy; c.anchor.orientation[0] = Math.round(dx2); c.anchor.orientation[1] = Math.round(dy2); } }, /*! \brief ueberprueft, ob eine id schon vergeben wurde, und aendert gegebenenfalls*/ checkId: function(elm) { console.log("checkId for '" + elm.id + "'"); while (1) { let nam_changed = false; let idname1 = elm.id; for (let key in LeSim.Blocks) { let idname2 = LeSim.Blocks[key].id; //console.log("checkId: "+ idname1 +"=="+ idname2 + "?"); if (idname1 === idname2) { // doppelter Name gefunden elm.id = idname1 + "_1"; console.warn("Der Name / DIV\"" + idname1 + "\" existiert, neue ID ist \"" + elm.id + "\""); nam_changed = true; } } if (!nam_changed) break; } }, htmlbase: '' + '