diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml index 14d78ab..afa3e09 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/Setting/ExpressionEditor.qml @@ -538,7 +538,7 @@ Item { try { expr = new JS.MathLib.Expression(value.toString()) // Check if the expression is valid, throws error otherwise. - if(!expr.allRequirementsFullfilled()) { + if(!expr.allRequirementsFulfilled()) { let undefVars = expr.undefinedVariables() if(undefVars.length > 1) throw new Error(qsTranslate('error', 'No object found with names %1.').arg(undefVars.join(', '))) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/color.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/color.mjs index 51541b0..1d395ed 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/color.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/color.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -21,36 +21,41 @@ import Objects from "../module/objects.mjs" export default class ColorChanged extends EditedProperty { // Action used everytime when an object's color is changed - type(){return 'ColorChanged'} - - icon(){return 'appearance'} - - + type() { + return "ColorChanged" + } + + icon() { + return "appearance" + } + constructor(targetName = "", targetType = "Point", oldColor = "black", newColor = "white") { super(targetName, targetType, "color", oldColor, newColor) } - + export() { return [this.targetName, this.targetType, this.previousValue, this.newValue] } - - color(darkVer=false){return darkVer ? 'purple' : 'plum'} - + + color(darkVer = false) { + return darkVer ? "purple" : "plum" + } + getReadableString() { return qsTranslate("color", "%1 %2's color changed from %3 to %4.") - .arg(Objects.types[this.targetType].displayType()).arg(this.targetName) - .arg(this.previousValue).arg(this.newValue) + .arg(Objects.types[this.targetType].displayType()).arg(this.targetName) + .arg(this.previousValue).arg(this.newValue) } - + formatColor(color) { return `██` } - + getHTMLString() { return qsTranslate("color", "%1 %2's color changed from %3 to %4.") - .arg(Objects.types[this.targetType].displayType()) - .arg(' ' + this.targetName + " ") - .arg(this.formatColor(this.previousValue)).arg(this.formatColor(this.newValue)) + .arg(Objects.types[this.targetType].displayType()) + .arg(" " + this.targetName + " ") + .arg(this.formatColor(this.previousValue)).arg(this.formatColor(this.newValue)) } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/common.mjs index 9e59376..33f9118 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/common.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/common.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -22,66 +22,72 @@ import Latex from "../module/latex.mjs" export class Action { /** * Type of the action. - * + * * @returns {string} */ - type(){return 'Unknown'} - + type() { + return "Unknown" + } + /** * Icon associated with the action. - * + * * @returns {string} */ - icon(){return 'position'} - + icon() { + return "position" + } + // TargetName is the name of the object that's targeted by the event. constructor(targetName = "", targetType = "Point") { this.targetName = targetName this.targetType = targetType } - + /** * Undoes the action. */ - undo() {} - + undo() { + } + /** * Redoes the action. */ - redo() {} - + redo() { + } + /** * Export the action to a serializable format. * NOTE: These arguments will be reinputed in the constructor in this order. - * + * * @returns {string[]} */ export() { return [this.targetName, this.targetType] } - + /** - * Returns a string with the human readable description of the action. - * + * Returns a string with the human-readable description of the action. + * * @returns {string} */ getReadableString() { - return 'Unknown action' + return "Unknown action" } - + /** * Returns a string containing an HTML tag describing the icon of a type - * + * * @param {string} type - Name of the icon to put in rich text. * @returns {string} */ getIconRichText(type) { - return `` + return `` } - + /** * Renders a LaTeX-formatted string to an image and wraps it in an HTML tag in a string. - * + * * @param {string} latexString - Source string of the latex. * @returns {Promise} */ @@ -94,12 +100,12 @@ export class Action { imgDepth * (History.fontSize + 2), History.themeTextColor ) - return `` + return `` } - + /** * Returns a string with the HTML-formatted description of the action. - * + * * @returns {string|Promise} */ getHTMLString() { diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/create.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/create.mjs index 9f0fa52..1308d9e 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/create.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/create.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -19,43 +19,51 @@ import Objects from "../module/objects.mjs" import { Action } from "./common.mjs" +/** + * Action used for the creation of an object. + */ export default class CreateNewObject extends Action { - // Action used for the creation of an object - type(){return 'CreateNewObject'} - - icon(){return 'create'} - - color(darkVer=false){return darkVer ? 'green' : 'lime'} - + type() { + return "CreateNewObject" + } + + icon() { + return "create" + } + + color(darkVer = false) { + return darkVer ? "green" : "lime" + } + constructor(targetName = "", targetType = "Point", properties = []) { super(targetName, targetType) this.targetProperties = properties } - + undo() { Objects.deleteObject(this.targetName) } - + redo() { Objects.createNewRegisteredObject(this.targetType, this.targetProperties) Objects.currentObjectsByName[this.targetName].update() } - + export() { return [this.targetName, this.targetType, this.targetProperties] } - + getReadableString() { return qsTranslate("create", "New %1 %2 created.") .arg(Objects.types[this.targetType].displayType()) .arg(this.targetName) } - + getHTMLString() { return qsTranslate("create", "New %1 %2 created.") - .arg(Objects.types[this.targetType].displayType()) - .arg('' + this.targetName + "") + .arg(Objects.types[this.targetType].displayType()) + .arg("" + this.targetName + "") } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/delete.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/delete.mjs index 984b5c2..f9674c5 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/delete.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/delete.mjs @@ -20,10 +20,10 @@ import Objects from "../module/objects.mjs" import CreateNewObject from "./create.mjs" +/** + * Action used at the deletion of an object. Basically the same thing as creating a new object, except Redo & Undo are reversed. + */ export default class DeleteObject extends CreateNewObject { - /** - * Action used at the deletion of an object. Basically the same thing as creating a new object, except Redo & Undo are reversed. - */ type(){return 'DeleteObject'} icon(){return 'delete'} diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/editproperty.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/editproperty.mjs index 93cc680..886f100 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/editproperty.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/editproperty.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -22,14 +22,20 @@ import * as MathLib from "../math/index.mjs" import { Action } from "./common.mjs" import { DrawableObject } from "../objs/common.mjs" +/** + * Action used everytime an object's property has been changed. + */ export default class EditedProperty extends Action { - // Action used everytime an object's property has been changed - type(){return 'EditedProperty'} - - icon(){return 'modify'} - - color(darkVer=false){ - return darkVer ? 'darkslateblue' : 'cyan'; + type() { + return "EditedProperty" + } + + icon() { + return "modify" + } + + color(darkVer = false) { + return darkVer ? "darkslateblue" : "cyan" } /** @@ -49,12 +55,12 @@ export default class EditedProperty extends Action { this.newValue = newValue this.propertyType = Objects.types[targetType].properties()[targetProperty] if(valueIsExpressionNeedingImport) { - if(typeof this.propertyType == 'object' && this.propertyType.type === "Expression") { - this.previousValue = new MathLib.Expression(this.previousValue); - this.newValue = new MathLib.Expression(this.newValue); + if(typeof this.propertyType == "object" && this.propertyType.type === "Expression") { + this.previousValue = new MathLib.Expression(this.previousValue) + this.newValue = new MathLib.Expression(this.newValue) } else if(this.propertyType === "Domain") { - this.previousValue = MathLib.parseDomain(this.previousValue); - this.newValue = MathLib.parseDomain(this.newValue); + this.previousValue = MathLib.parseDomain(this.previousValue) + this.newValue = MathLib.parseDomain(this.newValue) } else { // Objects this.previousValue = Objects.currentObjectsByName[this.previousValue] // Objects.getObjectByName(this.previousValue); @@ -63,17 +69,17 @@ export default class EditedProperty extends Action { } this.setReadableValues() } - + undo() { Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.previousValue Objects.currentObjectsByName[this.targetName].update() } - + redo() { Objects.currentObjectsByName[this.targetName][this.targetProperty] = this.newValue Objects.currentObjectsByName[this.targetName].update() } - + export() { if(this.previousValue instanceof MathLib.Expression) { return [this.targetName, this.targetType, this.targetProperty, this.previousValue.toEditableString(), this.newValue.toEditableString(), true] @@ -83,7 +89,7 @@ export default class EditedProperty extends Action { return [this.targetName, this.targetType, this.targetProperty, this.previousValue, this.newValue, false] } } - + setReadableValues() { this.prevString = "" this.nextString = "" @@ -93,45 +99,45 @@ export default class EditedProperty extends Action { case "Enum": this.prevString = this.propertyType.translatedValues[this.propertyType.values.indexOf(this.previousValue)] this.nextString = this.propertyType.translatedValues[this.propertyType.values.indexOf(this.newValue)] - break; + break case "ObjectType": this.prevString = this.previousValue == null ? "null" : this.previousValue.name this.nextString = this.newValue == null ? "null" : this.newValue.name - break; + break case "List": this.prevString = this.previousValue.join(",") this.nextString = this.newValue.name.join(",") - break; + break case "Dict": this.prevString = JSON.stringify(this.previousValue) this.nextString = JSON.stringify(this.newValue) - break; + break case "Expression": this.prevString = this.previousValue == null ? "null" : this.previousValue.toString() this.nextString = this.newValue == null ? "null" : this.newValue.toString() - break; + break } } else { this.prevString = this.previousValue == null ? "null" : this.previousValue.toString() this.nextString = this.newValue == null ? "null" : this.newValue.toString() } // HTML - this.prevHTML = ' '+this.prevString+' ' - this.nextHTML = ' '+this.nextString+' ' - if(Latex.enabled && typeof this.propertyType == 'object' && this.propertyType.type === "Expression") { + this.prevHTML = " " + this.prevString + " " + this.nextHTML = " " + this.nextString + " " + if(Latex.enabled && typeof this.propertyType == "object" && this.propertyType.type === "Expression") { // Store promises so that querying can wait for them to finish. this._renderPromises = [ this.renderLatexAsHtml(this.previousValue.latexMarkup).then(prev => this.prevHTML = prev), - this.renderLatexAsHtml(this.newValue.latexMarkup).then(next => this.nextHTML = prev) + this.renderLatexAsHtml(this.newValue.latexMarkup).then(next => this.nextHTML = next) ] } } - + getReadableString() { - return qsTranslate("editproperty", '%1 of %2 %3 changed from "%4" to "%5".') - .arg(this.targetPropertyReadable) - .arg(Objects.types[this.targetType].displayType()) - .arg(this.targetName).arg(this.prevString).arg(this.nextString) + return qsTranslate("editproperty", "%1 of %2 %3 changed from \"%4\" to \"%5\".") + .arg(this.targetPropertyReadable) + .arg(Objects.types[this.targetType].displayType()) + .arg(this.targetName).arg(this.prevString).arg(this.nextString) } /** @@ -139,9 +145,9 @@ export default class EditedProperty extends Action { * @return {Promise|string} */ async getHTMLString() { - const translation = qsTranslate("editproperty", '%1 of %2 changed from %3 to %4.') - .arg(this.targetPropertyReadable) - .arg(' ' + this.targetName + ' ') + const translation = qsTranslate("editproperty", "%1 of %2 changed from %3 to %4.") + .arg(this.targetPropertyReadable) + .arg(" " + this.targetName + " ") // Check if we need to wait for LaTeX HTML to be rendered. if(this.prevHTML === undefined || this.nextHTML === undefined) { const [prevHTML, nextHTML] = await Promise.all(this._renderPromises) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/name.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/name.mjs index b2ce9f1..5c5b397 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/name.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/name.mjs @@ -19,9 +19,10 @@ import EditedProperty from "./editproperty.mjs" import Objects from "../module/objects.mjs" - +/** + * Action used everytime an object's name has been changed. + */ export default class NameChanged extends EditedProperty { - // Action used everytime an object's property has been changed type(){return 'NameChanged'} icon(){return 'name'} diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/position.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/position.mjs index b84c18b..4c1af60 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/position.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/position.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -21,43 +21,48 @@ import Latex from "../module/latex.mjs" import * as MathLib from "../math/index.mjs" import { escapeHTML } from "../utils.mjs" import { Action } from "./common.mjs" -import { DrawableObject } from "../objs/common.mjs" +/** + * Action used for objects that have a X and Y expression properties (points, texts...) + */ export default class EditedPosition extends Action { - // Action used for objects that have a X and Y expression properties (points, texts...) - type(){return 'EditedPosition'} - - icon(){return 'position'} - - color(darkVer=false){ - return darkVer ? 'seagreen' : 'lightseagreen'; + type() { + return "EditedPosition" } - + + icon() { + return "position" + } + + color(darkVer = false) { + return darkVer ? "seagreen" : "lightseagreen" + } + constructor(targetName = "", targetType = "Point", previousXValue = "", newXValue = "", previousYValue = "", newYValue = "") { - super(targetName, targetType) + super(targetName, targetType) let imports = { - 'previousXValue': previousXValue, - 'previousYValue': previousYValue, - 'newXValue': newXValue, - 'newYValue': newYValue + "previousXValue": previousXValue, + "previousYValue": previousYValue, + "newXValue": newXValue, + "newYValue": newYValue } for(let name in imports) - this[name] = (typeof imports[name]) == 'string' ? new MathLib.Expression(imports[name]) : imports[name] + this[name] = (typeof imports[name]) == "string" ? new MathLib.Expression(imports[name]) : imports[name] this.setReadableValues() } - + undo() { Objects.currentObjectsByName[this.targetName].x = this.previousXValue Objects.currentObjectsByName[this.targetName].y = this.previousYValue Objects.currentObjectsByName[this.targetName].update() } - + redo() { Objects.currentObjectsByName[this.targetName].x = this.newXValue Objects.currentObjectsByName[this.targetName].y = this.newYValue Objects.currentObjectsByName[this.targetName].update() } - + setReadableValues() { this.prevString = `(${this.previousXValue.toString()},${this.previousYValue.toString()})` this.nextString = `(${this.newXValue.toString()},${this.newYValue.toString()})` @@ -71,27 +76,27 @@ export default class EditedPosition extends Action { this.renderLatexAsHtml(nextMarkup) ] } else { - this.prevHTML = ' '+escapeHTML(this.prevString)+' ' - this.nextHTML = ' '+escapeHTML(this.nextString)+' ' + this.prevHTML = " " + escapeHTML(this.prevString) + " " + this.nextHTML = " " + escapeHTML(this.nextString) + " " } - + } - + export() { return [this.targetName, this.targetType, - this.previousXValue.toEditableString(), this.newXValue.toEditableString(), - this.previousYValue.toEditableString(), this.newYValue.toEditableString()] + this.previousXValue.toEditableString(), this.newXValue.toEditableString(), + this.previousYValue.toEditableString(), this.newYValue.toEditableString()] } - + getReadableString() { - return qsTranslate("position", 'Position of %1 %2 set from "%3" to "%4".') - .arg(Objects.types[this.targetType].displayType()) - .arg(this.targetName).arg(this.prevString).arg(this.nextString) + return qsTranslate("position", "Position of %1 %2 set from \"%3\" to \"%4\".") + .arg(Objects.types[this.targetType].displayType()) + .arg(this.targetName).arg(this.prevString).arg(this.nextString) } - + async getHTMLString() { - const translation = qsTranslate("position", 'Position of %1 set from %2 to %3.') - .arg(' ' + this.targetName + ' ') + const translation = qsTranslate("position", "Position of %1 set from %2 to %3.") + .arg(" " + this.targetName + " ") // Check if we need to wait for LaTeX HTML to be rendered. if(this.prevHTML === undefined || this.nextHTML === undefined) { const [prevHTML, nextHTML] = await Promise.all(this._renderPromises) @@ -99,6 +104,6 @@ export default class EditedPosition extends Action { this.nextHTML = this.nextHTML ?? nextHTML } return translation.arg(this.prevHTML).arg(this.nextHTML) - + } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/visibility.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/visibility.mjs index c66ade0..e911c1b 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/visibility.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/history/visibility.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -20,36 +20,42 @@ import EditedProperty from "./editproperty.mjs" import Objects from "../module/objects.mjs" +/** + * Action used when an object's shown or hidden. + */ export default class EditedVisibility extends EditedProperty { - // Action used when an object's shown or hidden. - type(){return 'EditedVisibility'} - - icon(){return 'visibility'} - - color(darkVer=false){ - return this.newValue ? - (darkVer ? 'darkgray' : 'whitesmoke') : - (darkVer ? 'dimgray' : 'lightgray') + type() { + return "EditedVisibility" } - + + icon() { + return "visibility" + } + + color(darkVer = false) { + return this.newValue ? + (darkVer ? "darkgray" : "whitesmoke") : + (darkVer ? "dimgray" : "lightgray") + } + constructor(targetName = "", targetType = "Point", newValue = true) { super(targetName, targetType, "visible", !newValue, newValue) } - + export() { return [this.targetName, this.targetType, this.newValue] } - + getReadableString() { - return (this.newValue ? qsTranslate('visibility', '%1 %2 shown.') : qsTranslate('visibility', '%1 %2 hidden.')) + return (this.newValue ? qsTranslate("visibility", "%1 %2 shown.") : qsTranslate("visibility", "%1 %2 hidden.")) .arg(Objects.types[this.targetType].displayType()) .arg(this.targetName) } - + getHTMLString() { - return (this.newValue ? qsTranslate('visibility', '%1 %2 shown.') : qsTranslate('visibility', '%1 %2 hidden.')) + return (this.newValue ? qsTranslate("visibility", "%1 %2 shown.") : qsTranslate("visibility", "%1 %2 hidden.")) .arg(Objects.types[this.targetType].displayType()) - .arg('' + this.targetName + "") + .arg("" + this.targetName + "") } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/domain.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/domain.mjs index a9cefb5..846b66b 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/domain.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/domain.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -23,35 +23,44 @@ import { Expression, executeExpression } from "./expression.mjs" * It doesn't represent any kind of domain and is meant to be extended. */ export class Domain { - constructor() {} - + constructor() { + } + /** * Checks whether x is included in the domain. * @param {number} x - The x value. * @return {boolean} true if included, false otherwise. */ - includes(x) { return false } - + includes(x) { + return false + } + /** * Returns a string representation of the domain. * @return {string} String representation of the domain. */ - toString() { return '???' } - + toString() { + return "???" + } + /** * Returns a new domain that is the union between this domain and another. * @param {Domain} domain - Domain to unionise with this. * @return {Domain} newly created domain. */ - union(domain) { return domain } - + union(domain) { + return domain + } + /** * Returns a new domain that is the intersection between this domain and another. * @param {Domain} domain - Domain to get the interscection with this. * @return {Domain} newly created domain. */ - intersection(domain) { return this } - + intersection(domain) { + return this + } + /** * Imports a domain from a string. * @return {Domain} Found domain, string otherwise. @@ -61,24 +70,20 @@ export class Domain { case "R": case "ℝ": return Domain.R - break; case "RE": case "R*": case "ℝ*": return Domain.RE - break; case "RP": case "R+": case "ℝ⁺": case "ℝ+": return Domain.RP - break; case "RM": case "R-": case "ℝ⁻": case "ℝ-": return Domain.RM - break; case "RPE": case "REP": case "R+*": @@ -88,7 +93,6 @@ export class Domain { case "ℝ*+": case "ℝ+*": return Domain.RPE - break; case "RME": case "REM": case "R-*": @@ -98,7 +102,6 @@ export class Domain { case "ℝ-*": case "ℝ*-": return Domain.RME - break; case "ℕ": case "N": case "ZP": @@ -106,12 +109,10 @@ export class Domain { case "ℤ⁺": case "ℤ+": return Domain.N - break; case "NLOG": case "ℕˡᵒᵍ": case "ℕLOG": return Domain.NLog - break; case "NE": case "NP": case "N*": @@ -128,17 +129,14 @@ export class Domain { case "ℤ+*": case "ℤ*+": return Domain.NE - break; case "Z": case "ℤ": return Domain.Z - break; case "ZM": case "Z-": case "ℤ⁻": case "ℤ-": return Domain.ZM - break; case "ZME": case "ZEM": case "Z-*": @@ -148,15 +146,12 @@ export class Domain { case "ℤ-*": case "ℤ*-": return Domain.ZME - break; case "ZE": case "Z*": case "ℤ*": return Domain.ZE - break; default: return Domain.EmptySet - break; } } } @@ -170,16 +165,26 @@ export class EmptySet extends Domain { this.displayName = "∅" this.latexMarkup = "\\emptyset" } - - includes(x) { return false } - - toString() { return this.displayName } - - union(domain) { return domain } - - intersection(domain) { return this } - - static import(frm) { return new EmptySet() } + + includes(x) { + return false + } + + toString() { + return this.displayName + } + + union(domain) { + return domain + } + + intersection(domain) { + return this + } + + static import(frm) { + return new EmptySet() + } } Domain.EmptySet = new EmptySet() // To prevent use prior to declaration. @@ -190,27 +195,27 @@ Domain.EmptySet = new EmptySet() // To prevent use prior to declaration. export class Range extends Domain { constructor(begin, end, openBegin, openEnd) { super() - if(typeof begin == 'number' || typeof begin == 'string') begin = new Expression(begin.toString()) + if(typeof begin == "number" || typeof begin == "string") begin = new Expression(begin.toString()) this.begin = begin - if(typeof end == 'number' || typeof end == 'string') end = new Expression(end.toString()) + if(typeof end == "number" || typeof end == "string") end = new Expression(end.toString()) this.end = end this.openBegin = openBegin this.openEnd = openEnd this.displayName = (openBegin ? "]" : "[") + begin.toString() + ";" + end.toString() + (openEnd ? "[" : "]") this.latexMarkup = `\\mathopen${openBegin ? "]" : "["}${this.begin.latexMarkup};${this.end.latexMarkup}\\mathclose${openEnd ? "[" : "]"}` } - + includes(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) return ((this.openBegin && x > this.begin.execute()) || (!this.openBegin && x >= this.begin.execute())) && ((this.openEnd && x < this.end.execute()) || (!this.openEnd && x <= this.end.execute())) } - + toString() { return this.displayName } - + union(domain) { if(domain instanceof EmptySet) return this if(domain instanceof DomainSet) return domain.union(this) @@ -219,7 +224,7 @@ export class Range extends Domain { if(domain instanceof MinusDomain) return new UnionDomain(this, domain) if(domain instanceof Range) return new UnionDomain(this, domain) } - + intersection(domain) { if(domain instanceof EmptySet) return domain if(domain instanceof DomainSet) return domain.intersection(this) @@ -228,11 +233,11 @@ export class Range extends Domain { if(domain instanceof MinusDomain) return new IntersectionDomain(this, domain) if(domain instanceof Range) return new IntersectionDomain(this, domain) } - + static import(frm) { let openBegin = frm.trim().charAt(0) === "]" - let openEnd = frm.trim().charAt(frm.length -1) === "[" - let [begin, end] = frm.substr(1, frm.length-2).split(";") + let openEnd = frm.trim().charAt(frm.length - 1) === "[" + let [begin, end] = frm.substring(1, frm.length - 1).split(";") return new Range(begin.trim(), end.trim(), openBegin, openEnd) } } @@ -250,7 +255,7 @@ export class SpecialDomain extends Domain { * @param {boolean} moveSupported - Only true if next and previous functions are valid. */ constructor(displayName, isValid, next = () => true, previous = () => true, - moveSupported = true) { + moveSupported = true) { super() this.displayName = displayName this.isValid = isValid @@ -258,29 +263,29 @@ export class SpecialDomain extends Domain { this.prevValue = previous this.moveSupported = moveSupported } - + includes(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) return this.isValid(x) } - + next(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) return this.nextValue(x) } - + previous(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) return this.prevValue(x) } - + toString() { return this.displayName } - + union(domain) { if(domain instanceof EmptySet) return this if(domain instanceof DomainSet) return domain.union(this) @@ -289,7 +294,7 @@ export class SpecialDomain extends Domain { if(domain instanceof MinusDomain) return new UnionDomain(this, domain) if(domain instanceof Range) return new UnionDomain(this, domain) } - + intersection(domain) { if(domain instanceof EmptySet) return domain if(domain instanceof DomainSet) return domain.intersection(this) @@ -305,7 +310,7 @@ export class SpecialDomain extends Domain { */ export class DomainSet extends SpecialDomain { constructor(values) { - super('', x => true, x => x, true) + super("", () => true, x => x, true) let newVals = {} this.executedValues = [] for(let value of values) { @@ -314,54 +319,54 @@ export class DomainSet extends SpecialDomain { newVals[ex] = expr this.executedValues.push(ex) } - this.executedValues.sort((a,b) => a-b) + this.executedValues.sort((a, b) => a - b) this.values = this.executedValues.map(val => newVals[val]) this.displayName = "{" + this.values.join(";") + "}" this.latexMarkup = `\\{${this.values.join(";")}\\}` } - + includes(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) for(let value of this.values) if(x === value.execute()) return true return false } - + next(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) + if(typeof x == "string") x = executeExpression(x) if(x < this.executedValues[0]) return this.executedValues[0] for(let i = 1; i < this.values.length; i++) { - let prevValue = this.executedValues[i-1] + let prevValue = this.executedValues[i - 1] let value = this.executedValues[i] if(x >= prevValue && x < value) return value } return null } - + previous(x) { if(x instanceof Expression) x = x.execute() - if(typeof x == 'string') x = executeExpression(x) - if(x > this.executedValues[this.executedValues.length-1]) - return this.executedValues[this.executedValues.length-1] + if(typeof x == "string") x = executeExpression(x) + if(x > this.executedValues[this.executedValues.length - 1]) + return this.executedValues[this.executedValues.length - 1] for(let i = 1; i < this.values.length; i++) { - let prevValue = this.executedValues[i-1] + let prevValue = this.executedValues[i - 1] let value = this.executedValues[i] if(x > prevValue && x <= value) return prevValue } return null } - + toString() { return this.displayName } - + union(domain) { if(domain instanceof EmptySet) return this if(domain instanceof DomainSet) { let newValues = [] - let values = this.values.concat(domain.values).filter(function(val){ + let values = this.values.concat(domain.values).filter(function(val) { newValues.push(val.execute()) return newValues.indexOf(val.execute()) === newValues.length - 1 }) @@ -378,18 +383,18 @@ export class DomainSet extends SpecialDomain { domain.openEnd = false } } - if(!domain.includes(value)) + if(!domain.includes(value)) notIncludedValues.push(this.values[i].toEditableString()) } if(notIncludedValues.length === 0) return domain return new UnionDomain(domain, new DomainSet(notIncludedValues)) } - + intersection(domain) { if(domain instanceof EmptySet) return domain if(domain instanceof DomainSet) { let domValues = domain.values.map(expr => expr.execute()) - this.values = this.values.filter(function(val){ + this.values = this.values.filter(function(val) { return domValues.indexOf(val.execute()) >= 0 }) return this @@ -405,16 +410,16 @@ export class DomainSet extends SpecialDomain { domain.openEnd = false } } - if(domain.includes(value)) + if(domain.includes(value)) includedValues.push(this.values[i].toEditableString()) } if(includedValues.length === 0) return new EmptySet() if(includedValues.length === this.values.length) return this return new IntersectionDomain(domain, new DomainSet(includedValues)) } - + static import(frm) { - return new DomainSet(frm.substr(1, frm.length-2).split(";")) + return new DomainSet(frm.substring(1, frm.length - 1).split(";")) } } @@ -429,15 +434,15 @@ export class UnionDomain extends Domain { this.displayName = this.dom1.toString() + " ∪ " + this.dom2.toString() this.latexMarkup = `${dom1.latexMarkup}\\cup${dom2.latexMarkup}` } - + includes(x) { return this.dom1.includes(x) || this.dom2.includes(x) } - + toString() { return this.displayName } - + union(domain) { if(domain instanceof EmptySet) return this if(domain instanceof DomainSet) return domain.union(this) @@ -446,7 +451,7 @@ export class UnionDomain extends Domain { if(domain instanceof IntersectionDomain) return new UnionDomain(this, domain) if(domain instanceof MinusDomain) return new MinusDomain(this, domain) } - + intersection(domain) { if(domain instanceof EmptySet) return domain if(domain instanceof DomainSet) return domain.intersection(this) @@ -454,12 +459,12 @@ export class UnionDomain extends Domain { if(domain instanceof IntersectionDomain) return this.dom1.intersection(domain.dom1).intersection(this.dom2).intersection(domain.dom2) if(domain instanceof MinusDomain) return new IntersectionDomain(this, domain) } - + static import(frm) { let domains = frm.trim().split("∪") if(domains.length === 1) domains = frm.trim().split("U") // Fallback let dom2 = parseDomain(domains.pop()) - let dom1 = parseDomain(domains.join('∪')) + let dom1 = parseDomain(domains.join("∪")) return dom1.union(dom2) } } @@ -475,24 +480,24 @@ export class IntersectionDomain extends Domain { this.displayName = dom1.toString() + " ∩ " + dom2.toString() this.latexMarkup = `${dom1.latexMarkup}\\cap${dom2.latexMarkup}` } - + includes(x) { return this.dom1.includes(x) && this.dom2.includes(x) } - + toString() { return this.displayName } - + union(domain) { if(domain instanceof EmptySet) return this if(domain instanceof DomainSet) return domain.union(this) if(domain instanceof Range) return domain.union(this) - if(domain instanceof UnionDomain) return this.dom1.union(domain.dom1).union(this.dom2).union(domain.dom2) + if(domain instanceof UnionDomain) return this.dom1.union(domain.dom1).union(this.dom2).union(domain.dom2) if(domain instanceof IntersectionDomain) return new UnionDomain(this, domain) if(domain instanceof MinusDomain) return new MinusDomain(this, domain) } - + intersection(domain) { if(domain instanceof EmptySet) return domain if(domain instanceof DomainSet) return domain.intersection(this) @@ -500,11 +505,11 @@ export class IntersectionDomain extends Domain { if(domain instanceof IntersectionDomain) return new IntersectionDomain(this, domain) if(domain instanceof MinusDomain) return new IntersectionDomain(this, domain) } - + static import(frm) { let domains = frm.trim().split("∩") let dom1 = parseDomain(domains.pop()) - let dom2 = parseDomain(domains.join('∩')) + let dom2 = parseDomain(domains.join("∩")) return dom1.intersection(dom2) } } @@ -520,20 +525,20 @@ export class MinusDomain extends Domain { this.displayName = dom1.toString() + "∖" + dom2.toString() this.latexMarkup = `${dom1.latexMarkup}\\setminus${dom2.latexMarkup}` } - + includes(x) { return this.dom1.includes(x) && !this.dom2.includes(x) } - + toString() { return this.displayName } - + static import(frm) { let domains = frm.trim().split("∖") if(domains.length === 1) domains = frm.trim().split("\\") // Fallback let dom1 = parseDomain(domains.shift()) - let dom2 = parseDomain(domains.join('∪')) + let dom2 = parseDomain(domains.join("∪")) return new MinusDomain(dom1, dom2) } } @@ -542,53 +547,53 @@ Domain.RE = new MinusDomain("R", "{0}") Domain.RE.displayName = "ℝ*" Domain.RE.latexMarkup = "\\mathbb{R}^{*}" -Domain.R = new Range(-Infinity,Infinity,true,true) +Domain.R = new Range(-Infinity, Infinity, true, true) Domain.R.displayName = "ℝ" Domain.R.latexMarkup = "\\mathbb{R}" -Domain.RP = new Range(0,Infinity,true,false) +Domain.RP = new Range(0, Infinity, true, false) Domain.RP.displayName = "ℝ⁺" Domain.RP.latexMarkup = "\\mathbb{R}^{+}" -Domain.RM = new Range(-Infinity,0,true,false) +Domain.RM = new Range(-Infinity, 0, true, false) Domain.RM.displayName = "ℝ⁻" Domain.RM.latexMarkup = "\\mathbb{R}^{-}" -Domain.RPE = new Range(0,Infinity,true,true) +Domain.RPE = new Range(0, Infinity, true, true) Domain.RPE.displayName = "ℝ⁺*" Domain.RPE.latexMarkup = "\\mathbb{R}^{+*}" -Domain.RME = new Range(-Infinity,0,true,true) +Domain.RME = new Range(-Infinity, 0, true, true) Domain.RME.displayName = "ℝ⁻*" Domain.RME.latexMarkup = "\\mathbb{R}^{+*}" -Domain.N = new SpecialDomain('ℕ', x => x%1===0 && x >= 0, - x => Math.max(Math.floor(x)+1, 0), - x => Math.max(Math.ceil(x)-1, 0)) +Domain.N = new SpecialDomain("ℕ", x => x % 1 === 0 && x >= 0, + x => Math.max(Math.floor(x) + 1, 0), + x => Math.max(Math.ceil(x) - 1, 0)) Domain.N.latexMarkup = "\\mathbb{N}" -Domain.NE = new SpecialDomain('ℕ*', x => x%1===0 && x > 0, - x => Math.max(Math.floor(x)+1, 1), - x => Math.max(Math.ceil(x)-1, 1)) +Domain.NE = new SpecialDomain("ℕ*", x => x % 1 === 0 && x > 0, + x => Math.max(Math.floor(x) + 1, 1), + x => Math.max(Math.ceil(x) - 1, 1)) Domain.NE.latexMarkup = "\\mathbb{N}^{*}" -Domain.Z = new SpecialDomain('ℤ', x => x%1===0, x => Math.floor(x)+1, x => Math.ceil(x)-1) +Domain.Z = new SpecialDomain("ℤ", x => x % 1 === 0, x => Math.floor(x) + 1, x => Math.ceil(x) - 1) Domain.Z.latexMarkup = "\\mathbb{Z}" -Domain.ZE = new SpecialDomain('ℤ*', x => x%1===0 && x !== 0, - x => Math.floor(x)+1 === 0 ? Math.floor(x)+2 : Math.floor(x)+1, - x => Math.ceil(x)-1 === 0 ? Math.ceil(x)-2 : Math.ceil(x)-1) +Domain.ZE = new SpecialDomain("ℤ*", x => x % 1 === 0 && x !== 0, + x => Math.floor(x) + 1 === 0 ? Math.floor(x) + 2 : Math.floor(x) + 1, + x => Math.ceil(x) - 1 === 0 ? Math.ceil(x) - 2 : Math.ceil(x) - 1) Domain.ZE.latexMarkup = "\\mathbb{Z}^{*}" -Domain.ZM = new SpecialDomain('ℤ⁻', x => x%1===0 && x <= 0, - x => Math.min(Math.floor(x)+1, 0), - x => Math.min(Math.ceil(x)-1, 0)) +Domain.ZM = new SpecialDomain("ℤ⁻", x => x % 1 === 0 && x <= 0, + x => Math.min(Math.floor(x) + 1, 0), + x => Math.min(Math.ceil(x) - 1, 0)) Domain.ZM.latexMarkup = "\\mathbb{Z}^{-}" -Domain.ZME = new SpecialDomain('ℤ⁻*', x => x%1===0 && x < 0, - x => Math.min(Math.floor(x)+1, -1), - x => Math.min(Math.ceil(x)-1, -1)) +Domain.ZME = new SpecialDomain("ℤ⁻*", x => x % 1 === 0 && x < 0, + x => Math.min(Math.floor(x) + 1, -1), + x => Math.min(Math.ceil(x) - 1, -1)) Domain.ZME.latexMarkup = "\\mathbb{Z}^{-*}" -Domain.NLog = new SpecialDomain('ℕˡᵒᵍ', - x => x/Math.pow(10, x.toString().length-1) % 1 === 0 && x > 0, - function(x) { - let x10pow = Math.pow(10, x.toString().length-1) - return Math.max(1, (Math.floor(x/x10pow)+1)*x10pow) - }, - function(x) { - let x10pow = Math.pow(10, x.toString().length-1) - return Math.max(1, (Math.ceil(x/x10pow)-1)*x10pow) - }) +Domain.NLog = new SpecialDomain("ℕˡᵒᵍ", + x => x / Math.pow(10, x.toString().length - 1) % 1 === 0 && x > 0, + function(x) { + let x10pow = Math.pow(10, x.toString().length - 1) + return Math.max(1, (Math.floor(x / x10pow) + 1) * x10pow) + }, + function(x) { + let x10pow = Math.pow(10, x.toString().length - 1) + return Math.max(1, (Math.ceil(x / x10pow) - 1) * x10pow) + }) Domain.NLog.latexMarkup = "\\mathbb{N}^{log}" let refedDomains = [] @@ -600,11 +605,11 @@ let refedDomains = [] * @returns {Domain} Parsed domain. */ export function parseDomain(domain) { - if(!domain.includes(')') && !domain.includes('(')) return parseDomainSimple(domain) + if(!domain.includes(")") && !domain.includes("(")) return parseDomainSimple(domain) let domStr while((domStr = /\(([^)(]+)\)/.exec(domain)) !== null) { - let dom = parseDomainSimple(domStr[1].trim()); - domain = domain.replace(domStr[0], 'D' + refedDomains.length) + let dom = parseDomainSimple(domStr[1].trim()) + domain = domain.replace(domStr[0], "D" + refedDomains.length) refedDomains.push(dom) } return parseDomainSimple(domain) @@ -621,10 +626,10 @@ export function parseDomainSimple(domain) { if(domain.includes("U") || domain.includes("∪")) return UnionDomain.import(domain) if(domain.includes("∩")) return IntersectionDomain.import(domain) if(domain.includes("∖") || domain.includes("\\")) return MinusDomain.import(domain) - if(domain.charAt(0) === "{" && domain.charAt(domain.length -1) === "}") return DomainSet.import(domain) + if(domain.charAt(0) === "{" && domain.charAt(domain.length - 1) === "}") return DomainSet.import(domain) if(domain.includes("]") || domain.includes("[")) return Range.import(domain) if(["R", "ℝ", "N", "ℕ", "Z", "ℤ"].some(str => domain.toUpperCase().includes(str))) return Domain.import(domain) - if(domain[0] === 'D') return refedDomains[parseInt(domain.substr(1))] + if(domain[0] === "D") return refedDomains[parseInt(domain.substring(1))] return new EmptySet() } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/expression.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/expression.mjs index 6505018..2862183 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/expression.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/math/expression.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -37,70 +37,90 @@ export class Expression { } this.cached = this.isConstant() this.cachedValue = null - if(this.cached && this.allRequirementsFullfilled()) + if(this.cached && this.allRequirementsFulfilled()) this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) this.latexMarkup = Latex.expression(this.calc.tokens) } + /** + * Return all the variables used in calc + * @return {string[]} + */ variables() { return this.calc.variables() } + /** + * Checks if the current expression is constant (does not depend on a variable, be it x or n). + * @return {boolean} + */ isConstant() { let vars = this.calc.variables() return !vars.includes("x") && !vars.includes("n") } - + + /** + * Returns the list of object names this expression is dependant on. + * @return {string[]} + */ requiredObjects() { return this.calc.variables().filter(objName => objName !== "x" && objName !== "n") } - - allRequirementsFullfilled() { + + /** + * Checks if all the objects required for this expression are defined. + * @return {boolean} + */ + allRequirementsFulfilled() { return this.requiredObjects().every(objName => objName in Objects.currentObjectsByName) } - + + /** + * Returns a list of names whose corresponding objects this expression is dependant on and are missing. + * @return {boolean} + */ undefinedVariables() { return this.requiredObjects().filter(objName => !(objName in Objects.currentObjectsByName)) } - + recache() { if(this.cached) this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) } - + execute(x = 1) { if(this.cached) { if(this.cachedValue == null) this.cachedValue = this.calc.evaluate(Objects.currentObjectsByName) return this.cachedValue } - ExprParser.currentVars = Object.assign({'x': x}, Objects.currentObjectsByName) + ExprParser.currentVars = Object.assign({ "x": x }, Objects.currentObjectsByName) return this.calc.evaluate(ExprParser.currentVars) } - + simplify(x) { - let expr = this.calc.substitute('x', x).simplify() - if(expr.evaluate() === 0) expr = '0' + let expr = this.calc.substitute("x", x).simplify() + if(expr.evaluate() === 0) expr = "0" return new Expression(expr) } - + toEditableString() { return this.calc.toString() } - - toString(forceSign=false) { + + toString(forceSign = false) { let str = Utils.makeExpressionReadable(this.calc.toString()) if(str !== undefined && str.match(/^\d*\.\d+$/)) { - if(str.split('.')[1].split('0').length > 7) { + if(str.split(".")[1].split("0").length > 7) { // Likely rounding error - str = parseFloat(str.substring(0, str.length-1)).toString(); + str = parseFloat(str.substring(0, str.length - 1)).toString() } } - if(str[0] !== '-' && forceSign) str = '+' + str + if(str[0] !== "-" && forceSign) str = "+" + str return str } } -export function executeExpression(expr){ +export function executeExpression(expr) { return (new Expression(expr.toString())).execute() } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/canvas.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/canvas.mjs index 04abf68..e623034 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/canvas.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/canvas.mjs @@ -17,7 +17,7 @@ */ import { Module } from "./common.mjs" -import { FUNCTION, Interface, CanvasInterface, DialogInterface } from "./interface.mjs" +import { CanvasInterface, DialogInterface } from "./interface.mjs" import { textsup } from "../utils.mjs" import { Expression } from "../math/index.mjs" import Latex from "./latex.mjs" @@ -227,7 +227,7 @@ class CanvasAPI extends Module { // Drawing throws an error. Generally, it's due to a new modification (or the opening of a file) console.error(e) console.log(e.stack) - this._drawingErrorDialog.showDialog(objType, obj.name, e.message) + this._drawingErrorDialog.show(objType, obj.name, e.message) History.undo() } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/common.mjs index 6902745..0a5046b 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/common.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/common.mjs @@ -26,7 +26,7 @@ export class Module { /** * * @param {string} name - Name of the API - * @param {Object.} initializationParameters - List of parameters for the initialize function. + * @param {Object.} initializationParameters - List of parameters for the initialize function. */ constructor(name, initializationParameters = {}) { console.log(`Loading module ${name}...`) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/expreval.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/expreval.mjs index f40489f..854f928 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/expreval.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/expreval.mjs @@ -55,7 +55,7 @@ class ExprParserAPI extends Module { * @return {function} JS function to call. */ parseArgumentsForFunction(args, usage1, usage2) { - let f, target, variable + let f, variable if(args.length === 1) { // Parse object f = args[0] diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/history.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/history.mjs index 09b45d6..42146ce 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/history.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/history.mjs @@ -17,7 +17,6 @@ */ import { Module } from "./common.mjs" -import Latex from "./latex.mjs" import { HistoryInterface, NUMBER, STRING } from "./interface.mjs" diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/interface.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/interface.mjs index 37f4f5b..77e2741 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/interface.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/interface.mjs @@ -94,6 +94,10 @@ export class CanvasInterface extends SettingsInterface { markDirty = FUNCTION /** @type {function(string)} */ loadImage = FUNCTION + /** @type {function(string)} */ + isImageLoading = FUNCTION + /** @type {function(string)} */ + isImageLoaded = FUNCTION /** @type {function()} */ requestPaint = FUNCTION } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/io.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/io.mjs index d4ff50c..b6d40f5 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/io.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/io.mjs @@ -20,7 +20,7 @@ import { Module } from "./common.mjs" import Objects from "./objects.mjs" import History from "./history.mjs" import Canvas from "./canvas.mjs" -import { DialogInterface, FUNCTION, Interface, RootInterface, SettingsInterface } from "./interface.mjs" +import { DialogInterface, RootInterface, SettingsInterface } from "./interface.mjs" class IOAPI extends Module { diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/latex.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/latex.mjs index 0071779..fa194f5 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/latex.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/latex.mjs @@ -20,7 +20,8 @@ import { Module } from "./common.mjs" import * as Instruction from "../lib/expr-eval/instruction.mjs" import { escapeValue } from "../lib/expr-eval/expression.mjs" -const unicodechars = ["α", "β", "γ", "δ", "ε", "ζ", "η", +const unicodechars = [ + "α", "β", "γ", "δ", "ε", "ζ", "η", "π", "θ", "κ", "λ", "μ", "ξ", "ρ", "ς", "σ", "τ", "φ", "χ", "ψ", "ω", "Γ", "Δ", "Θ", "Λ", "Ξ", "Π", "Σ", @@ -30,7 +31,8 @@ const unicodechars = ["α", "β", "γ", "δ", "ε", "ζ", "η", "⁷", "⁸", "⁹", "⁰", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", "₀", "pi", "∞"] -const equivalchars = ["\\alpha", "\\beta", "\\gamma", "\\delta", "\\epsilon", "\\zeta", "\\eta", +const equivalchars = [ + "\\alpha", "\\beta", "\\gamma", "\\delta", "\\epsilon", "\\zeta", "\\eta", "\\pi", "\\theta", "\\kappa", "\\lambda", "\\mu", "\\xi", "\\rho", "\\sigma", "\\sigma", "\\tau", "\\phi", "\\chi", "\\psi", "\\omega", "\\Gamma", "\\Delta", "\\Theta", "\\Lambda", "\\Xi", "\\Pi", "\\Sigma", @@ -71,7 +73,7 @@ class LatexAPI extends Module { * * @param {string} markup - LaTeX markup to render. * @param {number} fontSize - Font size (in pt) to render. - * @param {color} color - Color of the text to render. + * @param {string} color - Color of the text to render. * @returns {LatexRenderResult|null} */ findPrerendered(markup, fontSize, color) { @@ -87,7 +89,7 @@ class LatexAPI extends Module { * * @param {string} markup - LaTeX markup to render. * @param {number} fontSize - Font size (in pt) to render. - * @param {color} color - Color of the text to render. + * @param {string} color - Color of the text to render. * @returns {Promise} */ async requestAsyncRender(markup, fontSize, color) { @@ -119,7 +121,7 @@ class LatexAPI extends Module { if(elem[0] !== "(" && elem[elem.length - 1] !== ")" && contents.some(x => elem.indexOf(x) > 0)) return this.par(elem) if(elem[0] === "(" && elem[elem.length - 1] === ")") - return elem.substr(1, elem.length - 2) + return elem.removeEnclosure() return elem } @@ -134,24 +136,24 @@ class LatexAPI extends Module { switch(f) { case "derivative": if(args.length === 3) - return "\\frac{d" + args[0].substr(1, args[0].length - 2).replace(new RegExp(args[1].substr(1, args[1].length - 2), "g"), "x") + "}{dx}" + return `\\frac{d${args[0].removeEnclosure().replaceAll(args[1].removeEnclosure(), "x")}}{dx}` else - return "\\frac{d" + args[0] + "}{dx}(x)" + return `\\frac{d${args[0]}}{dx}(x)` case "integral": if(args.length === 4) - return "\\int\\limits_{" + args[0] + "}^{" + args[1] + "}" + args[2].substr(1, args[2].length - 2) + " d" + args[3].substr(1, args[3].length - 2) + return `\\int\\limits_{${args[0]}}^{${args[1]}}${args[2].removeEnclosure()} d${args[3].removeEnclosure()}` else - return "\\int\\limits_{" + args[0] + "}^{" + args[1] + "}" + args[2] + "(t) dt" + return `\\int\\limits_{${args[0]}}^{${args[1]}}${args[2]}(t) dt` case "sqrt": - return "\\sqrt\\left(" + args.join(", ") + "\\right)" + return `\\sqrt\\left(${args.join(", ")}\\right)` case "abs": - return "\\left|" + args.join(", ") + "\\right|" + return `\\left|${args.join(", ")}\\right|` case "floor": - return "\\left\\lfloor" + args.join(", ") + "\\right\\rfloor" + return `\\left\\lfloor${args.join(", ")}\\right\\rfloor` case "ceil": - return "\\left\\lceil" + args.join(", ") + "\\right\\rceil" + return `\\left\\lceil${args.join(", ")}\\right\\rceil` default: - return "\\mathrm{" + f + "}\\left(" + args.join(", ") + "\\right)" + return `\\mathrm{${f}}\\left(${args.join(", ")}\\right)` } } @@ -166,12 +168,12 @@ class LatexAPI extends Module { if(wrapIn$) for(let i = 0; i < unicodechars.length; i++) { if(vari.includes(unicodechars[i])) - vari = vari.replace(new RegExp(unicodechars[i], "g"), "$" + equivalchars[i] + "$") + vari = vari.replaceAll(unicodechars[i], "$" + equivalchars[i] + "$") } else for(let i = 0; i < unicodechars.length; i++) { if(vari.includes(unicodechars[i])) - vari = vari.replace(new RegExp(unicodechars[i], "g"), equivalchars[i]) + vari = vari.replaceAll(unicodechars[i], equivalchars[i]) } return vari } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/objects.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/objects.mjs index 5a63386..a95dc89 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/objects.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/objects.mjs @@ -1,28 +1,28 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ -import { Module } from './common.mjs' -import { textsub } from '../utils.mjs' +import { Module } from "./common.mjs" +import { textsub } from "../utils.mjs" class ObjectsAPI extends Module { constructor() { - super('Objects') + super("Objects") this.types = {} /** @@ -45,7 +45,7 @@ class ObjectsAPI extends Module { * @param {string} prefix - Prefix to the name. * @return {string} New unused name for a new object. */ - getNewName(allowedLetters, prefix='') { + getNewName(allowedLetters, prefix = "") { // Allows to get a new name, based on the allowed letters, // as well as adding a sub number when needs be. let newid = 0 @@ -53,7 +53,7 @@ class ObjectsAPI extends Module { do { let letter = allowedLetters[newid % allowedLetters.length] let num = Math.floor((newid - (newid % allowedLetters.length)) / allowedLetters.length) - ret = prefix + letter + (num > 0 ? textsub(num-1) : '') + ret = prefix + letter + (num > 0 ? textsub(num - 1) : "") newid += 1 } while(ret in this.currentObjectsByName) return ret @@ -78,7 +78,7 @@ class ObjectsAPI extends Module { deleteObject(objName) { let obj = this.currentObjectsByName[objName] if(obj !== undefined) { - this.currentObjects[obj.type].splice(this.currentObjects[obj.type].indexOf(obj),1) + this.currentObjects[obj.type].splice(this.currentObjects[obj.type].indexOf(obj), 1) obj.delete() delete this.currentObjectsByName[objName] } @@ -90,15 +90,10 @@ class ObjectsAPI extends Module { * @returns {string[]} List of names of the objects. */ getObjectsName(objType) { - if(objType === "ExecutableObject") { - // NOTE: QMLJS does not support flatMap. - // return getExecutableTypes().flatMap(elemType => currentObjects[elemType].map(obj => obj.name)) - let types = this.getExecutableTypes() - let elementNames = [''] - for(let elemType of types) - elementNames = elementNames.concat(this.currentObjects[elemType].map(obj => obj.name)) - return elementNames - } + if(objType === "ExecutableObject") + return this.getExecutableTypes().flatMap( + elemType => this.currentObjects[elemType].map(obj => obj.name) + ) if(this.currentObjects[objType] === undefined) return [] return this.currentObjects[objType].map(obj => obj.name) } @@ -117,9 +112,9 @@ class ObjectsAPI extends Module { * @param {string[]} args - List of arguments for the objects (can be empty). * @return {DrawableObject} Newly created object. */ - createNewRegisteredObject(objType, args= []) { + createNewRegisteredObject(objType, args = []) { if(Object.keys(this.types).indexOf(objType) === -1) return null // Object type does not exist. - let newobj = new this.types[objType](...args) + const newobj = new this.types[objType](...args) if(Object.keys(this.currentObjects).indexOf(objType) === -1) { this.currentObjects[objType] = [] } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/preferences.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/preferences.mjs index 389a5ba..453bc0e 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/preferences.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/module/preferences.mjs @@ -15,19 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -import {Module} from "./common.mjs" +import { Module } from "./common.mjs" import General from "../preferences/general.mjs" import Editor from "../preferences/expression.mjs" import DefaultGraph from "../preferences/default.mjs" class PreferencesAPI extends Module { constructor() { - super('Preferences') + super("Preferences") this.categories = { - [QT_TRANSLATE_NOOP('settingCategory', 'general')]: General, - [QT_TRANSLATE_NOOP('settingCategory', 'editor')]: Editor, - [QT_TRANSLATE_NOOP('settingCategory', 'default')]: DefaultGraph, + [QT_TRANSLATE_NOOP("settingCategory", "general")]: General, + [QT_TRANSLATE_NOOP("settingCategory", "editor")]: Editor, + [QT_TRANSLATE_NOOP("settingCategory", "default")]: DefaultGraph } } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/autoload.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/autoload.mjs index 729e167..26a6003 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/autoload.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/autoload.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitude.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitude.mjs index 1534dd5..82d9728 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitude.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitude.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -27,89 +27,100 @@ import { ExecutableObject } from "./common.mjs" import Function from "./function.mjs" export default class BodeMagnitude extends ExecutableObject { - static type(){return 'Gain Bode'} - static displayType(){return qsTranslate("bodemagnitude", 'Bode Magnitude')} - static displayTypeMultiple(){return qsTranslate("bodemagnitude", 'Bode Magnitudes')} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','om_0')]: new P.ObjectType('Point'), - [QT_TRANSLATE_NOOP('prop','pass')]: P.Enum.BodePass, - [QT_TRANSLATE_NOOP('prop','gain')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - [QT_TRANSLATE_NOOP('prop','omGraduation')]: 'boolean' - }} + static type() { + return "Gain Bode" + } - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - om_0 = '', pass = 'high', gain = '20', labelPosition = 'above', labelX = 1, omGraduation = false) { - if(name == null) name = Objects.getNewName('G') - if(name === 'G') name = 'G₀' // G is reserved for sum of BODE magnitudes (Somme gains Bode). + static displayType() { + return qsTranslate("bodemagnitude", "Bode Magnitude") + } + + static displayTypeMultiple() { + return qsTranslate("bodemagnitude", "Bode Magnitudes") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "om_0")]: new P.ObjectType("Point"), + [QT_TRANSLATE_NOOP("prop", "pass")]: P.Enum.BodePass, + [QT_TRANSLATE_NOOP("prop", "gain")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number", + [QT_TRANSLATE_NOOP("prop", "omGraduation")]: "boolean" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + om_0 = "", pass = "high", gain = "20", labelPosition = "above", labelX = 1, omGraduation = false) { + if(name == null) name = Objects.getNewName("G") + if(name === "G") name = "G₀" // G is reserved for sum of BODE magnitudes (Somme gains Bode). super(name, visible, color, labelContent) if(typeof om_0 == "string") { // Point name or create one om_0 = Objects.currentObjectsByName[om_0] if(om_0 == null) { // Create new point - om_0 = Objects.createNewRegisteredObject('Point', [Objects.getNewName('ω'), true, this.color, 'name']) - History.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export())) + om_0 = Objects.createNewRegisteredObject("Point", [Objects.getNewName("ω"), true, this.color, "name"]) + History.addToHistory(new CreateNewObject(om_0.name, "Point", om_0.export())) om_0.update() - labelPosition = 'below' + labelPosition = "below" } om_0.requiredBy.push(this) } /** @type {Point} */ this.om_0 = om_0 this.pass = pass - if(typeof gain == 'number' || typeof gain == 'string') gain = new Expression(gain.toString()) + if(typeof gain == "number" || typeof gain == "string") gain = new Expression(gain.toString()) this.gain = gain this.labelPosition = labelPosition this.labelX = labelX this.omGraduation = omGraduation } - + getReadableString() { - let pass = this.pass === "low" ? qsTranslate("bodemagnitude", "low-pass") : qsTranslate("bodemagnitude", "high-pass"); - return `${this.name}: ${pass}; ${this.om_0.name} = ${this.om_0.x}\n ${' '.repeat(this.name.length)}${this.gain.toString(true)} dB/dec` + let pass = this.pass === "low" ? qsTranslate("bodemagnitude", "low-pass") : qsTranslate("bodemagnitude", "high-pass") + return `${this.name}: ${pass}; ${this.om_0.name} = ${this.om_0.x}\n ${" ".repeat(this.name.length)}${this.gain.toString(true)} dB/dec` } - + getLatexString() { - let pass = this.pass === "low" ? qsTranslate("bodemagnitude", "low-pass") : qsTranslate("bodemagnitude", "high-pass"); + let pass = this.pass === "low" ? qsTranslate("bodemagnitude", "low-pass") : qsTranslate("bodemagnitude", "high-pass") return `\\mathrm{${Latex.variable(this.name)}:}\\begin{array}{l} \\textsf{${pass}};${Latex.variable(this.om_0.name)} = ${this.om_0.x.latexMarkup} \\\\ ${this.gain.latexMarkup}\\textsf{ dB/dec} \\end{array}` } - - execute(x=1) { - if(typeof x == 'string') x = executeExpression(x) - if((this.pass === 'high' && x < this.om_0.x) || (this.pass === 'low' && x > this.om_0.x)) { + + execute(x = 1) { + if(typeof x == "string") x = executeExpression(x) + if((this.pass === "high" && x < this.om_0.x) || (this.pass === "low" && x > this.om_0.x)) { let dbfn = new Expression(`${this.gain.execute()}*(ln(x)-ln(${this.om_0.x}))/ln(10)+${this.om_0.y}`) return dbfn.execute(x) } else { return this.om_0.y.execute() } } - + simplify(x = 1) { let xval = x - if(typeof x == 'string') xval = executeExpression(x) - if((this.pass === 'high' && xval < this.om_0.x.execute()) || (this.pass === 'low' && xval > this.om_0.x.execute())) { + if(typeof x == "string") xval = executeExpression(x) + if((this.pass === "high" && xval < this.om_0.x.execute()) || (this.pass === "low" && xval > this.om_0.x.execute())) { let dbfn = new Expression(`${this.gain.execute()}*(ln(x)-ln(${this.om_0.x}))/ln(10)+${this.om_0.y}`) return dbfn.simplify(x) } else { return this.om_0.y.toString() } } - + canExecute(x = 1) { return true } - + draw(canvas) { let base = [canvas.x2px(this.om_0.x.execute()), canvas.y2px(this.om_0.y.execute())] let dbfn = new Expression(`${this.gain.execute()}*(log10(x)-log10(${this.om_0.x}))+${this.om_0.y}`) - let inDrawDom = new EmptySet() + let inDrawDom - if(this.pass === 'high') { + if(this.pass === "high") { // High pass, linear line from beginning, then constant to the end. canvas.drawLine(base[0], base[1], canvas.width, base[1]) inDrawDom = parseDomain(`]-inf;${this.om_0.x}[`) @@ -122,26 +133,28 @@ export default class BodeMagnitude extends ExecutableObject { // Dashed line representing break in function let xpos = canvas.x2px(this.om_0.x.execute()) let dashPxSize = 10 - for(let i = 0; i < canvas.height && this.omGraduation; i += dashPxSize*2) - canvas.drawLine(xpos, i, xpos, i+dashPxSize) - + for(let i = 0; i < canvas.height && this.omGraduation; i += dashPxSize * 2) + canvas.drawLine(xpos, i, xpos, i + dashPxSize) + // Label this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.labelX), canvas.y2px(this.execute(this.labelX))) } - + update() { super.update() - let sumObjs = Objects.currentObjects['Somme gains Bode'] + /** @type {BodeMagnitudeSum[]} */ + let sumObjs = Objects.currentObjects["Somme gains Bode"] if(sumObjs !== undefined && sumObjs.length > 0) { sumObjs[0].recalculateCache() } else { - Objects.createNewRegisteredObject('Somme gains Bode') + Objects.createNewRegisteredObject("Somme gains Bode") } } - + delete() { super.delete() - let sumObjs = Objects.currentObjects['Somme gains Bode'] + /** @type {BodeMagnitudeSum[]} */ + let sumObjs = Objects.currentObjects["Somme gains Bode"] if(sumObjs !== undefined && sumObjs.length > 0) { sumObjs[0].recalculateCache() } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitudesum.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitudesum.mjs index f268bbe..eb81663 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitudesum.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodemagnitudesum.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -26,32 +26,46 @@ import Function from "./function.mjs" export default class BodeMagnitudeSum extends ExecutableObject { - static type(){return 'Somme gains Bode'} - static displayType(){return qsTranslate("bodemagnitudesum", 'Bode Magnitudes Sum')} - static displayTypeMultiple(){return qsTranslate("bodemagnitudesum", 'Bode Magnitudes Sum')} - static createable() {return false} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - labelPosition = 'above', labelX = 1) { - if(name == null) name = 'G' + static type() { + return "Somme gains Bode" + } + + static displayType() { + return qsTranslate("bodemagnitudesum", "Bode Magnitudes Sum") + } + + static displayTypeMultiple() { + return qsTranslate("bodemagnitudesum", "Bode Magnitudes Sum") + } + + static createable() { + return false + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + labelPosition = "above", labelX = 1) { + if(name == null) name = "G" super(name, visible, color, labelContent) this.labelPosition = labelPosition this.labelX = labelX this.recalculateCache() } - + getReadableString() { - return `${this.name} = ${Objects.getObjectsName('Gain Bode').join(' + ')}` + return `${this.name} = ${Objects.getObjectsName("Gain Bode").join(" + ")}` } - + getLatexString() { - return `${Latex.variable(this.name)} = ${Objects.getObjectsName('Gain Bode').map(name => Latex.variable(name)).join(' + ')}` + return `${Latex.variable(this.name)} = ${Objects.getObjectsName("Gain Bode").map(name => Latex.variable(name)).join(" + ")}` } - + execute(x = 0) { for(let [limitedDrawFunction, inDrawDom] of this.cachedParts) { if(inDrawDom.includes(x)) { @@ -60,50 +74,50 @@ export default class BodeMagnitudeSum extends ExecutableObject { } return null } - + canExecute(x = 1) { return true // Should always be true } - + simplify(x = 1) { for(let [limitedDrawFunction, inDrawDom] of this.cachedParts) { if(inDrawDom.includes(x)) { return limitedDrawFunction.simplify(x) } } - return '' + return "" } - + recalculateCache() { this.cachedParts = [] // Calculating this is fairly resource expansive so it's cached. - let magnitudeObjects = Objects.currentObjects['Gain Bode'] + let magnitudeObjects = Objects.currentObjects["Gain Bode"] if(magnitudeObjects === undefined || magnitudeObjects.length < 1) { Objects.deleteObject(this.name) } else { - console.log('Recalculating cache gain') + console.log("Recalculating cache gain") // Minimum to draw (can be expended if needed, just not infinite or it'll cause issues. const MIN_DRAW = 1e-20 // Format: [[x value of where the filter transitions, magnitude, high-pass (bool)]] - const magnitudes = [] + const magnitudes = [] const XVALUE = 0 const MAGNITUDE = 1 const PASS = 2 magnitudes.push([Number.MAX_VALUE, 0, true]) // Draw the ending section // Collect data from current magnitude (or gain in French) objects. let baseY = 0 - for(/** @type {Bodemagnitude} */ let magnitudeObj of magnitudeObjects) { // Sorting by their om_0 position. + for(/** @type {BodeMagnitude} */ let magnitudeObj of magnitudeObjects) { // Sorting by their om_0 position. const om0x = magnitudeObj.om_0.x.execute() - magnitudes.push([om0x, magnitudeObj.gain.execute(), magnitudeObj.pass === 'high']) + magnitudes.push([om0x, magnitudeObj.gain.execute(), magnitudeObj.pass === "high"]) baseY += magnitudeObj.execute(MIN_DRAW) } // Sorting the data by their x transitions value - magnitudes.sort((a,b) => a[XVALUE] - b[XVALUE]) + magnitudes.sort((a, b) => a[XVALUE] - b[XVALUE]) // Adding the total gains. let magnitudesBeforeTransition = [] let magnitudesAfterTransition = [] let totalMagnitudeAtStart = 0 // Magnitude at the lowest x value (sum of all high-pass magnitudes) - for(let [om0x, magnitude, highpass] of magnitudes){ + for(let [om0x, magnitude, highpass] of magnitudes) { if(highpass) { magnitudesBeforeTransition.push(magnitude) magnitudesAfterTransition.push(0) @@ -129,7 +143,7 @@ export default class BodeMagnitudeSum extends ExecutableObject { } } } - + draw(canvas) { if(this.cachedParts.length > 0) { for(let [limitedDrawFunction, drawDomain] of this.cachedParts) { diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephase.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephase.mjs index 310bb25..9c93bba 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephase.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephase.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -27,33 +27,44 @@ import { ExecutableObject } from "./common.mjs" export default class BodePhase extends ExecutableObject { - static type(){return 'Phase Bode'} - static displayType(){return qsTranslate("bodephase", 'Bode Phase')} - static displayTypeMultiple(){return qsTranslate("bodephase", 'Bode Phases')} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','om_0')]: new P.ObjectType('Point'), - [QT_TRANSLATE_NOOP('prop','phase')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','unit')]: new P.Enum('°', 'deg', 'rad'), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number' - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - om_0 = '', phase = 90, unit = '°', labelPosition = 'above', labelX = 1) { - if(name == null) name = Objects.getNewName('φ') - if(name === 'φ') name = 'φ₀' // φ is reserved for sum of Bode phases. + static type() { + return "Phase Bode" + } + + static displayType() { + return qsTranslate("bodephase", "Bode Phase") + } + + static displayTypeMultiple() { + return qsTranslate("bodephase", "Bode Phases") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "om_0")]: new P.ObjectType("Point"), + [QT_TRANSLATE_NOOP("prop", "phase")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "unit")]: new P.Enum("°", "deg", "rad"), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + om_0 = "", phase = 90, unit = "°", labelPosition = "above", labelX = 1) { + if(name == null) name = Objects.getNewName("φ") + if(name === "φ") name = "φ₀" // φ is reserved for sum of Bode phases. super(name, visible, color, labelContent) - if(typeof phase == 'number' || typeof phase == 'string') phase = new Expression(phase.toString()) + if(typeof phase == "number" || typeof phase == "string") phase = new Expression(phase.toString()) this.phase = phase if(typeof om_0 == "string") { // Point name or create one om_0 = Objects.currentObjectsByName[om_0] if(om_0 == null) { // Create new point - om_0 = Objects.createNewRegisteredObject('Point', [Objects.getNewName('ω'), this.color, 'name']) - om_0.labelPosition = this.phase.execute() >= 0 ? 'above' : 'below' - History.history.addToHistory(new CreateNewObject(om_0.name, 'Point', om_0.export())) - labelPosition = 'below' + om_0 = Objects.createNewRegisteredObject("Point", [Objects.getNewName("ω"), this.color, "name"]) + om_0.labelPosition = this.phase.execute() >= 0 ? "above" : "below" + History.history.addToHistory(new CreateNewObject(om_0.name, "Point", om_0.export())) + labelPosition = "below" } om_0.requiredBy.push(this) } @@ -63,69 +74,71 @@ export default class BodePhase extends ExecutableObject { this.labelPosition = labelPosition this.labelX = labelX } - + getReadableString() { return `${this.name}: ${this.phase.toString(true)}${this.unit} at ${this.om_0.name} = ${this.om_0.x}` } - + getLatexString() { return `${Latex.variable(this.name)}: ${this.phase.latexMarkup}\\textsf{${this.unit} at }${Latex.variable(this.om_0.name)} = ${this.om_0.x.latexMarkup}` } - - execute(x=1) { - if(typeof x == 'string') x = executeExpression(x) + + execute(x = 1) { + if(typeof x == "string") x = executeExpression(x) if(x < this.om_0.x) { return this.om_0.y.execute() } else { return this.om_0.y.execute() + this.phase.execute() } } - + simplify(x = 1) { let xval = x - if(typeof x == 'string') xval = executeExpression(x) + if(typeof x == "string") xval = executeExpression(x) if(xval < this.om_0.x) { return this.om_0.y.toString() } else { - let newExp = this.om_0.y.toEditableString() + ' + ' + this.phase.toEditableString() + let newExp = this.om_0.y.toEditableString() + " + " + this.phase.toEditableString() return new Expression(newExp) } } - + canExecute(x = 1) { return true } - + draw(canvas) { let baseX = canvas.x2px(this.om_0.x.execute()) let omy = this.om_0.y.execute() let augmt = this.phase.execute() let baseY = canvas.y2px(omy) - let augmtY = canvas.y2px(omy+augmt) + let augmtY = canvas.y2px(omy + augmt) // Before change line. canvas.drawLine(0, baseY, Math.min(baseX, canvas.height), baseY) // Transition line. canvas.drawLine(baseX, baseY, baseX, augmtY) // After change line canvas.drawLine(Math.max(0, baseX), augmtY, canvas.width, augmtY) - + // Label this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.labelX), canvas.y2px(this.execute(this.labelX))) } - + update() { super.update() - let sumObjs = Objects.currentObjects['Somme phases Bode'] + /** @type {BodePhaseSum[]} */ + let sumObjs = Objects.currentObjects["Somme phases Bode"] if(sumObjs !== undefined && sumObjs.length > 0) { sumObjs[0].recalculateCache() } else { - Objects.createNewRegisteredObject('Somme phases Bode') + Objects.createNewRegisteredObject("Somme phases Bode") } } - + delete() { super.update() - let sumObjs = Objects.currentObjects['Somme phases Bode'] + /** @type {BodePhaseSum[]} */ + let sumObjs = Objects.currentObjects["Somme phases Bode"] if(sumObjs !== undefined && sumObjs.length > 0) { sumObjs[0].recalculateCache() } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephasesum.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephasesum.mjs index a3de8f6..90864d7 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephasesum.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/bodephasesum.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -24,101 +24,114 @@ import Latex from "../module/latex.mjs" import { ExecutableObject } from "./common.mjs" export default class BodePhaseSum extends ExecutableObject { - static type(){return 'Somme phases Bode'} - static displayType(){return qsTranslate("bodephasesum", 'Bode Phases Sum')} - static displayTypeMultiple(){return qsTranslate("bodephasesum", 'Bode Phases Sum')} - static createable() {return false} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - labelPosition = 'above', labelX = 1) { - if(name == null) name = 'φ' + static type() { + return "Somme phases Bode" + } + + static displayType() { + return qsTranslate("bodephasesum", "Bode Phases Sum") + } + + static displayTypeMultiple() { + return qsTranslate("bodephasesum", "Bode Phases Sum") + } + + static createable() { + return false + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + labelPosition = "above", labelX = 1) { + if(name == null) name = "φ" super(name, visible, color, labelContent) this.labelPosition = labelPosition this.labelX = labelX this.recalculateCache() } - + getReadableString() { - return `${this.name} = ${Objects.getObjectsName('Phase Bode').join(' + ')}` + return `${this.name} = ${Objects.getObjectsName("Phase Bode").join(" + ")}` } - + getLatexString() { - return `${Latex.variable(this.name)} = ${Objects.getObjectsName('Phase Bode').map(name => Latex.variable(name)).join(' + ')}` + return `${Latex.variable(this.name)} = ${Objects.getObjectsName("Phase Bode").map(name => Latex.variable(name)).join(" + ")}` } - - execute(x=1) { - if(typeof x == 'string') x = executeExpression(x) - for(let i = 0; i < this.om0xList.length-1; i++) { - if(x >= this.om0xList[i] && x < this.om0xList[i+1]) return this.phasesList[i] + + execute(x = 1) { + if(typeof x == "string") x = executeExpression(x) + for(let i = 0; i < this.om0xList.length - 1; i++) { + if(x >= this.om0xList[i] && x < this.om0xList[i + 1]) return this.phasesList[i] } } - + simplify(x = 1) { let xval = x - if(typeof x == 'string') xval = executeExpression(x) - for(let i = 0; i < this.om0xList.length-1; i++) { - if(xval >= this.om0xList[i] && xval < this.om0xList[i+1]) { + if(typeof x == "string") xval = executeExpression(x) + for(let i = 0; i < this.om0xList.length - 1; i++) { + if(xval >= this.om0xList[i] && xval < this.om0xList[i + 1]) { return (new Expression(this.phasesExprList[i])).simplify() } } - return '0' + return "0" } - + canExecute(x = 1) { return true } - + recalculateCache() { // Minimum to draw (can be expended if needed, just not infinite or it'll cause issues. let drawMin = 1e-20 let drawMax = 1e20 this.om0xList = [drawMin, drawMax] this.phasesList = [0] - this.phasesExprList = ['0'] + this.phasesExprList = ["0"] let phasesDict = new Map() let phasesExprDict = new Map() phasesDict.set(drawMax, 0) - - let phaseObjects = Objects.currentObjects['Phase Bode'] + + let phaseObjects = Objects.currentObjects["Phase Bode"] if(phaseObjects === undefined || phaseObjects.length < 1) { Objects.deleteObject(this.name) } else { - console.log('Recalculating cache phase') - for(/** @type {Bodephase} */ let obj of phaseObjects) { + console.log("Recalculating cache phase") + for(/** @type {BodePhase} */ let obj of phaseObjects) { this.om0xList.push(obj.om_0.x.execute()) if(!phasesDict.has(obj.om_0.x.execute())) { phasesDict.set(obj.om_0.x.execute(), obj.phase.execute()) phasesExprDict.set(obj.om_0.x.execute(), obj.phase.toEditableString()) } else { phasesDict.set(obj.om_0.x.execute(), obj.phase.execute() + phasesDict.get(obj.om_0.x.execute())) - phasesExprDict.set(obj.om_0.x.execute(), obj.phase.toEditableString() + '+' + phasesExprDict.get(obj.om_0.x.execute())) + phasesExprDict.set(obj.om_0.x.execute(), obj.phase.toEditableString() + "+" + phasesExprDict.get(obj.om_0.x.execute())) } this.phasesList[0] += obj.om_0.y.execute() - this.phasesExprList[0] += '+' + obj.om_0.y.toEditableString() + this.phasesExprList[0] += "+" + obj.om_0.y.toEditableString() } - this.om0xList.sort((a,b) => a - b) - let totalAdded = this.phasesList[0] + this.om0xList.sort((a, b) => a - b) for(let i = 1; i < this.om0xList.length; i++) { - this.phasesList[i] = this.phasesList[i-1] + phasesDict.get(this.om0xList[i]) - this.phasesExprList[i] = this.phasesExprList[i-1] + '+' + phasesDict.get(this.om0xList[i]) + this.phasesList[i] = this.phasesList[i - 1] + phasesDict.get(this.om0xList[i]) + this.phasesExprList[i] = this.phasesExprList[i - 1] + "+" + phasesDict.get(this.om0xList[i]) } } } - + draw(canvas) { - for(let i = 0; i < this.om0xList.length-1; i++) { + for(let i = 0; i < this.om0xList.length - 1; i++) { let om0xBegin = canvas.x2px(this.om0xList[i]) - let om0xEnd = canvas.x2px(this.om0xList[i+1]) + let om0xEnd = canvas.x2px(this.om0xList[i + 1]) let baseY = canvas.y2px(this.phasesList[i]) - let nextY = canvas.y2px(this.phasesList[i+1]) + let nextY = canvas.y2px(this.phasesList[i + 1]) canvas.drawLine(om0xBegin, baseY, om0xEnd, baseY) canvas.drawLine(om0xEnd, baseY, om0xEnd, nextY) } - + // Label this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.labelX), canvas.y2px(this.execute(this.labelX))) } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/common.mjs index 9b13fbd..891fdd5 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/common.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/common.mjs @@ -1,25 +1,25 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ -import { getRandomColor, textsub } from "../utils.mjs" +import { getRandomColor } from "../utils.mjs" import Objects from "../module/objects.mjs" import Latex from "../module/latex.mjs" -import {ensureTypeSafety, serializesByPropertyType} from "../parameters.mjs" +import { ensureTypeSafety, serializesByPropertyType } from "../parameters.mjs" // This file contains the default data to be imported from all other objects @@ -32,52 +32,64 @@ export class DrawableObject { * Base name of the object. Needs to be constant over time. * @return {string} Type of the object. */ - static type(){return 'Unknown'} - + static type() { + return "Unknown" + } + /** * Translated name of the object to be shown to the user. * @return {string} */ - static displayType(){return 'Unknown'} - + static displayType() { + return "Unknown" + } + /** * Translated name of the object in plural form to be shown to the user. * @return {string} */ - static displayTypeMultiple(){return 'Unknowns'} - + static displayTypeMultiple() { + return "Unknowns" + } + /** * True if this object can be created by the user, false if it can only * be instantiated by other objects * @return {boolean} */ - static createable() {return true} - + static createable() { + return true + } + /** * List of properties used in the Object Editor. - * + * * Properties are set with key as property name and * value as it's type name (e.g 'numbers', 'string'...), * an Enum for enumerations, an ObjectType for DrawableObjects - * with a specific type, a List instance for lists, a + * with a specific type, a List instance for lists, a * Dictionary instance for dictionaries, an Expression for expressions... - * + * * If the property is to be translated, the key should be passed * through the QT_TRANSLATE_NOOP macro in that form: * [QT_TRANSLATE_NOOP('prop','key')] - * Enums that are translated should be indexed in parameters.mjs and + * Enums that are translated should be indexed in parameters.mjs and * then be linked directly here. - * + * * @return {Object.} */ - static properties() {return {}} - + static properties() { + return {} + } + /** * True if this object can be executed, so that an y value might be computed * for an x value. Only ExecutableObjects have that property set to true. * @return {boolean} */ - static executable() {return false} + static executable() { + return false + } /** * Imports the object from its serialized form. @@ -85,23 +97,23 @@ export class DrawableObject { */ static import(name, visible, color, labelContent, ...args) { let importedArgs = [name.toString(), visible === true, color.toString(), labelContent] - console.log('Importing', this.type(), name, args) + console.log("Importing", this.type(), name, args) for(let [name, propType] of Object.entries(this.properties())) - if(!name.startsWith('comment')) { - importedArgs.push(ensureTypeSafety(propType, args[importedArgs.length-4])) + if(!name.startsWith("comment")) { + importedArgs.push(ensureTypeSafety(propType, args[importedArgs.length - 4])) } return new this(...importedArgs) } - + /** * Base constructor for the object. * @param {string} name - Name of the object * @param {boolean} visible - true if the object is visible, false otherwise. * @param {color|string} color - Color of the object (can be string or QColor) - * @param {'null'|'name'|'name + value'} labelContent - One of 'null', 'name' or 'name + value' describing the content of the label. + * @param {"null"|"name"|"name + value"} labelContent - One of 'null', 'name' or 'name + value' describing the content of the label. * @constructor */ - constructor(name, visible = true, color = null, labelContent = 'name + value') { + constructor(name, visible = true, color = null, labelContent = "name + value") { if(color == null) color = getRandomColor() this.type = this.constructor.type() this.name = name @@ -120,11 +132,11 @@ export class DrawableObject { export() { let exportList = [this.name, this.visible, this.color.toString(), this.labelContent] for(let [name, propType] of Object.entries(this.constructor.properties())) - if(!name.startsWith('comment')) + if(!name.startsWith("comment")) exportList.push(serializesByPropertyType(propType, this[name])) return exportList } - + /** * String representing the object that will be displayed to the user. * It allows for 2 lines and translated text, but it shouldn't be too long. @@ -133,10 +145,10 @@ export class DrawableObject { getReadableString() { return `${this.name} = Unknown` } - + /** * Latex markuped version of the readable string. - * Every non latin character should be passed as latex symbols and formulas + * Every non latin character should be passed as latex symbols and formulas * should be in latex form. * See ../latex.mjs for helper methods. * @return {string} @@ -144,42 +156,42 @@ export class DrawableObject { getLatexString() { return this.getReadableString() } - + /** * Readable string content of the label depending on the value of the latexContent. * @return {string} */ getLabel() { switch(this.labelContent) { - case 'name': + case "name": return this.name - case 'name + value': + case "name + value": return this.getReadableString() - case 'null': - return '' - + case "null": + return "" + } } - + /** * Latex markup string content of the label depending on the value of the latexContent. - * Every non latin character should be passed as latex symbols and formulas + * Every non latin character should be passed as latex symbols and formulas * should be in latex form. * See ../latex.mjs for helper methods. * @return {string} */ getLatexLabel() { switch(this.labelContent) { - case 'name': + case "name": return Latex.variable(this.name) - case 'name + value': + case "name + value": return this.getLatexString() - case 'null': - return '' - + case "null": + return "" + } } - + /** * Returns the recursive list of objects this one depends on. * @return {array} @@ -190,7 +202,7 @@ export class DrawableObject { dependencies = dependencies.concat(obj.getDependenciesList()) return dependencies } - + /** * Callback method when one of the properties of the object is updated. */ @@ -203,8 +215,8 @@ export class DrawableObject { let currentObjectsByName = Objects.currentObjectsByName let properties = this.constructor.properties() for(let property in properties) - if(typeof properties[property] == 'object' && 'type' in properties[property]) - if(properties[property].type === 'Expression' && this[property] != null) { + if(typeof properties[property] == "object" && "type" in properties[property]) + if(properties[property].type === "Expression" && this[property] != null) { // Expressions with dependencies for(let objName of this[property].requiredObjects()) { if(objName in currentObjectsByName && !this.requires.includes(currentObjectsByName[objName])) { @@ -215,8 +227,8 @@ export class DrawableObject { if(this[property].cached && this[property].requiredObjects().length > 0) // Recalculate this[property].recache() - - } else if(properties[property].type === 'ObjectType' && this[property] != null) { + + } else if(properties[property].type === "ObjectType" && this[property] != null) { // Object dependency this.requires.push(this[property]) this[property].requiredBy.push(this) @@ -225,7 +237,7 @@ export class DrawableObject { for(let req of this.requiredBy) req.update() } - + /** * Callback method when the object is about to get deleted. */ @@ -237,64 +249,65 @@ export class DrawableObject { toRemoveFrom.requiredBy = toRemoveFrom.requiredBy.filter(o => o !== this) } } - + /** * Abstract method. Draw the object onto the canvas with the. * @param {CanvasAPI} canvas */ - draw(canvas) {} - + draw(canvas) { + } + /** - * Applicates a drawFunction with two position arguments depending on - * both the posX and posY of where the label should be displayed, + * Applicates a drawFunction with two position arguments depending on + * both the posX and posY of where the label should be displayed, * and the labelPosition which declares the label should be displayed * relatively to that position. - * + * * @param {string|Enum} labelPosition - Position of the label relative to the marked position * @param {number} offset - Margin between the position and the object to be drawn - * @param {Object.} size - Size of the label item, containing two properties, "width" and "height" - * @param {number} posX - Component of the marked position on the x-axis - * @param {number} posY - Component of the marked position on the y-axis - * @param {function} drawFunction - Function with two arguments (x, y) that will be called to draw the label + * @param {{width: number, height: number}} size - Size of the label item, containing two properties, "width" and "height" + * @param {number} posX - Component of the marked position on the x-axis + * @param {number} posY - Component of the marked position on the y-axis + * @param {function} drawFunction - Function with two arguments (x, y) that will be called to draw the label */ drawPositionDivergence(labelPosition, offset, size, posX, posY, drawFunction) { switch(labelPosition) { - case 'center': - drawFunction(posX-size.width/2, posY-size.height/2) - break; - case 'top': - case 'above': - drawFunction(posX-size.width/2, posY-size.height-offset) - break; - case 'bottom': - case 'below': - drawFunction(posX-size.width/2, posY+offset) - break; - case 'left': - drawFunction(posX-size.width-offset, posY-size.height/2) - break; - case 'right': - drawFunction(posX+offset, posY-size.height/2) - break; - case 'top-left': - case 'above-left': - drawFunction(posX-size.width, posY-size.height-offset) - break; - case 'top-right': - case 'above-right': - drawFunction(posX+offset, posY-size.height-offset) - break; - case 'bottom-left': - case 'below-left': - drawFunction(posX-size.width-offset, posY+offset) - break; - case 'bottom-right': - case 'below-right': - drawFunction(posX+offset, posY+offset) - break; + case "center": + drawFunction(posX - size.width / 2, posY - size.height / 2) + break + case "top": + case "above": + drawFunction(posX - size.width / 2, posY - size.height - offset) + break + case "bottom": + case "below": + drawFunction(posX - size.width / 2, posY + offset) + break + case "left": + drawFunction(posX - size.width - offset, posY - size.height / 2) + break + case "right": + drawFunction(posX + offset, posY - size.height / 2) + break + case "top-left": + case "above-left": + drawFunction(posX - size.width, posY - size.height - offset) + break + case "top-right": + case "above-right": + drawFunction(posX + offset, posY - size.height - offset) + break + case "bottom-left": + case "below-left": + drawFunction(posX - size.width - offset, posY + offset) + break + case "bottom-right": + case "below-right": + drawFunction(posX + offset, posY + offset) + break } } - + /** * Automatically draw text (by default the label of the object on the canvas * depending on user settings. @@ -304,55 +317,54 @@ export class DrawableObject { * depending on whether to use latex. * Then, it's displayed using the drawFunctionLatex (x,y,imageData) and * drawFunctionText (x,y,text) depending on whether to use latex. - * + * * @param {CanvasAPI} canvas * @param {string|Enum} labelPosition - Position of the label relative to the marked position - * @param {number} posX - Component of the marked position on the x-axis - * @param {number} posY - Component of the marked position on the y-axis + * @param {number} posX - Component of the marked position on the x-axis + * @param {number} posY - Component of the marked position on the y-axis * @param {boolean} forceText - Force the rendering of the label as text * @param {function|null} getLatexFunction - Function (no argument) to get the latex markup to be displayed * @param {function|null} getTextFunction - Function (no argument) to get the text to be displayed * @param {function|null} drawFunctionLatex - Function (x,y,imageData) to display the latex image * @param {function|null} drawFunctionText - Function (x,y,text,textSize) to display the text */ - drawLabel(canvas, labelPosition, posX, posY,forceText = false, - getLatexFunction = null, getTextFunction = null, drawFunctionLatex = null, drawFunctionText = null) { + drawLabel(canvas, labelPosition, posX, posY, forceText = false, + getLatexFunction = null, getTextFunction = null, drawFunctionLatex = null, drawFunctionText = null) { // Default functions if(getLatexFunction == null) getLatexFunction = this.getLatexLabel.bind(this) if(getTextFunction == null) getTextFunction = this.getLabel.bind(this) if(drawFunctionLatex == null) - drawFunctionLatex = (x,y,ltxImg) => canvas.drawVisibleImage(ltxImg.source, x, y, ltxImg.width, ltxImg.height) + drawFunctionLatex = (x, y, ltxImg) => canvas.drawVisibleImage(ltxImg.source, x, y, ltxImg.width, ltxImg.height) if(drawFunctionText == null) - drawFunctionText = (x,y,text,textSize) => canvas.drawVisibleText(text, x, y+textSize.height) // Positioned from left bottom + drawFunctionText = (x, y, text, textSize) => canvas.drawVisibleText(text, x, y + textSize.height) // Positioned from left bottom // Drawing the label - let offset if(!forceText && Latex.enabled) { // With latex let drawLblCb = ((ltxImg) => { - this.drawPositionDivergence(labelPosition, 8+canvas.linewidth/2, ltxImg, posX, posY, (x,y) => drawFunctionLatex(x,y,ltxImg)) - }).bind(this) - let ltxLabel = getLatexFunction(); + this.drawPositionDivergence(labelPosition, 8 + canvas.linewidth / 2, ltxImg, posX, posY, (x, y) => drawFunctionLatex(x, y, ltxImg)) + }) + let ltxLabel = getLatexFunction() if(ltxLabel !== "") - canvas.renderLatexImage(ltxLabel, this.color, drawLblCb.bind(this)) + canvas.renderLatexImage(ltxLabel, this.color, drawLblCb) } else { // Without latex let text = getTextFunction() canvas.font = `${canvas.textsize}px sans-serif` let textSize = canvas.measureText(text) - this.drawPositionDivergence(labelPosition, 8+canvas.linewidth/2, textSize, posX, posY, (x,y) => drawFunctionText(x,y,text,textSize)) + this.drawPositionDivergence(labelPosition, 8 + canvas.linewidth / 2, textSize, posX, posY, (x, y) => drawFunctionText(x, y, text, textSize)) } } - + toString() { - return this.name; + return this.name } } /** - * Class to be extended for every object on which + * Class to be extended for every object on which * an y for a x can be computed with the execute function. * If a value cannot be found during execute, it will * return null. However, theses same x values will @@ -363,32 +375,42 @@ export class ExecutableObject extends DrawableObject { * Returns the corresponding y value for an x value. * If the object isn't defined on the given x, then * this function will return null. - * + * * @param {number} x * @returns {number|null} */ - execute(x = 1) {return 0} + execute(x = 1) { + return 0 + } + /** * Returns false if the object isn't defined on the given x, true otherwise. - * + * * @param {number} x * @returns {boolean} */ - canExecute(x = 1) {return true} + canExecute(x = 1) { + return true + } + /** * Returns the simplified expression string for a given x. - * + * * @param {number} x * @returns {string|Expression} */ - simplify(x = 1) {return '0'} - + simplify(x = 1) { + return "0" + } + /** * True if this object can be executed, so that an y value might be computed * for an x value. Only ExecutableObjects have that property set to true. * @return {boolean} */ - static executable() {return true} + static executable() { + return true + } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/distribution.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/distribution.mjs index 411e191..16aa4d4 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/distribution.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/distribution.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -24,18 +24,30 @@ import { ExecutableObject } from "./common.mjs" export default class DistributionFunction extends ExecutableObject { - static type(){return 'Repartition'} - static displayType(){return qsTranslate("distribution", 'Repartition')} - static displayTypeMultiple(){return qsTranslate("distribution", 'Repartition functions')} - static properties() {return { - 'comment1': QT_TRANSLATE_NOOP( - 'comment', - 'Note: Specify the probability for each value.' - ), - [QT_TRANSLATE_NOOP('prop','probabilities')]: new P.Dictionary('string', 'double', /^-?[\d.,]+$/, /^-?[\d.,]+$/, 'P({name_} = ', ') = '), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - }} + static type() { + return "Repartition" + } + + static displayType() { + return qsTranslate("distribution", "Repartition") + } + + static displayTypeMultiple() { + return qsTranslate("distribution", "Repartition functions") + } + + static properties() { + return { + "comment1": QT_TRANSLATE_NOOP( + "comment", + "Note: Specify the probability for each value." + ), + [QT_TRANSLATE_NOOP("prop", "probabilities")]: new P.Dictionary("string", "double", /^-?[\d.,]+$/, /^-?[\d.,]+$/, "P({name_} = ", ") = "), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number" + } + } + static import(name, visible, color, labelContent, ...args) { console.log(args, args.length) if(args.length === 5) { @@ -45,99 +57,101 @@ export default class DistributionFunction extends ExecutableObject { } return super.import(name, visible, color, labelContent, ...args) } - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - probabilities = {'0': '0'}, labelPosition = 'above', labelX = 1) { - if(name == null) name = Objects.getNewName('XYZUVW', "F_") + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + probabilities = { "0": "0" }, labelPosition = "above", labelX = 1) { + if(name == null) name = Objects.getNewName("XYZUVW", "F_") super(name, visible, color, labelContent) this.probabilities = probabilities this.labelPosition = labelPosition this.labelX = labelX this.update() } - + getReadableString() { - let keys = Object.keys(this.probabilities).sort((a,b) => a-b); - let varname = this.name.substring(this.name.indexOf("_")+1) + let keys = Object.keys(this.probabilities).sort((a, b) => a - b) + let varname = this.name.substring(this.name.indexOf("_") + 1) return `${this.name}(x) = P(${varname} ≤ x)\n` + keys.map(idx => `P(${varname}=${idx})=${this.probabilities[idx]}`).join("; ") } - + getLatexString() { - let keys = Object.keys(this.probabilities).sort((a,b) => a-b); + let keys = Object.keys(this.probabilities).sort((a, b) => a - b) let funcName = Latex.variable(this.name) - let varName = Latex.variable(this.name.substring(this.name.indexOf("_")+1)) - return `\\begin{array}{l}{${funcName}}(x) = P(${varName} \\le x)\\\\` + keys.map(idx => `P(${varName}=${idx})=${this.probabilities[idx]}`).join("; ") + '\\end{array}' + let varName = Latex.variable(this.name.substring(this.name.indexOf("_") + 1)) + return `\\begin{array}{l}{${funcName}}(x) = P(${varName} \\le x)\\\\` + keys.map(idx => `P(${varName}=${idx})=${this.probabilities[idx]}`).join("; ") + "\\end{array}" } - + execute(x = 1) { - let ret = 0; - Object.keys(this.probabilities).sort((a,b) => a-b).forEach(idx => { - if(x >= idx) ret += parseFloat(this.probabilities[idx].replace(/,/g, '.')) + let ret = 0 + Object.keys(this.probabilities).sort((a, b) => a - b).forEach(idx => { + if(x >= idx) ret += parseFloat(this.probabilities[idx].replace(/,/g, ".")) }) return ret } - - canExecute(x = 1) {return true} + + canExecute(x = 1) { + return true + } // Simplify returns the simplified string of the expression. simplify(x = 1) { return this.execute(x).toString() } - + getLabel() { switch(this.labelContent) { - case 'name': + case "name": return `${this.name}(x)` - case 'name + value': + case "name + value": return this.getReadableString() - case 'null': - return '' + case "null": + return "" } } - + draw(canvas) { - let currentY = 0; - let keys = Object.keys(this.probabilities).map(idx => parseInt(idx)).sort((a,b) => a-b) - if(canvas.isVisible(keys[0],this.probabilities[keys[0]].replace(/,/g, '.'))) { + let currentY = 0 + let keys = Object.keys(this.probabilities).map(idx => parseInt(idx)).sort((a, b) => a - b) + if(canvas.isVisible(keys[0], this.probabilities[keys[0]].replace(/,/g, "."))) { canvas.drawLine(0, canvas.y2px(0), canvas.x2px(keys[0]), canvas.y2px(0)) - if(canvas.isVisible(keys[0],0)) { - canvas.arc(canvas.x2px(keys[0])+4,canvas.y2px(0), 4, Math.PI / 2, 3 * Math.PI / 2); + if(canvas.isVisible(keys[0], 0)) { + canvas.arc(canvas.x2px(keys[0]) + 4, canvas.y2px(0), 4, Math.PI / 2, 3 * Math.PI / 2) } } - for(let i = 0; i < keys.length-1; i++) { - let idx = keys[i]; - currentY += parseFloat(this.probabilities[idx].replace(/,/g, '.')); - if(canvas.isVisible(idx,currentY) || canvas.isVisible(keys[i+1],currentY)) { + for(let i = 0; i < keys.length - 1; i++) { + let idx = keys[i] + currentY += parseFloat(this.probabilities[idx].replace(/,/g, ".")) + if(canvas.isVisible(idx, currentY) || canvas.isVisible(keys[i + 1], currentY)) { canvas.drawLine( - Math.max(0,canvas.x2px(idx)), + Math.max(0, canvas.x2px(idx)), canvas.y2px(currentY), - Math.min(canvas.width,canvas.x2px(keys[i+1])), + Math.min(canvas.width, canvas.x2px(keys[i + 1])), canvas.y2px(currentY) ) - if(canvas.isVisible(idx,currentY)) { + if(canvas.isVisible(idx, currentY)) { canvas.disc(canvas.x2px(idx), canvas.y2px(currentY), 4) } - if(canvas.isVisible(keys[i+1],currentY)) { - canvas.arc(canvas.x2px(keys[i+1])+4,canvas.y2px(currentY), 4, Math.PI / 2, 3 * Math.PI / 2); + if(canvas.isVisible(keys[i + 1], currentY)) { + canvas.arc(canvas.x2px(keys[i + 1]) + 4, canvas.y2px(currentY), 4, Math.PI / 2, 3 * Math.PI / 2) } } } - if(canvas.isVisible(keys[keys.length-1],currentY+parseFloat(this.probabilities[keys[keys.length-1]]))) { + if(canvas.isVisible(keys[keys.length - 1], currentY + parseFloat(this.probabilities[keys[keys.length - 1]]))) { canvas.drawLine( - Math.max(0,canvas.x2px(keys[keys.length-1])), - canvas.y2px(currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.'))), + Math.max(0, canvas.x2px(keys[keys.length - 1])), + canvas.y2px(currentY + parseFloat(this.probabilities[keys[keys.length - 1]].replace(/,/g, "."))), canvas.width, - canvas.y2px(currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.'))) + canvas.y2px(currentY + parseFloat(this.probabilities[keys[keys.length - 1]].replace(/,/g, "."))) ) canvas.disc( - canvas.x2px(keys[keys.length-1]), + canvas.x2px(keys[keys.length - 1]), canvas.y2px( - currentY+parseFloat(this.probabilities[keys[keys.length-1]].replace(/,/g, '.')) + currentY + parseFloat(this.probabilities[keys[keys.length - 1]].replace(/,/g, ".")) ), 4 ) } - + // Label this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.labelX), canvas.y2px(this.execute(this.labelX))) } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/function.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/function.mjs index 84cf45c..1e345cb 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/function.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/function.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -25,39 +25,50 @@ import Latex from "../module/latex.mjs" export default class Function extends ExecutableObject { - static type(){return 'Function'} - static displayType(){return qsTranslate("function", 'Function')} - static displayTypeMultiple(){return qsTranslate("function", 'Functions')} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','expression')]: new P.Expression('x'), - [QT_TRANSLATE_NOOP('prop','definitionDomain')]: 'Domain', - [QT_TRANSLATE_NOOP('prop','destinationDomain')]: 'Domain', - 'comment1': QT_TRANSLATE_NOOP( - 'comment', - 'Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5}' - ), - [QT_TRANSLATE_NOOP('prop','displayMode')]: P.Enum.FunctionDisplayType, - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - 'comment2': QT_TRANSLATE_NOOP( - 'comment', - 'The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...)' - ), - [QT_TRANSLATE_NOOP('prop','drawPoints')]: 'boolean', - [QT_TRANSLATE_NOOP('prop','drawDashedLines')]: 'boolean' - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - expression = 'x', definitionDomain = 'RPE', destinationDomain = 'R', - displayMode = 'application', labelPosition = 'above', labelX = 1, - drawPoints = true, drawDashedLines = true) { - if(name == null) name = Objects.getNewName('fghjqlmnopqrstuvwabcde') + static type() { + return "Function" + } + + static displayType() { + return qsTranslate("function", "Function") + } + + static displayTypeMultiple() { + return qsTranslate("function", "Functions") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "expression")]: new P.Expression("x"), + [QT_TRANSLATE_NOOP("prop", "definitionDomain")]: "Domain", + [QT_TRANSLATE_NOOP("prop", "destinationDomain")]: "Domain", + "comment1": QT_TRANSLATE_NOOP( + "comment", + "Ex: R+* (ℝ⁺*), N (ℕ), Z-* (ℤ⁻*), ]0;1[, {3;4;5}" + ), + [QT_TRANSLATE_NOOP("prop", "displayMode")]: P.Enum.FunctionDisplayType, + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number", + "comment2": QT_TRANSLATE_NOOP( + "comment", + "The following parameters are used when the definition domain is a non-continuous set. (Ex: ℕ, ℤ, sets like {0;3}...)" + ), + [QT_TRANSLATE_NOOP("prop", "drawPoints")]: "boolean", + [QT_TRANSLATE_NOOP("prop", "drawDashedLines")]: "boolean" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + expression = "x", definitionDomain = "RPE", destinationDomain = "R", + displayMode = "application", labelPosition = "above", labelX = 1, + drawPoints = true, drawDashedLines = true) { + if(name == null) name = Objects.getNewName("fghjqlmnopqrstuvwabcde") super(name, visible, color, labelContent) - if(typeof expression == 'number' || typeof expression == 'string') expression = new Expression(expression.toString()) + if(typeof expression == "number" || typeof expression == "string") expression = new Expression(expression.toString()) this.expression = expression - if(typeof definitionDomain == 'string') definitionDomain = parseDomain(definitionDomain) + if(typeof definitionDomain == "string") definitionDomain = parseDomain(definitionDomain) this.definitionDomain = definitionDomain - if(typeof destinationDomain == 'string') destinationDomain = parseDomain(destinationDomain) + if(typeof destinationDomain == "string") destinationDomain = parseDomain(destinationDomain) this.destinationDomain = destinationDomain this.displayMode = displayMode this.labelPosition = labelPosition @@ -65,17 +76,17 @@ export default class Function extends ExecutableObject { this.drawPoints = drawPoints this.drawDashedLines = drawDashedLines } - + getReadableString() { - if(this.displayMode === 'application') { - return `${this.name}: ${this.definitionDomain} ⟶ ${this.destinationDomain}\n ${' '.repeat(this.name.length)}x ⟼ ${this.expression.toString()}` + if(this.displayMode === "application") { + return `${this.name}: ${this.definitionDomain} ⟶ ${this.destinationDomain}\n ${" ".repeat(this.name.length)}x ⟼ ${this.expression.toString()}` } else { return `${this.name}(x) = ${this.expression.toString()}\nD${textsub(this.name)} = ${this.definitionDomain}` } } - + getLatexString() { - if(this.displayMode === 'application') { + if(this.displayMode === "application") { return `${Latex.variable(this.name)}:\\begin{array}{llll}${this.definitionDomain.latexMarkup}\\textrm{ } & \\rightarrow & \\textrm{ }${this.destinationDomain.latexMarkup}\\\\ x\\textrm{ } & \\mapsto & \\textrm{ }${this.expression.latexMarkup}\\end{array}` } else { @@ -88,17 +99,17 @@ export default class Function extends ExecutableObject { return this.expression.execute(x) return null } - + canExecute(x = 1) { return this.definitionDomain.includes(x) } - + simplify(x = 1) { if(this.definitionDomain.includes(x)) return this.expression.simplify(x) - return '' + return "" } - + draw(canvas) { Function.drawFunction(canvas, this.expression, this.definitionDomain, this.destinationDomain, this.drawPoints, this.drawDashedLines) // Label @@ -112,7 +123,7 @@ export default class Function extends ExecutableObject { static drawFunction(canvas, expr, definitionDomain, destinationDomain, drawPoints = true, drawDash = true) { let pxprecision = 10 let previousX = canvas.px2x(0) - let previousY = null; + let previousY = null if(definitionDomain instanceof SpecialDomain && definitionDomain.moveSupported) { // Point based functions. previousX = definitionDomain.next(previousX) @@ -121,16 +132,16 @@ export default class Function extends ExecutableObject { if(!drawPoints && !drawDash) return while(previousX !== null && canvas.x2px(previousX) < canvas.width) { // Reconverted for canvas to fix for logarithmic scales. - let currentX = definitionDomain.next(canvas.px2x(canvas.x2px(previousX)+pxprecision)); + let currentX = definitionDomain.next(canvas.px2x(canvas.x2px(previousX) + pxprecision)) let currentY = expr.execute(currentX) - if(currentX === null) break; + if(currentX === null) break if((definitionDomain.includes(currentX) || definitionDomain.includes(previousX)) && (destinationDomain.includes(currentY) || destinationDomain.includes(previousY))) { if(drawDash) canvas.drawDashedLine(canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY)) if(drawPoints) { - canvas.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2) - canvas.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10) + canvas.fillRect(canvas.x2px(previousX) - 5, canvas.y2px(previousY) - 1, 10, 2) + canvas.fillRect(canvas.x2px(previousX) - 1, canvas.y2px(previousY) - 5, 2, 10) } } previousX = currentX @@ -138,8 +149,8 @@ export default class Function extends ExecutableObject { } if(drawPoints) { // Drawing the last cross - canvas.fillRect(canvas.x2px(previousX)-5, canvas.y2px(previousY)-1, 10, 2) - canvas.fillRect(canvas.x2px(previousX)-1, canvas.y2px(previousY)-5, 2, 10) + canvas.fillRect(canvas.x2px(previousX) - 5, canvas.y2px(previousY) - 1, 10, 2) + canvas.fillRect(canvas.x2px(previousX) - 1, canvas.y2px(previousY) - 5, 2, 10) } } else { // Use max precision if function is trigonometrical on log scale. @@ -154,9 +165,9 @@ export default class Function extends ExecutableObject { if(!definitionDomain.includes(previousX) && definitionDomain.includes(currentX)) { // Should draw up to currentX, but NOT at previousX. // Need to find the starting point. - let tmpPx = px-pxprecision + let tmpPx = px - pxprecision do { - tmpPx++; + tmpPx++ previousX = canvas.px2x(tmpPx) } while(!definitionDomain.includes(previousX)) // Recaclulate previousY @@ -166,16 +177,16 @@ export default class Function extends ExecutableObject { // Augmenting the pixel precision until this condition is fulfilled. let tmpPx = px do { - tmpPx--; + tmpPx-- currentX = canvas.px2x(tmpPx) } while(!definitionDomain.includes(currentX) && currentX !== previousX) } // This max variation is needed for functions with asymptotical vertical lines (e.g. 1/x, tan x...) - let maxvariation = (canvas.px2y(0)-canvas.px2y(canvas.height)) + let maxvariation = (canvas.px2y(0) - canvas.px2y(canvas.height)) if(definitionDomain.includes(previousX) && definitionDomain.includes(currentX)) { let currentY = expr.execute(currentX) if(destinationDomain.includes(currentY)) { - if(previousY != null && destinationDomain.includes(previousY) && Math.abs(previousY-currentY) < maxvariation) { + if(previousY != null && destinationDomain.includes(previousY) && Math.abs(previousY - currentY) < maxvariation) { canvas.drawLine(canvas.x2px(previousX), canvas.y2px(previousY), canvas.x2px(currentX), canvas.y2px(currentY)) } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/point.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/point.mjs index 2c07836..d179481 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/point.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/point.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -24,53 +24,63 @@ import Latex from "../module/latex.mjs" import { DrawableObject } from "./common.mjs" -export default class Point extends DrawableObject { - static type(){return 'Point'} - static displayType(){return qsTranslate("point", 'Point')} - static displayTypeMultiple(){return qsTranslate("point", 'Points')} - - static properties() {return { - [QT_TRANSLATE_NOOP('prop','x')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','y')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','pointStyle')]: new P.Enum('●', '✕', '+') - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - x = 1, y = 0, labelPosition = 'above', pointStyle = '●') { - if(name == null) name = Objects.getNewName('ABCDEFJKLMNOPQRSTUVW') +export default class Point extends DrawableObject { + static type() { + return "Point" + } + + static displayType() { + return qsTranslate("point", "Point") + } + + static displayTypeMultiple() { + return qsTranslate("point", "Points") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "x")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "y")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "pointStyle")]: new P.Enum("●", "✕", "+") + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + x = 1, y = 0, labelPosition = "above", pointStyle = "●") { + if(name == null) name = Objects.getNewName("ABCDEFJKLMNOPQRSTUVW") super(name, visible, color, labelContent) - if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString()) + if(typeof x == "number" || typeof x == "string") x = new Expression(x.toString()) this.x = x - if(typeof y == 'number' || typeof y == 'string') y = new Expression(y.toString()) + if(typeof y == "number" || typeof y == "string") y = new Expression(y.toString()) this.y = y this.labelPosition = labelPosition this.pointStyle = pointStyle } - + getReadableString() { return `${this.name} = (${this.x}, ${this.y})` } - + getLatexString() { return `${Latex.variable(this.name)} = \\left(${this.x.latexMarkup}, ${this.y.latexMarkup}\\right)` } - + draw(canvas) { let [canvasX, canvasY] = [canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute())] - let pointSize = 8+(canvas.linewidth*2) + let pointSize = 8 + (canvas.linewidth * 2) switch(this.pointStyle) { - case '●': - canvas.disc(canvasX, canvasY, pointSize/2) - break; - case '✕': - canvas.drawLine(canvasX-pointSize/2, canvasY-pointSize/2, canvasX+pointSize/2, canvasY+pointSize/2) - canvas.drawLine(canvasX-pointSize/2, canvasY+pointSize/2, canvasX+pointSize/2, canvasY-pointSize/2) - break; - case '+': - canvas.fillRect(canvasX-pointSize/2, canvasY-1, pointSize, 2) - canvas.fillRect(canvasX-1, canvasY-pointSize/2, 2, pointSize) - break; + case "●": + canvas.disc(canvasX, canvasY, pointSize / 2) + break + case "✕": + canvas.drawLine(canvasX - pointSize / 2, canvasY - pointSize / 2, canvasX + pointSize / 2, canvasY + pointSize / 2) + canvas.drawLine(canvasX - pointSize / 2, canvasY + pointSize / 2, canvasX + pointSize / 2, canvasY - pointSize / 2) + break + case "+": + canvas.fillRect(canvasX - pointSize / 2, canvasY - 1, pointSize, 2) + canvas.fillRect(canvasX - 1, canvasY - pointSize / 2, 2, pointSize) + break } this.drawLabel(canvas, this.labelPosition, canvasX, canvasY) } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/sequence.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/sequence.mjs index 310444e..0328041 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/sequence.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/sequence.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -26,27 +26,37 @@ import Function from "./function.mjs" export default class Sequence extends ExecutableObject { - static type(){return 'Sequence'} - static displayType(){return qsTranslate("sequence", 'Sequence')} - static displayTypeMultiple(){return qsTranslate("sequence", 'Sequences')} - - static properties() {return { - [QT_TRANSLATE_NOOP('prop','drawPoints')]: 'boolean', - [QT_TRANSLATE_NOOP('prop','drawDashedLines')]: 'boolean', - [QT_TRANSLATE_NOOP('prop','defaultExpression')]: new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[n+', '] = ', true), - 'comment1': QT_TRANSLATE_NOOP( - 'comment', - 'Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁...' - ), - [QT_TRANSLATE_NOOP('prop','baseValues')]: new P.Dictionary('string', 'int', /^.+$/, /^\d+$/, '{name}[', '] = '), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Position, - [QT_TRANSLATE_NOOP('prop','labelX')]: 'number', - }} - - constructor(name = null, visible = true, color = null, labelContent = 'name + value', - drawPoints = true, drawDashedLines = true, defaultExp = {1: "n"}, - baseValues = {0: 0}, labelPosition = 'above', labelX = 1) { - if(name == null) name = Objects.getNewName('uvwPSUVWabcde') + static type() { + return "Sequence" + } + + static displayType() { + return qsTranslate("sequence", "Sequence") + } + + static displayTypeMultiple() { + return qsTranslate("sequence", "Sequences") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "drawPoints")]: "boolean", + [QT_TRANSLATE_NOOP("prop", "drawDashedLines")]: "boolean", + [QT_TRANSLATE_NOOP("prop", "defaultExpression")]: new P.Dictionary("string", "int", /^.+$/, /^\d+$/, "{name}[n+", "] = ", true), + "comment1": QT_TRANSLATE_NOOP( + "comment", + "Note: Use %1[n] to refer to %1ₙ, %1[n+1] for %1ₙ₊₁..." + ), + [QT_TRANSLATE_NOOP("prop", "baseValues")]: new P.Dictionary("string", "int", /^.+$/, /^\d+$/, "{name}[", "] = "), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Position, + [QT_TRANSLATE_NOOP("prop", "labelX")]: "number" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "name + value", + drawPoints = true, drawDashedLines = true, defaultExp = { 1: "n" }, + baseValues = { 0: 0 }, labelPosition = "above", labelX = 1) { + if(name == null) name = Objects.getNewName("uvwPSUVWabcde") super(name, visible, color, labelContent) this.drawPoints = drawPoints this.drawDashedLines = drawDashedLines @@ -58,68 +68,71 @@ export default class Sequence extends ExecutableObject { } update() { - console.log('Updating sequence', this.sequence) + console.log("Updating sequence", this.sequence) super.update() if( this.sequence == null || this.baseValues !== this.sequence.baseValues || this.sequence.name !== this.name || this.sequence.expr !== Object.values(this.defaultExpression)[0] || - this.sequence.valuePlus !== Object.keys(this.defaultExpression)[0] + this.sequence.valuePlus.toString() !== Object.keys(this.defaultExpression)[0] ) this.sequence = new MathSequence( - this.name, this.baseValues, - Object.keys(this.defaultExpression)[0], + this.name, this.baseValues, + parseFloat(Object.keys(this.defaultExpression)[0]), Object.values(this.defaultExpression)[0] ) } - + getReadableString() { return this.sequence.toString() } - + getLatexString() { return this.sequence.toLatexString() } - + execute(x = 1) { if(x % 1 === 0) return this.sequence.execute(x) return null } - canExecute(x = 1) {return x%1 === 0} - + + canExecute(x = 1) { + return x % 1 === 0 + } + // Simplify returns the simplified string of the expression. simplify(x = 1) { if(x % 1 === 0) return this.sequence.simplify(x) return null } - + getLabel() { switch(this.labelContent) { - case 'name': + case "name": return `(${this.name}ₙ)` - case 'name + value': + case "name + value": return this.getReadableString() - case 'null': - return '' + case "null": + return "" } } - + getLatexLabel() { switch(this.labelContent) { - case 'name': + case "name": return `(${Latex.variable(this.name)}_n)` - case 'name + value': + case "name + value": return this.getLatexString() - case 'null': - return '' + case "null": + return "" } } - + draw(canvas) { Function.drawFunction(canvas, this.sequence, canvas.logscalex ? Domain.NE : Domain.N, Domain.R, this.drawPoints, this.drawDashedLines) - + // Label this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.labelX), canvas.y2px(this.execute(this.labelX))) } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/text.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/text.mjs index e7f7a05..af79824 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/text.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/text.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -24,72 +24,85 @@ import Latex from "../module/latex.mjs" import { DrawableObject } from "./common.mjs" -export default class Text extends DrawableObject { - static type(){return 'Text'} - static displayType(){return qsTranslate("text", 'Text')} - static displayTypeMultiple(){return qsTranslate("text", 'Texts')} - static properties() {return { - [QT_TRANSLATE_NOOP('prop','x')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','y')]: new P.Expression(), - [QT_TRANSLATE_NOOP('prop','labelPosition')]: P.Enum.Positioning, - [QT_TRANSLATE_NOOP('prop','text')]: 'string', - 'comment1': QT_TRANSLATE_NOOP( - 'comment', - 'If you have latex enabled, you can use use latex markup in between $$ to create equations.' - ), - [QT_TRANSLATE_NOOP('prop','disableLatex')]: 'boolean' - }} - - constructor(name = null, visible = true, color = null, labelContent = 'null', - x = 1, y = 0, labelPosition = 'center', text = 'New text', disableLatex = false) { - if(name == null) name = Objects.getNewName('t') +export default class Text extends DrawableObject { + static type() { + return "Text" + } + + static displayType() { + return qsTranslate("text", "Text") + } + + static displayTypeMultiple() { + return qsTranslate("text", "Texts") + } + + static properties() { + return { + [QT_TRANSLATE_NOOP("prop", "x")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "y")]: new P.Expression(), + [QT_TRANSLATE_NOOP("prop", "labelPosition")]: P.Enum.Positioning, + [QT_TRANSLATE_NOOP("prop", "text")]: "string", + "comment1": QT_TRANSLATE_NOOP( + "comment", + "If you have latex enabled, you can use use latex markup in between $$ to create equations." + ), + [QT_TRANSLATE_NOOP("prop", "disableLatex")]: "boolean" + } + } + + constructor(name = null, visible = true, color = null, labelContent = "null", + x = 1, y = 0, labelPosition = "center", text = "New text", disableLatex = false) { + if(name == null) name = Objects.getNewName("t") super(name, visible, color, labelContent) - if(typeof x == 'number' || typeof x == 'string') x = new Expression(x.toString()) + if(typeof x == "number" || typeof x == "string") x = new Expression(x.toString()) this.x = x - if(typeof y == 'number' || typeof y == 'string') y = new Expression(y.toString()) + if(typeof y == "number" || typeof y == "string") y = new Expression(y.toString()) this.y = y this.labelPosition = labelPosition this.text = text this.disableLatex = disableLatex } - + getReadableString() { return `${this.name} = "${this.text}"` } - + latexMarkupText() { // Check whether the text contains latex escaped elements. let txt = [] - this.text.split('$$').forEach(function(t) { txt = txt.concat(Latex.variable(t, true).replace(/\$\$/g, '').split('$')) }) + this.text.split("$$").forEach(function(t) { + txt = txt.concat(Latex.variable(t, true).replace(/\$\$/g, "").split("$")) + }) let newTxt = txt[0] let i // Split between normal text and latex escaped. - for(i = 0; i < txt.length-1; i++) + for(i = 0; i < txt.length - 1; i++) if(i & 0x01) // Every odd number - newTxt += '\\textsf{'+Latex.variable(txt[i+1]) + newTxt += "\\textsf{" + Latex.variable(txt[i + 1]) else - newTxt += '}'+txt[i+1] + newTxt += "}" + txt[i + 1] // Finished by a } - if(i & 0x01) + if(i & 0x01) newTxt += "{" return newTxt } - + getLatexString() { return `${Latex.variable(this.name)} = "\\textsf{${this.latexMarkupText()}}"` } - + getLabel() { return this.text } - + getLatexLabel() { return `\\textsf{${this.latexMarkupText()}}` } - + draw(canvas) { - let yOffset = this.disableLatex ? canvas.textsize-4 : 0 - this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute())+yOffset, this.disableLatex) + let yOffset = this.disableLatex ? canvas.textsize - 4 : 0 + this.drawLabel(canvas, this.labelPosition, canvas.x2px(this.x.execute()), canvas.y2px(this.y.execute()) + yOffset, this.disableLatex) } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/xcursor.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/xcursor.mjs index 7c6d422..11f6a5a 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/xcursor.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/objs/xcursor.mjs @@ -72,30 +72,29 @@ export default class XCursor extends DrawableObject { ${this.getTargetValueLatexLabel()} \\end{array}` } - - getTargetValueLabel() { - var t = this.targetElement - var approx = '' + + getApprox() { + let approx = '' if(this.approximate) { - approx = (t.execute(this.x.execute())) + approx = (this.targetElement.execute(this.x.execute())) let intLength = Math.round(approx).toString().length let rounding = Math.min(this.rounding, approx.toString().length - intLength - 1) approx = approx.toPrecision(rounding + intLength) } + return approx + } + + getTargetValueLabel() { + const t = this.targetElement + const approx = this.getApprox() return `${t.name}(${this.name}) = ${t.simplify(this.x.toEditableString())}` + (this.approximate ? ' ≈ ' + approx : '') } getTargetValueLatexLabel() { - let t = this.targetElement - let approx = '' - if(this.approximate) { - approx = (t.execute(this.x.execute())) - let intLength = Math.round(approx).toString().length - let rounding = Math.min(this.rounding, approx.toString().length - intLength - 1) - approx = approx.toPrecision(rounding + intLength) - } - let simpl = t.simplify(this.x.toEditableString()) + const t = this.targetElement + const approx = this.getApprox() + const simpl = t.simplify(this.x.toEditableString()) return `${Latex.variable(t.name)}(${Latex.variable(this.name)}) = ${simpl.latexMarkup ? simpl.latexMarkup : Latex.variable(simpl)}` + (this.approximate ? ' \\simeq ' + approx : '') } @@ -104,16 +103,13 @@ export default class XCursor extends DrawableObject { switch(this.labelContent) { case 'name': return this.name - break; case 'name + value': switch(this.targetValuePosition) { case 'Next to target': case 'Hidden': return `${this.name} = ${this.x.toString()}` - break; case 'With label': return this.getReadableString() - break; } case 'null': return '' @@ -124,16 +120,13 @@ export default class XCursor extends DrawableObject { switch(this.labelContent) { case 'name': return Latex.variable(this.name) - break; case 'name + value': switch(this.targetValuePosition) { case 'Next to target': case 'Hidden': return `${Latex.variable(this.name)} = ${this.x.latexMarkup}` - break; case 'With label': return this.getLatexString() - break; } case 'null': return '' diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parameters.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parameters.mjs index b301997..1078518 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parameters.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parameters.mjs @@ -15,15 +15,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -import {parseDomain, Expression as Expr, Domain} from "./math/index.mjs" +import { parseDomain, Expression as Expr, Domain } from "./math/index.mjs" import Objects from "./module/objects.mjs" -const NONE = class Empty {} +const NONE = class Empty { +} let stringValuesValidators = { - 'int': [parseInt, (x) => !isNaN(x)], - 'double': [parseFloat, (x) => !isNaN(x)], - 'string': [(x) => x, () => true] + "int": [parseInt, (x) => !isNaN(x)], + "double": [parseFloat, (x) => !isNaN(x)], + "string": [(x) => x, () => true] } let stringValidatorTypes = Object.keys(stringValuesValidators) @@ -52,17 +53,17 @@ class PropertyType { export class Expression extends PropertyType { constructor(...variables) { super() - this.type = 'Expression' + this.type = "Expression" this.variables = variables } - + toString() { - return this.variables.length === 0 ? 'Number' : `Expression(${this.variables.join(', ')})` + return this.variables.length === 0 ? "Number" : `Expression(${this.variables.join(", ")})` } parse(value) { let result = NONE - if(typeof value == 'string') + if(typeof value == "string") try { result = new Expr(value) } catch(e) { @@ -86,14 +87,14 @@ export class Expression extends PropertyType { export class Enum extends PropertyType { constructor(...values) { super() - this.type = 'Enum' + this.type = "Enum" this.values = values this.legacyValues = {} - this.translatedValues = values.map(x => qsTranslate('parameters', x)) + this.translatedValues = values.map(x => qsTranslate("parameters", x)) } - + toString() { - return `${this.type}(${this.values.join(', ')})` + return `${this.type}(${this.values.join(", ")})` } parse(value) { @@ -111,28 +112,28 @@ export class Enum extends PropertyType { else if(this.legacyValues[value]) return this.legacyValues[value] else - throw new TypeError(`Exportation error: ${value} not one of ${this.values.join(', ')}.`) + throw new TypeError(`Exportation error: ${value} not one of ${this.values.join(", ")}.`) } } export class ObjectType extends PropertyType { - constructor(objType, allowNull=false) { + constructor(objType, allowNull = false) { super() - this.type = 'ObjectType' + this.type = "ObjectType" this.objType = objType this.allowNull = allowNull } - + toString() { return this.objType } parse(name) { let result = NONE - if(typeof name == 'string' && name in Objects.currentObjectsByName) { + if(typeof name == "string" && name in Objects.currentObjectsByName) { let obj = Objects.currentObjectsByName[name] - if (obj.type === this.objType || (this.objType === 'ExecutableObject' && obj.execute)) { + if(obj.type === this.objType || (this.objType === "ExecutableObject" && obj.execute)) { result = obj } else { // Silently error and return null @@ -147,7 +148,7 @@ export class ObjectType extends PropertyType { export(value) { if(value == null && this.allowNull) return null - else if(value.type === this.objType || (this.objType === 'ExecutableObject' && value.execute)) + else if(value.type === this.objType || (this.objType === "ExecutableObject" && value.execute)) return value.name else throw new TypeError(`Exportation error: ${value} not a ${this.objType}.`) @@ -156,28 +157,28 @@ export class ObjectType extends PropertyType { export class List extends PropertyType { - constructor(type, format = /^.+$/, label = '', forbidAdding = false) { + constructor(type, format = /^.+$/, label = "", forbidAdding = false) { super() // type can be string, int and double. - this.type = 'List' + this.type = "List" this.valueType = type if(!stringValidatorTypes.includes(this.valueType)) - throw new TypeError(`${this.valueType} must be one of ${stringValidatorTypes.join(', ')}.`) + throw new TypeError(`${this.valueType} must be one of ${stringValidatorTypes.join(", ")}.`) this.format = format this.label = label this.forbidAdding = forbidAdding } - + toString() { return `${this.type}(${this.valueType}:${this.format})` } parse(value) { let result = NONE - if(typeof value == 'object' && value.__proto__ === Array) { + if(typeof value == "object" && value.__proto__ === Array) { let valid = 0 for(let v of value) { - if (this.format.test(v)) { + if(this.format.test(v)) { v = stringValuesValidators[this.valueType][0](v) if(stringValuesValidators[this.valueType][1](v)) valid++ @@ -190,7 +191,7 @@ export class List extends PropertyType { } export(value) { - if(typeof value == 'object' && value.__proto__ === Array) + if(typeof value == "object" && value.__proto__ === Array) return value else throw new TypeError(`Exportation error: ${value} not a list.`) @@ -200,10 +201,10 @@ export class List extends PropertyType { export class Dictionary extends PropertyType { - constructor(type, keyType = 'string', format = /^.+$/, keyFormat = /^.+$/, preKeyLabel = '', postKeyLabel = ': ', forbidAdding = false) { + constructor(type, keyType = "string", format = /^.+$/, keyFormat = /^.+$/, preKeyLabel = "", postKeyLabel = ": ", forbidAdding = false) { super() // type & keyType can be string, int and double. - this.type = 'Dict' + this.type = "Dict" this.valueType = type this.keyType = keyType this.format = format @@ -219,10 +220,10 @@ export class Dictionary extends PropertyType { parse(value) { let result = NONE - if(typeof value == 'object' && value.__proto__ !== Array) { + if(typeof value == "object" && value.__proto__ !== Array) { let dict = [] for(let [k, v] of Object.entries(value)) { - if (this.format.test(v) && this.keyFormat.test(k)) { + if(this.format.test(v) && this.keyFormat.test(k)) { k = stringValuesValidators[this.keyType][0](k) v = stringValuesValidators[this.valueType][0](v) if(stringValuesValidators[this.keyType][1](k)) @@ -237,7 +238,7 @@ export class Dictionary extends PropertyType { } export(value) { - if(typeof value == 'object' && value.__proto__ !== Array) + if(typeof value == "object" && value.__proto__ !== Array) return value else throw new TypeError(`Exportation error: ${value} not a dictionary.`) @@ -247,51 +248,51 @@ export class Dictionary extends PropertyType { // Common parameters for Enums Enum.Position = new Enum( - QT_TRANSLATE_NOOP('parameters', 'above'), - QT_TRANSLATE_NOOP('parameters', 'below'), - QT_TRANSLATE_NOOP('parameters', 'left'), - QT_TRANSLATE_NOOP('parameters', 'right'), - QT_TRANSLATE_NOOP('parameters', 'above-left'), - QT_TRANSLATE_NOOP('parameters', 'above-right'), - QT_TRANSLATE_NOOP('parameters', 'below-left'), - QT_TRANSLATE_NOOP('parameters', 'below-right') + QT_TRANSLATE_NOOP("parameters", "above"), + QT_TRANSLATE_NOOP("parameters", "below"), + QT_TRANSLATE_NOOP("parameters", "left"), + QT_TRANSLATE_NOOP("parameters", "right"), + QT_TRANSLATE_NOOP("parameters", "above-left"), + QT_TRANSLATE_NOOP("parameters", "above-right"), + QT_TRANSLATE_NOOP("parameters", "below-left"), + QT_TRANSLATE_NOOP("parameters", "below-right") ) Enum.Position.legacyValues = { - 'top': 'above', - 'bottom': 'below', - 'top-left': 'above-left', - 'top-right': 'above-right', - 'bottom-left': 'below-left', - 'bottom-right': 'below-right', + "top": "above", + "bottom": "below", + "top-left": "above-left", + "top-right": "above-right", + "bottom-left": "below-left", + "bottom-right": "below-right" } Enum.Positioning = new Enum( - QT_TRANSLATE_NOOP('parameters', 'center'), - QT_TRANSLATE_NOOP('parameters', 'top'), - QT_TRANSLATE_NOOP('parameters', 'bottom'), - QT_TRANSLATE_NOOP('parameters', 'left'), - QT_TRANSLATE_NOOP('parameters', 'right'), - QT_TRANSLATE_NOOP('parameters', 'top-left'), - QT_TRANSLATE_NOOP('parameters', 'top-right'), - QT_TRANSLATE_NOOP('parameters', 'bottom-left'), - QT_TRANSLATE_NOOP('parameters', 'bottom-right') + QT_TRANSLATE_NOOP("parameters", "center"), + QT_TRANSLATE_NOOP("parameters", "top"), + QT_TRANSLATE_NOOP("parameters", "bottom"), + QT_TRANSLATE_NOOP("parameters", "left"), + QT_TRANSLATE_NOOP("parameters", "right"), + QT_TRANSLATE_NOOP("parameters", "top-left"), + QT_TRANSLATE_NOOP("parameters", "top-right"), + QT_TRANSLATE_NOOP("parameters", "bottom-left"), + QT_TRANSLATE_NOOP("parameters", "bottom-right") ) Enum.FunctionDisplayType = new Enum( - QT_TRANSLATE_NOOP('parameters', 'application'), - QT_TRANSLATE_NOOP('parameters', 'function') + QT_TRANSLATE_NOOP("parameters", "application"), + QT_TRANSLATE_NOOP("parameters", "function") ) Enum.BodePass = new Enum( - QT_TRANSLATE_NOOP('parameters', 'high'), - QT_TRANSLATE_NOOP('parameters', 'low') + QT_TRANSLATE_NOOP("parameters", "high"), + QT_TRANSLATE_NOOP("parameters", "low") ) Enum.XCursorValuePosition = new Enum( - QT_TRANSLATE_NOOP('parameters', 'Next to target'), - QT_TRANSLATE_NOOP('parameters', 'With label'), - QT_TRANSLATE_NOOP('parameters', 'Hidden') + QT_TRANSLATE_NOOP("parameters", "Next to target"), + QT_TRANSLATE_NOOP("parameters", "With label"), + QT_TRANSLATE_NOOP("parameters", "Hidden") ) /** @@ -303,23 +304,23 @@ Enum.XCursorValuePosition = new Enum( export function ensureTypeSafety(propertyType, value) { let result let error = false - if(typeof propertyType == 'string') + if(typeof propertyType == "string") switch(propertyType) { - case 'string': + case "string": result = value - error = typeof value !== 'string' + error = typeof value !== "string" break - case 'number': + case "number": result = parseFloat(value) error = isNaN(result) break - case 'boolean': + case "boolean": result = value error = value !== true && value !== false break - case 'Domain': + case "Domain": try { - error = typeof value !== 'string' + error = typeof value !== "string" if(!error) result = parseDomain(value) } catch(e) { @@ -353,18 +354,18 @@ export function ensureTypeSafety(propertyType, value) { */ export function serializesByPropertyType(propertyType, value) { let result - if(typeof propertyType == 'string') + if(typeof propertyType == "string") switch(propertyType) { - case 'string': + case "string": result = value.toString() break - case 'number': + case "number": result = parseFloat(value) break - case 'boolean': + case "boolean": result = value === true break - case 'Domain': + case "Domain": if(value instanceof Domain) result = value.toString() else diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/common.mjs index 3313a1b..72a9a4b 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/common.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/common.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -19,30 +19,30 @@ export default class InputExpression { constructor(expression) { - this.position = 0; - this.input = expression; + this.position = 0 + this.input = expression } - + next() { - return this.input[this.position++]; + return this.input[this.position++] } - + peek() { - return this.input[this.position]; + return this.input[this.position] } - + skip(char) { if(!this.atEnd() && this.peek() === char) { - this.position++; + this.position++ } else { - this.raise("Unexpected character " + this.peek() + ". Expected character " + char); + this.raise("Unexpected character " + this.peek() + ". Expected character " + char) } } - + atEnd() { - return this.position >= this.input.length; + return this.position >= this.input.length } - + raise(message) { throw new SyntaxError(message + " at " + this.position + ".") } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/reference.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/reference.mjs index 9c30991..36d4c8c 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/reference.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/reference.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -25,8 +25,8 @@ export const CONSTANTS = { "infinity": Infinity, "∞": Infinity, "e": Math.E -}; -export const CONSTANTS_LIST = Object.keys(CONSTANTS); +} +export const CONSTANTS_LIST = Object.keys(CONSTANTS) export const FUNCTIONS = { // The functions commented are the one either not implemented @@ -36,78 +36,78 @@ export const FUNCTIONS = { //'-': (x) => -x, //'!' // Other operations - 'length': (s) => Array.isArray(s) ? s.length : String(s).length, + "length": (s) => Array.isArray(s) ? s.length : String(s).length, // Boolean functions - 'not': (x) => !x, + "not": (x) => !x, // Math functions - 'abs': Math.abs, - 'acos': Math.acos, - 'acosh': Math.acosh, - 'asin': Math.asin, - 'asinh': Math.asinh, - 'atan': Math.atan, - 'atan2': Math.atan2, - 'atanh': Math.atanh, - 'cbrt': Math.cbrt, - 'ceil': Math.ceil, + "abs": Math.abs, + "acos": Math.acos, + "acosh": Math.acosh, + "asin": Math.asin, + "asinh": Math.asinh, + "atan": Math.atan, + "atan2": Math.atan2, + "atanh": Math.atanh, + "cbrt": Math.cbrt, + "ceil": Math.ceil, //'clz32': Math.clz32, - 'cos': Math.cos, - 'cosh': Math.cosh, - 'exp': Math.exp, - 'expm1': Math.expm1, - 'floor': Math.floor, + "cos": Math.cos, + "cosh": Math.cosh, + "exp": Math.exp, + "expm1": Math.expm1, + "floor": Math.floor, //'fround': Math.fround, - 'hypot': Math.hypot, + "hypot": Math.hypot, //'imul': Math.imul, - 'lg': Math.log10, - 'ln': Math.log, - 'log': Math.log, - 'log10': Math.log10, - 'log1p': Math.log1p, - 'log2': Math.log2, - 'max': Math.max, - 'min': Math.min, - 'pow': Math.log2, - 'random': Math.random, - 'round': Math.round, - 'sign': Math.sign, - 'sin': Math.sin, - 'sinh': Math.sinh, - 'sqrt': Math.sqrt, - 'tan': Math.tan, - 'tanh': Math.tanh, - 'trunc': Math.trunc, + "lg": Math.log10, + "ln": Math.log, + "log": Math.log, + "log10": Math.log10, + "log1p": Math.log1p, + "log2": Math.log2, + "max": Math.max, + "min": Math.min, + "pow": Math.log2, + "random": Math.random, + "round": Math.round, + "sign": Math.sign, + "sin": Math.sin, + "sinh": Math.sinh, + "sqrt": Math.sqrt, + "tan": Math.tan, + "tanh": Math.tanh, + "trunc": Math.trunc, // Functions in expr-eval, ported here. - 'fac': Polyfill.factorial, - 'gamma': Polyfill.gamma, - 'Γ': Polyfill.gamma, - 'roundTo': (x, exp) => Number(x).toFixed(exp), + "fac": Polyfill.factorial, + "gamma": Polyfill.gamma, + "Γ": Polyfill.gamma, + "roundTo": (x, exp) => Number(x).toFixed(exp), // 'map': Polyfill.arrayMap, // 'fold': Polyfill.arrayFold, // 'filter': Polyfill.arrayFilter, // 'indexOf': Polyfill.indexOf, // 'join': Polyfill.arrayJoin, // Integral & derivative (only here for autocomplete). - 'integral': () => 0, // TODO: Implement - 'derivative': () => 0, + "integral": () => 0, // TODO: Implement + "derivative": () => 0 } -export const FUNCTIONS_LIST = Object.keys(FUNCTIONS); +export const FUNCTIONS_LIST = Object.keys(FUNCTIONS) export class P { // Parameter class. - constructor(type, name = '', optional = false, multipleAllowed = false) { + constructor(type, name = "", optional = false, multipleAllowed = false) { this.name = name this.type = type this.optional = optional this.multipleAllowed = multipleAllowed } - + toString() { let base_string = this.type - if(this.name !== '') + if(this.name !== "") base_string = `${this.name}: ${base_string}` if(this.multipleAllowed) - base_string += '...' + base_string += "..." if(!this.optional) base_string = `<${base_string}>` else @@ -116,59 +116,59 @@ export class P { } } -export let string = new P('string') -export let bool = new P('bool') -export let number = new P('number') -export let array = new P('array') +export let string = new P("string") +export let bool = new P("bool") +export let number = new P("number") +export let array = new P("array") export const FUNCTIONS_USAGE = { - 'length': [string], - 'not': [bool], + "length": [string], + "not": [bool], // Math functions - 'abs': [number], - 'acos': [number], - 'acosh': [number], - 'asin': [number], - 'asinh': [number], - 'atan': [number], - 'atan2': [number], - 'atanh': [number], - 'cbrt': [number], - 'ceil': [number], + "abs": [number], + "acos": [number], + "acosh": [number], + "asin": [number], + "asinh": [number], + "atan": [number], + "atan2": [number], + "atanh": [number], + "cbrt": [number], + "ceil": [number], //'clz32': [number], - 'cos': [number], - 'cosh': [number], - 'exp': [number], - 'expm1': [number], - 'floor': [number], + "cos": [number], + "cosh": [number], + "exp": [number], + "expm1": [number], + "floor": [number], //'fround': [number], - 'hypot': [number], + "hypot": [number], //'imul': [number], - 'lg': [number], - 'ln': [number], - 'log': [number], - 'log10': [number], - 'log1p': [number], - 'log2': [number], - 'max': [number, number, new P('numbers', '', true, true)], - 'min': [number, number, new P('numbers', '', true, true)], - 'pow': [number, new P('number', 'exp')], - 'random': [number, number], - 'round': [number], - 'sign': [number], - 'sin': [number], - 'sinh': [number], - 'sqrt': [number], - 'tan': [number], - 'tanh': [number], - 'trunc': [number], + "lg": [number], + "ln": [number], + "log": [number], + "log10": [number], + "log1p": [number], + "log2": [number], + "max": [number, number, new P("numbers", "", true, true)], + "min": [number, number, new P("numbers", "", true, true)], + "pow": [number, new P("number", "exp")], + "random": [number, number], + "round": [number], + "sign": [number], + "sin": [number], + "sinh": [number], + "sqrt": [number], + "tan": [number], + "tanh": [number], + "trunc": [number], // Functions in expr-eval, ported here. - 'fac': [number], - 'gamma': [number], - 'Γ': [number], - 'roundTo': [number, new P('number')], + "fac": [number], + "gamma": [number], + "Γ": [number], + "roundTo": [number, new P("number")], // Function manipulation - 'derivative': [new P('f'), new P('string', 'var', true), number], - 'integral': [new P('from'), new P('to'), new P('f'), new P('string', 'var', true)], + "derivative": [new P("f"), new P("string", "var", true), number], + "integral": [new P("from"), new P("to"), new P("f"), new P("string", "var", true)] } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/tokenizer.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/tokenizer.mjs index 2dd8620..a8552fc 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/tokenizer.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/parsing/tokenizer.mjs @@ -1,17 +1,17 @@ /** * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. * Copyright (C) 2021-2024 Ad5001 - * + * * 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 . */ @@ -20,9 +20,9 @@ import * as Reference from "./reference.mjs" const WHITESPACES = " \t\n\r" -const STRING_LIMITERS = '"\'`'; -const OPERATORS = "+-*/^%?:=!><"; -const PUNCTUATION = "()[]{},."; +const STRING_LIMITERS = "\"'`" +const OPERATORS = "+-*/^%?:=!><" +const PUNCTUATION = "()[]{},." const NUMBER_CHARS = "0123456789" const IDENTIFIER_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_₀₁₂₃₄₅₆₇₈₉αβγδεζηθκλμξρςστφχψωₐₑₒₓₔₕₖₗₘₙₚₛₜ" @@ -41,8 +41,8 @@ export const TokenType = { export class Token { constructor(type, value, startPosition) { - this.type = type; - this.value = value; + this.type = type + this.value = value this.startPosition = startPosition } } @@ -55,120 +55,120 @@ export class ExpressionTokenizer { * @param {boolean} errorOnUnknown */ constructor(input, tokenizeWhitespaces = false, errorOnUnknown = true) { - this.input = input; - this.currentToken = null; + this.input = input + this.currentToken = null this.tokenizeWhitespaces = tokenizeWhitespaces this.errorOnUnknown = errorOnUnknown } - + skipWhitespaces() { while(!this.input.atEnd() && WHITESPACES.includes(this.input.peek())) - this.input.next(); + this.input.next() } - + readWhitespaces() { - let included = ""; + let included = "" while(!this.input.atEnd() && WHITESPACES.includes(this.input.peek())) { - included += this.input.next(); + included += this.input.next() } - return new Token(TokenType.WHITESPACE, included, this.input.position-included.length) + return new Token(TokenType.WHITESPACE, included, this.input.position - included.length) } - + readString() { - let delimitation = this.input.peek(); + let delimitation = this.input.peek() if(STRING_LIMITERS.includes(delimitation)) { this.input.skip(delimitation) - let included = ""; - let justEscaped = false; + let included = "" + let justEscaped = false while(!this.input.atEnd() && (!STRING_LIMITERS.includes(this.input.peek()) || justEscaped)) { justEscaped = this.input.peek() === "\\" if(!justEscaped) - included += this.input.next(); + included += this.input.next() } this.input.skip(delimitation) - let token = new Token(TokenType.STRING, included, this.input.position-included.length) + let token = new Token(TokenType.STRING, included, this.input.position - included.length) token.limitator = delimitation return token } else { this.input.raise("Unexpected " + delimitation + ". Expected string delimitator") } } - + readNumber() { - let included = ""; - let hasDot = false; - while(!this.input.atEnd() && (NUMBER_CHARS.includes(this.input.peek()) || this.input.peek() === '.')) { + let included = "" + let hasDot = false + while(!this.input.atEnd() && (NUMBER_CHARS.includes(this.input.peek()) || this.input.peek() === ".")) { if(this.input.peek() === ".") { if(hasDot) this.input.raise("Unexpected '.'. Expected digit") - hasDot = true; + hasDot = true } - included += this.input.next(); + included += this.input.next() } - return new Token(TokenType.NUMBER, included, this.input.position-included.length) + return new Token(TokenType.NUMBER, included, this.input.position - included.length) } - + readOperator() { - let included = ""; + let included = "" while(!this.input.atEnd() && OPERATORS.includes(this.input.peek())) { - included += this.input.next(); + included += this.input.next() } - return new Token(TokenType.OPERATOR, included, this.input.position-included.length) + return new Token(TokenType.OPERATOR, included, this.input.position - included.length) } - + readIdentifier() { - let identifier = ""; + let identifier = "" while(!this.input.atEnd() && IDENTIFIER_CHARS.includes(this.input.peek().toLowerCase())) { - identifier += this.input.next(); + identifier += this.input.next() } if(Reference.CONSTANTS_LIST.includes(identifier.toLowerCase())) { - return new Token(TokenType.CONSTANT, identifier.toLowerCase(), this.input.position-identifier.length) + return new Token(TokenType.CONSTANT, identifier.toLowerCase(), this.input.position - identifier.length) } else if(Reference.FUNCTIONS_LIST.includes(identifier.toLowerCase())) { - return new Token(TokenType.FUNCTION, identifier.toLowerCase(), this.input.position-identifier.length) + return new Token(TokenType.FUNCTION, identifier.toLowerCase(), this.input.position - identifier.length) } else { - return new Token(TokenType.VARIABLE, identifier, this.input.position-identifier.length) + return new Token(TokenType.VARIABLE, identifier, this.input.position - identifier.length) } } - + readNextToken() { if(!this.tokenizeWhitespaces) this.skipWhitespaces() - if(this.input.atEnd()) return null; - let c = this.input.peek(); - if(this.tokenizeWhitespaces && WHITESPACES.includes(c)) return this.readWhitespaces(); - if(STRING_LIMITERS.includes(c)) return this.readString(); - if(NUMBER_CHARS.includes(c)) return this.readNumber(); - if(IDENTIFIER_CHARS.includes(c.toLowerCase())) return this.readIdentifier(); - if(OPERATORS.includes(c)) return this.readOperator(); - if(Reference.CONSTANTS_LIST.includes(c)) return new Token(TokenType.CONSTANT, this.input.next(), this.input.position-1); - if(PUNCTUATION.includes(c)) return new Token(TokenType.PUNCT, this.input.next(), this.input.position-1); + if(this.input.atEnd()) return null + let c = this.input.peek() + if(this.tokenizeWhitespaces && WHITESPACES.includes(c)) return this.readWhitespaces() + if(STRING_LIMITERS.includes(c)) return this.readString() + if(NUMBER_CHARS.includes(c)) return this.readNumber() + if(IDENTIFIER_CHARS.includes(c.toLowerCase())) return this.readIdentifier() + if(OPERATORS.includes(c)) return this.readOperator() + if(Reference.CONSTANTS_LIST.includes(c)) return new Token(TokenType.CONSTANT, this.input.next(), this.input.position - 1) + if(PUNCTUATION.includes(c)) return new Token(TokenType.PUNCT, this.input.next(), this.input.position - 1) if(this.errorOnUnknown) this.input.raise("Unknown token character " + c) else - return new Token(TokenType.UNKNOWN, this.input.next(), this.input.position-1); + return new Token(TokenType.UNKNOWN, this.input.next(), this.input.position - 1) } peek() { - if(this.currentToken == null) this.currentToken = this.readNextToken(); - return this.currentToken; + if(this.currentToken == null) this.currentToken = this.readNextToken() + return this.currentToken } next() { - let tmp; + let tmp if(this.currentToken == null) - tmp = this.readNextToken(); + tmp = this.readNextToken() else - tmp = this.currentToken; - this.currentToken = null; - return tmp; + tmp = this.currentToken + this.currentToken = null + return tmp } - + atEnd() { - return this.peek() == null; + return this.peek() == null } - + skip(type) { - let next = this.next(); + let next = this.next() if(next.type !== type) - this.input.raise("Unexpected token " + next.type.toLowerCase() + ' "' + next.value + '". Expected ' + type.toLowerCase()); + this.input.raise("Unexpected token " + next.type.toLowerCase() + " \"" + next.value + "\". Expected " + type.toLowerCase()) } } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs index 1e708ca..e456dc2 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/common.mjs @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import {Expression} from "../math/index.mjs" +import { Expression } from "../math/index.mjs" class Setting { constructor(type, name, nameInConfig, icon) { @@ -49,7 +49,7 @@ class Setting { export class BoolSetting extends Setting { constructor(name, nameInConfig, icon) { - super('bool', name, nameInConfig, icon) + super("bool", name, nameInConfig, icon) } value() { @@ -63,9 +63,9 @@ export class BoolSetting extends Setting { export class NumberSetting extends Setting { constructor(name, nameInConfig, icon, min = -Infinity, max = +Infinity) { - super('number', name, nameInConfig, icon) - this.min = typeof min == 'number' ? () => min : min - this.max = typeof max == 'number' ? () => max : max + super("number", name, nameInConfig, icon) + this.min = typeof min == "number" ? () => min : min + this.max = typeof max == "number" ? () => max : max } value() { @@ -79,7 +79,7 @@ export class NumberSetting extends Setting { export class EnumIntSetting extends Setting { constructor(name, nameInConfig, icon, values = []) { - super('enum', name, nameInConfig, icon) + super("enum", name, nameInConfig, icon) this.values = values } @@ -94,7 +94,7 @@ export class EnumIntSetting extends Setting { export class ExpressionSetting extends Setting { constructor(name, nameInConfig, icon, variables = []) { - super('expression', name, nameInConfig, icon) + super("expression", name, nameInConfig, icon) this.variables = variables } @@ -112,17 +112,17 @@ export class ExpressionSetting extends Setting { Helper.setSetting(this.nameInConfig, value) else { let undefinedVars = vars.filter(x => !this.variables.includes(x)) - let allowed = '' + let allowed = "" if(this.variables.length > 0) - allowed = `Allowed variables: ${this.variables.join(', ')}.` - throw new TypeError(`Cannot use variable(s) ${undefinedVars.join(', or ')} to define ${this.displayName}. ${allowed}`) + allowed = `Allowed variables: ${this.variables.join(", ")}.` + throw new TypeError(`Cannot use variable(s) ${undefinedVars.join(", or ")} to define ${this.displayName}. ${allowed}`) } } } export class StringSetting extends Setting { constructor(name, nameInConfig, icon, defaultValues = []) { - super('string', name, nameInConfig, icon) + super("string", name, nameInConfig, icon) this.defaultValues = defaultValues } diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs index c58f4de..0fa9531 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/default.mjs @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import {BoolSetting, ExpressionSetting, NumberSetting, StringSetting} from "./common.mjs" +import { BoolSetting, ExpressionSetting, NumberSetting, StringSetting } from "./common.mjs" const XZOOM = new NumberSetting( @@ -49,13 +49,13 @@ const YMAX = new NumberSetting( const XAXISSTEP = new ExpressionSetting( qsTranslate("Settings", "X Axis Step"), "default_graph.xaxisstep", - "xaxisstep", + "xaxisstep" ) const YAXISSTEP = new ExpressionSetting( qsTranslate("Settings", "Y Axis Step"), "default_graph.yaxisstep", - "yaxisstep", + "yaxisstep" ) const LINE_WIDTH = new NumberSetting( @@ -72,33 +72,33 @@ const TEXT_SIZE = new NumberSetting( ) const X_LABEL = new StringSetting( - qsTranslate("Settings", 'X Label'), + qsTranslate("Settings", "X Label"), "default_graph.xlabel", "xlabel", ["", "x", "ω (rad/s)"] ) const Y_LABEL = new StringSetting( - qsTranslate("Settings", 'Y Label'), + qsTranslate("Settings", "Y Label"), "default_graph.ylabel", "xlabel", ["", "y", "G (dB)", "φ (°)", "φ (deg)", "φ (rad)"] ) const LOG_SCALE_X = new BoolSetting( - qsTranslate("Settings", 'X Log scale'), + qsTranslate("Settings", "X Log scale"), "default_graph.logscalex", "logscalex" ) const SHOW_X_GRAD = new BoolSetting( - qsTranslate("Settings", 'Show X graduation'), + qsTranslate("Settings", "Show X graduation"), "default_graph.showxgrad", "showxgrad" ) const SHOW_Y_GRAD = new BoolSetting( - qsTranslate("Settings", 'Show Y graduation'), + qsTranslate("Settings", "Show Y graduation"), "default_graph.showygrad", "showygrad" ) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs index efd7b40..85e1fbe 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/expression.mjs @@ -16,30 +16,30 @@ * along with this program. If not, see . */ -import {BoolSetting, EnumIntSetting} from "./common.mjs" +import { BoolSetting, EnumIntSetting } from "./common.mjs" const AUTOCLOSE_FORMULA = new BoolSetting( qsTranslate("expression", "Automatically close parenthesises and brackets"), - 'expression_editor.autoclose', - 'text' + "expression_editor.autoclose", + "text" ) const ENABLE_SYNTAX_HIGHLIGHTING = new BoolSetting( qsTranslate("expression", "Enable syntax highlighting"), - 'expression_editor.colorize', - 'appearance' + "expression_editor.colorize", + "appearance" ) const ENABLE_AUTOCOMPLETE = new BoolSetting( qsTranslate("expression", "Enable autocompletion"), - 'autocompletion.enabled', - 'label' + "autocompletion.enabled", + "label" ) const PICK_COLOR_SCHEME = new EnumIntSetting( qsTranslate("expression", "Color Scheme"), - 'expression_editor.color_scheme', - 'color', + "expression_editor.color_scheme", + "color", ["Breeze Light", "Breeze Dark", "Solarized", "Github Light", "Github Dark", "Nord", "Monokai"] ) diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs index 8d1e751..81c5e3d 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/preferences/general.mjs @@ -16,25 +16,25 @@ * along with this program. If not, see . */ -import {BoolSetting} from "./common.mjs" +import { BoolSetting } from "./common.mjs" import Canvas from "../module/canvas.mjs" import LatexAPI from "../module/latex.mjs" const CHECK_FOR_UPDATES = new BoolSetting( qsTranslate("general", "Check for updates on startup"), - 'check_for_updates', - 'update' + "check_for_updates", + "update" ) const RESET_REDO_STACK = new BoolSetting( qsTranslate("general", "Reset redo stack automaticly"), - 'reset_redo_stack', - 'timeline' + "reset_redo_stack", + "timeline" ) class EnableLatex extends BoolSetting { constructor() { - super(qsTranslate("general","Enable LaTeX rendering"), 'enable_latex', 'Expression') + super(qsTranslate("general", "Enable LaTeX rendering"), "enable_latex", "Expression") } set(value) { diff --git a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/utils.mjs b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/utils.mjs index 2e82be4..4f6b0c5 100644 --- a/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/utils.mjs +++ b/LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/utils.mjs @@ -16,6 +16,25 @@ * along with this program. If not, see . */ +// Add string methods +/** + * Replaces latin characters with their uppercase versions. + * @return {string} + */ +String.prototype.toLatinUppercase = String.prototype.toLatinUppercase || function() { + return this.replace(/[a-z]/g, function(match) { + return match.toUpperCase() + }) +} + +/** + * Removes the 'enclosers' of a string (e.g. quotes, parentheses, brackets...) + * @return {string} + */ +String.prototype.removeEnclosure = function() { + return this.substring(1, this.length - 1) +} + const powerpos = { "-": "⁻", "+": "⁺", @@ -350,10 +369,6 @@ export function parseName(str, removeUnallowed = true) { return str } -String.prototype.toLatinUppercase = function() { - return this.replace(/[a-z]/g, function(match){return match.toUpperCase()}) -} - /** * Transforms camel case strings to a space separated one. * diff --git a/LogarithmPlotter/util/debug.py b/LogarithmPlotter/util/debug.py index b093ee0..05271ac 100644 --- a/LogarithmPlotter/util/debug.py +++ b/LogarithmPlotter/util/debug.py @@ -29,7 +29,7 @@ class LOG_COLORS: GRAY = "\033[90m" BLUE = "\033[94m" ORANGE = "\033[38;5;166m" - RED = "\033[e[38;5;204m" + RED = "\033[38;5;204m" INVERT = "\033[7m" RESET_INVERT = "\033[27m" RESET = "\033[0m" diff --git a/package-lock.json b/package-lock.json index 1232c01..639f4a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", "install": "^0.13.0", "rollup": "^4.22.4", "rollup-plugin-cleanup": "^3.2.1" @@ -1724,16 +1723,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -1838,28 +1827,6 @@ } } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "license": "MIT", - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, "node_modules/@rollup/pluginutils": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", @@ -2114,18 +2081,6 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "license": "MIT" }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -2209,12 +2164,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, "node_modules/caniuse-lite": { "version": "1.0.30001663", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", @@ -2264,12 +2213,6 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2602,15 +2545,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -2770,26 +2704,6 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "license": "MIT" }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -2799,15 +2713,6 @@ "semver": "bin/semver.js" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/skip-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", @@ -2817,31 +2722,6 @@ "node": ">=4.2" } }, - "node_modules/smob": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", - "license": "MIT" - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -2873,24 +2753,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", - "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/package.json b/package.json index 78fad44..00761cd 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", "install": "^0.13.0", "rollup": "^4.22.4", "rollup-plugin-cleanup": "^3.2.1" diff --git a/rollup.config.mjs b/rollup.config.mjs index 4b4a305..892c9fb 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -20,7 +20,6 @@ import { nodeResolve } from "@rollup/plugin-node-resolve" import commonjs from "@rollup/plugin-commonjs" import { babel } from "@rollup/plugin-babel" import cleanup from "rollup-plugin-cleanup" -import terser from "@rollup/plugin-terser" const path = "LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js" @@ -39,9 +38,6 @@ export default { babel({ babelHelpers: "bundled" }), - // terser({ - // ecma: 2015 - // }) ] }