Improving reliability of threaded rendering, separating JS Utils into separate files.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
49e94317d4
commit
687b14429a
18 changed files with 285 additions and 197 deletions
|
@ -19,7 +19,7 @@
|
||||||
import Objects from "../module/objects.mjs"
|
import Objects from "../module/objects.mjs"
|
||||||
import Latex from "../module/latex.mjs"
|
import Latex from "../module/latex.mjs"
|
||||||
import * as MathLib from "../math/index.mjs"
|
import * as MathLib from "../math/index.mjs"
|
||||||
import { escapeHTML } from "../utils.mjs"
|
import { escapeHTML } from "../utils/index.mjs"
|
||||||
import { Action } from "./common.mjs"
|
import { Action } from "./common.mjs"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
|
|
||||||
import js from "./lib/polyfills/js.mjs"
|
import js from "./lib/polyfills/js.mjs"
|
||||||
|
|
||||||
import * as Modules from "./module/index.mjs"
|
export * as Utils from "./utils/index.mjs"
|
||||||
|
|
||||||
import * as ObjsAutoload from "./objs/autoload.mjs"
|
import * as ObjsAutoload from "./objs/autoload.mjs"
|
||||||
|
|
||||||
|
export * as Modules from "./module/index.mjs"
|
||||||
export * as MathLib from "./math/index.mjs"
|
export * as MathLib from "./math/index.mjs"
|
||||||
export * as HistoryLib from "./history/index.mjs"
|
export * as HistoryLib from "./history/index.mjs"
|
||||||
export * as Parsing from "./parsing/index.mjs"
|
export * as Parsing from "./parsing/index.mjs"
|
||||||
export * as Utils from "./utils.mjs"
|
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import * as Utils from "../utils.mjs"
|
import * as Utils from "../utils/index.mjs"
|
||||||
|
import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs"
|
||||||
import Latex from "../module/latex.mjs"
|
import Latex from "../module/latex.mjs"
|
||||||
import ExprParser from "../module/expreval.mjs"
|
import ExprParser from "../module/expreval.mjs"
|
||||||
import Objects from "../module/objects.mjs"
|
import Objects from "../module/objects.mjs"
|
||||||
import { ExprEvalExpression } from "../lib/expr-eval/expression.mjs"
|
|
||||||
|
|
||||||
const NUMBER_MATCHER = /^\d*\.\d+(e[+-]\d+)?$/
|
const NUMBER_MATCHER = /^\d*\.\d+(e[+-]\d+)?$/
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as Expr from "./expression.mjs"
|
import * as Expr from "./expression.mjs"
|
||||||
import * as Utils from "../utils.mjs"
|
import * as Utils from "../utils/index.mjs"
|
||||||
import Latex from "../module/latex.mjs"
|
import Latex from "../module/latex.mjs"
|
||||||
import Objects from "../module/objects.mjs"
|
import Objects from "../module/objects.mjs"
|
||||||
import ExprParser from "../module/expreval.mjs"
|
import ExprParser from "../module/expreval.mjs"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
import { Module } from "./common.mjs"
|
import { Module } from "./common.mjs"
|
||||||
import { CanvasInterface, DialogInterface } from "./interface.mjs"
|
import { CanvasInterface, DialogInterface } from "./interface.mjs"
|
||||||
import { textsup } from "../utils.mjs"
|
import { textsup } from "../utils/index.mjs"
|
||||||
import { Expression } from "../math/index.mjs"
|
import { Expression } from "../math/index.mjs"
|
||||||
import Latex from "./latex.mjs"
|
import Latex from "./latex.mjs"
|
||||||
import Objects from "./objects.mjs"
|
import Objects from "./objects.mjs"
|
||||||
|
|
|
@ -97,6 +97,7 @@ class LatexAPI extends Module {
|
||||||
* true if latex has been enabled by the user, false otherwise.
|
* true if latex has been enabled by the user, false otherwise.
|
||||||
*/
|
*/
|
||||||
this.enabled = false
|
this.enabled = false
|
||||||
|
this.promises = new Set()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,9 +140,12 @@ class LatexAPI extends Module {
|
||||||
if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!")
|
if(!this.initialized) throw new Error("Attempting requestAsyncRender before initialize!")
|
||||||
let render
|
let render
|
||||||
if(this.#latex.supportsAsyncRender) {
|
if(this.#latex.supportsAsyncRender) {
|
||||||
console.trace()
|
|
||||||
this.emit(new AsyncRenderStartedEvent(markup, fontSize, color))
|
this.emit(new AsyncRenderStartedEvent(markup, fontSize, color))
|
||||||
render = await this.#latex.renderAsync(markup, fontSize, color)
|
// Storing promise so that it does not get dereferenced.
|
||||||
|
const promise = this.#latex.renderAsync(markup, fontSize, color)
|
||||||
|
this.promises.add(promise)
|
||||||
|
render = await promise
|
||||||
|
this.promises.delete(promise)
|
||||||
this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color))
|
this.emit(new AsyncRenderFinishedEvent(markup, fontSize, color))
|
||||||
} else {
|
} else {
|
||||||
render = this.#latex.renderSync(markup, fontSize, color)
|
render = this.#latex.renderSync(markup, fontSize, color)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Module } from "./common.mjs"
|
import { Module } from "./common.mjs"
|
||||||
import { textsub } from "../utils.mjs"
|
import { textsub } from "../utils/index.mjs"
|
||||||
|
|
||||||
class ObjectsAPI extends Module {
|
class ObjectsAPI extends Module {
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getRandomColor } from "../utils.mjs"
|
|
||||||
import Objects from "../module/objects.mjs"
|
import Objects from "../module/objects.mjs"
|
||||||
import Latex from "../module/latex.mjs"
|
import Latex from "../module/latex.mjs"
|
||||||
|
import { getRandomColor } from "../utils/index.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
|
// This file contains the default data to be imported from all other objects
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { textsub } from "../utils.mjs"
|
import { textsub } from "../utils/index.mjs"
|
||||||
import Objects from "../module/objects.mjs"
|
import Objects from "../module/objects.mjs"
|
||||||
import { ExecutableObject } from "./common.mjs"
|
import { ExecutableObject } from "./common.mjs"
|
||||||
import { parseDomain, Expression, SpecialDomain } from "../math/index.mjs"
|
import { parseDomain, Expression, SpecialDomain } from "../math/index.mjs"
|
||||||
|
|
|
@ -16,151 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Add string methods
|
import { textsub, textsup } from "./subsup.mjs"
|
||||||
/**
|
|
||||||
* Replaces latin characters with their uppercase versions.
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
String.prototype.toLatinUppercase = function() {
|
|
||||||
return this.replace(/[a-z]/g, function(match) {
|
|
||||||
return match.toUpperCase()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the first and last character of a string
|
|
||||||
* Used to remove enclosing characters like quotes, parentheses, brackets...
|
|
||||||
* @note Does NOT check for their existence ahead of time.
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
String.prototype.removeEnclosure = function() {
|
|
||||||
return this.substring(1, this.length - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rounds to a certain number of decimal places.
|
|
||||||
* From https://stackoverflow.com/a/48764436
|
|
||||||
*
|
|
||||||
* @param {number} decimalPlaces
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) {
|
|
||||||
const p = Math.pow(10, decimalPlaces)
|
|
||||||
const n = (this * p) * (1 + Number.EPSILON)
|
|
||||||
return Math.round(n) / p
|
|
||||||
}
|
|
||||||
|
|
||||||
const CHARACTER_TO_POWER = new Map([
|
|
||||||
["-", "⁻"],
|
|
||||||
["+", "⁺"],
|
|
||||||
["=", "⁼"],
|
|
||||||
[" ", " "],
|
|
||||||
["(", "⁽"],
|
|
||||||
[")", "⁾"],
|
|
||||||
["0", "⁰"],
|
|
||||||
["1", "¹"],
|
|
||||||
["2", "²"],
|
|
||||||
["3", "³"],
|
|
||||||
["4", "⁴"],
|
|
||||||
["5", "⁵"],
|
|
||||||
["6", "⁶"],
|
|
||||||
["7", "⁷"],
|
|
||||||
["8", "⁸"],
|
|
||||||
["9", "⁹"],
|
|
||||||
["a", "ᵃ"],
|
|
||||||
["b", "ᵇ"],
|
|
||||||
["c", "ᶜ"],
|
|
||||||
["d", "ᵈ"],
|
|
||||||
["e", "ᵉ"],
|
|
||||||
["f", "ᶠ"],
|
|
||||||
["g", "ᵍ"],
|
|
||||||
["h", "ʰ"],
|
|
||||||
["i", "ⁱ"],
|
|
||||||
["j", "ʲ"],
|
|
||||||
["k", "ᵏ"],
|
|
||||||
["l", "ˡ"],
|
|
||||||
["m", "ᵐ"],
|
|
||||||
["n", "ⁿ"],
|
|
||||||
["o", "ᵒ"],
|
|
||||||
["p", "ᵖ"],
|
|
||||||
["r", "ʳ"],
|
|
||||||
["s", "ˢ"],
|
|
||||||
["t", "ᵗ"],
|
|
||||||
["u", "ᵘ"],
|
|
||||||
["v", "ᵛ"],
|
|
||||||
["w", "ʷ"],
|
|
||||||
["x", "ˣ"],
|
|
||||||
["y", "ʸ"],
|
|
||||||
["z", "ᶻ"]
|
|
||||||
])
|
|
||||||
|
|
||||||
const CHARACTER_TO_INDICE = new Map([
|
|
||||||
["-", "₋"],
|
|
||||||
["+", "₊"],
|
|
||||||
["=", "₌"],
|
|
||||||
["(", "₍"],
|
|
||||||
[")", "₎"],
|
|
||||||
[" ", " "],
|
|
||||||
["0", "₀"],
|
|
||||||
["1", "₁"],
|
|
||||||
["2", "₂"],
|
|
||||||
["3", "₃"],
|
|
||||||
["4", "₄"],
|
|
||||||
["5", "₅"],
|
|
||||||
["6", "₆"],
|
|
||||||
["7", "₇"],
|
|
||||||
["8", "₈"],
|
|
||||||
["9", "₉"],
|
|
||||||
["a", "ₐ"],
|
|
||||||
["e", "ₑ"],
|
|
||||||
["h", "ₕ"],
|
|
||||||
["i", "ᵢ"],
|
|
||||||
["j", "ⱼ"],
|
|
||||||
["k", "ₖ"],
|
|
||||||
["l", "ₗ"],
|
|
||||||
["m", "ₘ"],
|
|
||||||
["n", "ₙ"],
|
|
||||||
["o", "ₒ"],
|
|
||||||
["p", "ₚ"],
|
|
||||||
["r", "ᵣ"],
|
|
||||||
["s", "ₛ"],
|
|
||||||
["t", "ₜ"],
|
|
||||||
["u", "ᵤ"],
|
|
||||||
["v", "ᵥ"],
|
|
||||||
["x", "ₓ"]
|
|
||||||
])
|
|
||||||
|
|
||||||
const EXPONENTS = [
|
|
||||||
"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
|
|
||||||
]
|
|
||||||
|
|
||||||
const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put a text in sup position
|
|
||||||
* @param {string} text
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
export function textsup(text) {
|
|
||||||
let ret = ""
|
|
||||||
text = text.toString()
|
|
||||||
for(let letter of text)
|
|
||||||
ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put a text in sub position
|
|
||||||
* @param {string} text
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
export function textsub(text) {
|
|
||||||
let ret = ""
|
|
||||||
text = text.toString()
|
|
||||||
for(let letter of text)
|
|
||||||
ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplifies (mathematically) a mathematical expression.
|
* Simplifies (mathematically) a mathematical expression.
|
||||||
|
@ -400,35 +256,3 @@ export function parseName(str, removeUnallowed = true) {
|
||||||
|
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a randomized color string.
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function getRandomColor() {
|
|
||||||
let clrs = "0123456789ABCDEF"
|
|
||||||
let color = "#"
|
|
||||||
for(let i = 0; i < 6; i++) {
|
|
||||||
color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))]
|
|
||||||
}
|
|
||||||
return color
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes text to html entities.
|
|
||||||
* @param {string} str
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function escapeHTML(str) {
|
|
||||||
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses exponents and replaces them with expression values
|
|
||||||
* @param {string} expression - The expression to replace in.
|
|
||||||
* @return {string} The parsed expression
|
|
||||||
*/
|
|
||||||
export function exponentsToExpression(expression) {
|
|
||||||
return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join(""))
|
|
||||||
}
|
|
22
common/src/utils/index.mjs
Normal file
22
common/src/utils/index.mjs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from "./prototype.mjs"
|
||||||
|
export * from "./subsup.mjs"
|
||||||
|
export * from "./expression.mjs"
|
||||||
|
export * from "./other.mjs"
|
41
common/src/utils/other.mjs
Normal file
41
common/src/utils/other.mjs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a randomized color string.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getRandomColor() {
|
||||||
|
let clrs = "0123456789ABCDEF"
|
||||||
|
let color = "#"
|
||||||
|
for(let i = 0; i < 6; i++) {
|
||||||
|
color += clrs[Math.floor(Math.random() * (16 - 5 * (i % 2 === 0)))]
|
||||||
|
}
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes text to html entities.
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function escapeHTML(str) {
|
||||||
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")
|
||||||
|
}
|
51
common/src/utils/prototype.mjs
Normal file
51
common/src/utils/prototype.mjs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add string methods
|
||||||
|
/**
|
||||||
|
* Replaces latin characters with their uppercase versions.
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
String.prototype.toLatinUppercase = function() {
|
||||||
|
return this.replace(/[a-z]/g, function(match) {
|
||||||
|
return match.toUpperCase()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first and last character of a string
|
||||||
|
* Used to remove enclosing characters like quotes, parentheses, brackets...
|
||||||
|
* @note Does NOT check for their existence ahead of time.
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
String.prototype.removeEnclosure = function() {
|
||||||
|
return this.substring(1, this.length - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rounds to a certain number of decimal places.
|
||||||
|
* From https://stackoverflow.com/a/48764436
|
||||||
|
*
|
||||||
|
* @param {number} decimalPlaces
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
Number.prototype.toDecimalPrecision = function(decimalPlaces = 0) {
|
||||||
|
const p = Math.pow(10, decimalPlaces)
|
||||||
|
const n = (this * p) * (1 + Number.EPSILON)
|
||||||
|
return Math.round(n) / p
|
||||||
|
}
|
140
common/src/utils/subsup.mjs
Normal file
140
common/src/utils/subsup.mjs
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const CHARACTER_TO_POWER = new Map([
|
||||||
|
["-", "⁻"],
|
||||||
|
["+", "⁺"],
|
||||||
|
["=", "⁼"],
|
||||||
|
[" ", " "],
|
||||||
|
["(", "⁽"],
|
||||||
|
[")", "⁾"],
|
||||||
|
["0", "⁰"],
|
||||||
|
["1", "¹"],
|
||||||
|
["2", "²"],
|
||||||
|
["3", "³"],
|
||||||
|
["4", "⁴"],
|
||||||
|
["5", "⁵"],
|
||||||
|
["6", "⁶"],
|
||||||
|
["7", "⁷"],
|
||||||
|
["8", "⁸"],
|
||||||
|
["9", "⁹"],
|
||||||
|
["a", "ᵃ"],
|
||||||
|
["b", "ᵇ"],
|
||||||
|
["c", "ᶜ"],
|
||||||
|
["d", "ᵈ"],
|
||||||
|
["e", "ᵉ"],
|
||||||
|
["f", "ᶠ"],
|
||||||
|
["g", "ᵍ"],
|
||||||
|
["h", "ʰ"],
|
||||||
|
["i", "ⁱ"],
|
||||||
|
["j", "ʲ"],
|
||||||
|
["k", "ᵏ"],
|
||||||
|
["l", "ˡ"],
|
||||||
|
["m", "ᵐ"],
|
||||||
|
["n", "ⁿ"],
|
||||||
|
["o", "ᵒ"],
|
||||||
|
["p", "ᵖ"],
|
||||||
|
["r", "ʳ"],
|
||||||
|
["s", "ˢ"],
|
||||||
|
["t", "ᵗ"],
|
||||||
|
["u", "ᵘ"],
|
||||||
|
["v", "ᵛ"],
|
||||||
|
["w", "ʷ"],
|
||||||
|
["x", "ˣ"],
|
||||||
|
["y", "ʸ"],
|
||||||
|
["z", "ᶻ"]
|
||||||
|
])
|
||||||
|
|
||||||
|
const CHARACTER_TO_INDICE = new Map([
|
||||||
|
["-", "₋"],
|
||||||
|
["+", "₊"],
|
||||||
|
["=", "₌"],
|
||||||
|
["(", "₍"],
|
||||||
|
[")", "₎"],
|
||||||
|
[" ", " "],
|
||||||
|
["0", "₀"],
|
||||||
|
["1", "₁"],
|
||||||
|
["2", "₂"],
|
||||||
|
["3", "₃"],
|
||||||
|
["4", "₄"],
|
||||||
|
["5", "₅"],
|
||||||
|
["6", "₆"],
|
||||||
|
["7", "₇"],
|
||||||
|
["8", "₈"],
|
||||||
|
["9", "₉"],
|
||||||
|
["a", "ₐ"],
|
||||||
|
["e", "ₑ"],
|
||||||
|
["h", "ₕ"],
|
||||||
|
["i", "ᵢ"],
|
||||||
|
["j", "ⱼ"],
|
||||||
|
["k", "ₖ"],
|
||||||
|
["l", "ₗ"],
|
||||||
|
["m", "ₘ"],
|
||||||
|
["n", "ₙ"],
|
||||||
|
["o", "ₒ"],
|
||||||
|
["p", "ₚ"],
|
||||||
|
["r", "ᵣ"],
|
||||||
|
["s", "ₛ"],
|
||||||
|
["t", "ₜ"],
|
||||||
|
["u", "ᵤ"],
|
||||||
|
["v", "ᵥ"],
|
||||||
|
["x", "ₓ"]
|
||||||
|
])
|
||||||
|
|
||||||
|
const EXPONENTS = [
|
||||||
|
"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"
|
||||||
|
]
|
||||||
|
|
||||||
|
const EXPONENTS_REG = new RegExp("([" + EXPONENTS.join("") + "]+)", "g")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put a text in sup position
|
||||||
|
* @param {string} text
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function textsup(text) {
|
||||||
|
let ret = ""
|
||||||
|
text = text.toString()
|
||||||
|
for(let letter of text)
|
||||||
|
ret += CHARACTER_TO_POWER.has(letter) ? CHARACTER_TO_POWER.get(letter) : letter
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put a text in sub position
|
||||||
|
* @param {string} text
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function textsub(text) {
|
||||||
|
let ret = ""
|
||||||
|
text = text.toString()
|
||||||
|
for(let letter of text)
|
||||||
|
ret += CHARACTER_TO_INDICE.has(letter) ? CHARACTER_TO_INDICE.get(letter) : letter
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses exponents and replaces them with expression values
|
||||||
|
* @param {string} expression - The expression to replace in.
|
||||||
|
* @return {string} The parsed expression
|
||||||
|
*/
|
||||||
|
export function exponentsToExpression(expression) {
|
||||||
|
return expression.replace(EXPONENTS_REG, (m, exp) => "^" + exp.split("").map((x) => EXPONENTS.indexOf(x)).join(""))
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils.mjs"
|
import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExpression } from "../../src/utils/index.mjs"
|
||||||
|
|
||||||
|
|
||||||
import { describe, it } from "mocha"
|
import { describe, it } from "mocha"
|
||||||
|
|
|
@ -178,4 +178,4 @@ describe("Math/Expression", function() {
|
||||||
expect(() => executeExpression("x+n")).to.throw("Undefined variable n.")
|
expect(() => executeExpression("x+n")).to.throw("Undefined variable n.")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,9 +21,10 @@ from platform import system as os_name, release as OS_RELEASE
|
||||||
from sys import path as sys_path
|
from sys import path as sys_path
|
||||||
from sys import argv, exit
|
from sys import argv, exit
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
from math import ceil
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from PySide6.QtCore import QTranslator, QLocale
|
from PySide6.QtCore import QTranslator, QLocale, QThreadPool, QThread
|
||||||
from PySide6.QtGui import QIcon
|
from PySide6.QtGui import QIcon
|
||||||
from PySide6.QtQml import QQmlApplicationEngine
|
from PySide6.QtQml import QQmlApplicationEngine
|
||||||
from PySide6.QtQuickControls2 import QQuickStyle
|
from PySide6.QtQuickControls2 import QQuickStyle
|
||||||
|
@ -162,7 +163,11 @@ def run():
|
||||||
|
|
||||||
dep_time = time()
|
dep_time = time()
|
||||||
print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.")
|
print("Loaded dependencies in " + str((dep_time - start_time) * 1000) + "ms.")
|
||||||
|
|
||||||
|
# Maxing thread count to half the computer's thread count to avoid maxing CPU
|
||||||
|
# with too many threads (and also leaving some for rendering).
|
||||||
|
QThreadPool.globalInstance().setMaxThreadCount(int(ceil(QThread.idealThreadCount() / 2)))
|
||||||
|
|
||||||
register_icon_directories()
|
register_icon_directories()
|
||||||
app = create_qapp()
|
app = create_qapp()
|
||||||
translator = install_translation(app)
|
translator = install_translation(app)
|
||||||
|
|
|
@ -22,6 +22,8 @@ from PySide6.QtQml import QJSValue
|
||||||
|
|
||||||
from LogarithmPlotter.util.js import PyJSValue
|
from LogarithmPlotter.util.js import PyJSValue
|
||||||
|
|
||||||
|
NO_RETURN = [None, QJSValue.SpecialValue.UndefinedValue]
|
||||||
|
|
||||||
|
|
||||||
def check_callable(function: Callable|QJSValue) -> Callable|None:
|
def check_callable(function: Callable|QJSValue) -> Callable|None:
|
||||||
"""
|
"""
|
||||||
|
@ -153,13 +155,12 @@ class PyPromise(QObject):
|
||||||
@Slot(QObject)
|
@Slot(QObject)
|
||||||
def _fulfill(self, data):
|
def _fulfill(self, data):
|
||||||
self._state = "fulfilled"
|
self._state = "fulfilled"
|
||||||
no_return = [None, QJSValue.SpecialValue.UndefinedValue]
|
|
||||||
print("Finished", self._runner.args)
|
print("Finished", self._runner.args)
|
||||||
for i in range(len(self._fulfills)):
|
for i in range(len(self._fulfills)):
|
||||||
try:
|
try:
|
||||||
result = self._fulfills[i](data)
|
result = self._fulfills[i](data)
|
||||||
result = result.qjs_value if isinstance(result, PyJSValue) else result
|
result = result.qjs_value if isinstance(result, PyJSValue) else result
|
||||||
data = result if result not in no_return else data # Forward data.
|
data = result if result not in NO_RETURN else data # Forward data.
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._reject(repr(e), start_at=i)
|
self._reject(repr(e), start_at=i)
|
||||||
break
|
break
|
||||||
|
@ -168,8 +169,7 @@ class PyPromise(QObject):
|
||||||
@Slot(str)
|
@Slot(str)
|
||||||
def _reject(self, error, start_at=0):
|
def _reject(self, error, start_at=0):
|
||||||
self._state = "rejected"
|
self._state = "rejected"
|
||||||
no_return = [None, QJSValue.SpecialValue.UndefinedValue]
|
|
||||||
for i in range(start_at, len(self._rejects)):
|
for i in range(start_at, len(self._rejects)):
|
||||||
result = self._rejects[i](error)
|
result = self._rejects[i](error)
|
||||||
result = result.qjs_value if isinstance(result, PyJSValue) else result
|
result = result.qjs_value if isinstance(result, PyJSValue) else result
|
||||||
error = result if result not in no_return else error # Forward data.
|
error = result if result not in NO_RETURN else error # Forward data.
|
||||||
|
|
Loading…
Reference in a new issue