lib/outils/mathgraph/FormulaComparator.js

import { isDomElement } from 'sesajs/dom'
import { getMqValue, isInputMathquill, unLatexify } from 'src/lib/mathquill/functions'

/**
 * Une classe pour comparer des expressions algébriques
 */
class FormulaComparator {
  constructor (mtgAppLecteur) {
    this.list = mtgAppLecteur.createList('TWF0aEdyYXBoSmF2YTEuMAAAABM+TMzNAAJmcv###wEA#wEAAAAAAAAAAAUeAAACygAAAQEAAAAAAAAAAQAAAAX#####AAAAAQAKQ0NhbGNDb25zdAD#####AAJwaQAWMy4xNDE1OTI2NTM1ODk3OTMyMzg0Nv####8AAAABAApDQ29uc3RhbnRlQAkh+1RELRj#####AAAAAQAJQ0ZvbmNOVmFyAP####8AB2ZvbmNzb2wAATAAAAABAAAAAAAAAAAAAAAGAAF4AAF5AAF6AAF0AAFhAAFiAAAAAgD#####AAdmb25jcmVwAAEwAAAAAQAAAAAAAAAAAAAABgABeAABeQABegABdAABYQABYv####8AAAADABBDVGVzdEVxdWl2YWxlbmNlAP####8ADHRlcWVxZGVjZnJhYwAAAAEAAAACAQAAAAABP#AAAAAAAAABAAAAAwD#####AA90ZXFub25lcWRlY2ZyYWMAAAABAAAAAgEAAAAAAT#wAAAAAAAAAP###############w==')
  }

  /**
   * Compare deux expressions pour savoir si elles sont équivalentes (au sens des permutations possibles dans l’expression, 1*x est équivalent à x mais x+x n’est pas équivalent à 2x ni x+0 à x).
   * @param {string} solution La solution (syntaxe mathgraph)
   * @param {string|HTMLElement} reponse (string avec syntaxe mathgraph ou input mathquill ou input mathlive)
   * @param {Object} [options]
   * @param {string} [options.varNames=xyztab] noms des variables formelles utilisées (6 max)
   * @param {boolean} [options.equivalenceFracDec=false] Passer true pour que une fraction irréductible dans solution
   * soit considérée comme équivalente à son écriture décimale quand elle tombe juste
   * @param {boolean} [options.simplify=true] true pour que, dans solution, les additions de 0 soient supprimées, les multiplications
   * et divisions par 1 soient supprimées (si simplifyMult1 est true, les multiplations par 1 sont préservées)
   * @param {boolean} [options.simplifyMult1=true], si simplify est true et simplifyMult1 est false, les multiplications par 1 sont préservées
   * @returns {number} -1 en cas d’erreur de syntaxe sur la réponse (-2 en cas d’erreur de syntaxe sur la solution), 1 si équivalent et 0 sinon
   */
  compare (solution, reponse, options = {}) {
    if (!options.varNames) options.varNames = 'xyztab'
    options.equivalenceFracDec = !(options.equivalenceFracDec === false) // Vrai par défaut si si précisé false
    options.simplify = !(options.simplify === false) // Vrai par défaut si si précisé false
    options.simplifyMult1 = !(options.simplifyMult1 === false)

    // si reponse est un HTMLElement (pas forcément dans le DOM), on va chercher sa valeur
    if (isDomElement(reponse, { htmlOnly: true })) {
      if (reponse.tagName === 'MATH-FIELD') {
        reponse = reponse.getValue('latex-unstyled')
      } else if (isInputMathquill(reponse)) {
        // c’est du mathquill
        reponse = getMqValue(reponse)
      } else {
        throw TypeError('reponse invalide (ni une string ni un input Mathquill|MathLive)')
      }
      // reste à nettoyer le latex
      reponse = unLatexify(reponse)
    }

    // On change maintenant le nom des variables formelles dans les deux fonctions utilisées
    if (options.varNames.length < 6) {
      const defvarnames = 'xyztab'
      for (let i = 0; (i < defvarnames.length) && (options.varNames.length < 6); i++) {
        if (!options.varNames.includes(defvarnames[i])) options.varNames += defvarnames[i]
      }
    }
    const tabvar = Array.from(options.varNames)
    this.list.col[1].chaineVariable = tabvar
    this.list.col[2].chaineVariable = tabvar
    if (!this.list.verifieSyntaxe(solution, tabvar)) return -2
    if (!this.list.verifieSyntaxe(reponse, tabvar)) return -1
    const teq1 = this.list.col[3]
    teq1.remplacementValeurs1 = options.simplify
    teq1.eliminMultUn1 = options.simplifyMult1
    const teq2 = this.list.col[4]
    teq2.remplacementValeurs1 = options.simplify
    teq2.eliminMultUn1 = options.simplifyMult1
    this.list.giveFormula2('foncsol', solution)
    this.list.giveFormula2('foncrep', reponse)
    this.list.calculateNG(false)
    if (options.equivalenceFracDec) return this.list.valueOf('teqeqdecfrac')
    return this.list.valueOf('teqnoneqdecfrac')
  }
}

export default FormulaComparator