legacy/outils/psylvia/Psylvia.js

// chargement de la feuille de style
import './psylvia.css'
import { j3pShowError } from 'src/legacy/core/functions'
import ALrepere from 'src/legacy/outils/psylvia/ALrepere'
import Tortue from 'src/legacy/outils/psylvia/Tortue'
import { afficher, filmDessinEfface, filmDessinGetElt, filmDessinSetElt, filmTortueEfface, filmTortueGetElt, filmTortueSetElt, getFreqTortue, papGetIndex, papInc, papReset, setFreqTortue } from './functions'

const w = window
const isFirefox = (navigator.userAgent.indexOf('Firefox') > -1)
const ALisIE = w.ActiveXObject

// recherche du num de la ligne de l’erreur
w.onerror = function onError (message, url, linenumber) {
  // pourquoi linenumber -1 ??
  souligne(numLignes[linenumber - 1], 'erreur')
}
// des trucs qui doivent être globaux (utilisé dans du code en string)
// décimales
w.ALprecision = 6
/** @type {ALrepere} */
w.ALrep = null
/** @type {Tortue} */
w.ALtortue = null

w.ALfcts = {}
w.ALvarAnciennes = {}

// tableau d’instructions formatees
w.ALformatees = []
// pour la gestion du pas à pas
// film de l’exécution du programme utilisateur
w.ALstop = false
w.AL1clic = undefined
w.ALtortueActive = false
// ralenti tortue
w.ALnb = undefined
w.ALangle = undefined

// nom du programme écrit par utilisateur
w.ALcle = ''
// pour le dessin
w.ALfenetre = { xMin: -5, yMin: -5, xMax: 5, yMax: 5, stroke: 'noir', fill: 'red' }

// fcts globales plus loin, après nos fonctions locales

// variables globales aux fcts de ce module
let actionFusee = () => undefined
let clic = false
/** @type {string} */
let controles
let dessinActif = false
let index = -1
// index du pas à pas
let indexPaP
// film de l’exécution du programme utilisateur (pas à pas)
let film = []
let limite = 5000
let vars = {}
let numLignes = []
let texteAffiche = ''
// liste nom: string
let verifs = {}
// liste nom: boolean
const isVerifOk = {}

function chercheElement (conteneur, tag, index) {
  tag = tag.toUpperCase()
  const c = document.getElementById(conteneur).childNodes
  let i = -1
  let j = -1
  while (i < c.length && j < index) {
    i++
    if (c?.[i]?.tagName?.toUpperCase() === tag) { j++ }
  }
  if (i < c.length) { return c[i] }
  return false
}

function compte () {
  index++
  // on propose l’arrêt du programme
  if (index >= limite) {
    let noLimit = false
    if (index === limite) {
      // eslint-disable-next-line no-alert
      noLimit = confirm('Les ' + limite + ' étapes sont dépassées.\nBoucle sans fin possible.\nFaut-il continuer ?')
    }
    if (!noLimit) {
      throw Error('Programme interrompu à votre demande.')
    }
    // sinon on augmente la limite
    limite += Math.min(20 * limite, 100000)
  }
}

function ecritSource (texte) {
  const div = document.getElementById('ALgauche')
  // nettoyage et récup de l’element pre
  let pre = div.firstChild
  while (pre) {
    div.removeChild(pre)
    pre = div.firstChild
  }
  pre = document.createElement('pre')
  texte = texte.replace(/\/\/br/g, '<br>')
  texte = texte.replace(/&lt;sup&gt;/gi, '<sup>')
  texte = texte.replace(/&lt;\/sup&gt/gi, '</sup>')
  pre.innerHTML = texte
  div.appendChild(pre)
}

function exec (prog) {
  limite = 5000
  index = -1
  const err777 = new Error()
  try {
  // eslint-disable-next-line no-eval
    eval(prog)
  } catch (err) {
    if (w.ALstop) {
      afficher('Programme arrêté par l’utilisateur')
    } else {
      afficher('ERREUR : ', err.message)
      // pour encadrer en rouge si pas firefox
      if (isFirefox) {
        const numLigne = numLignes[err.lineNumber - err777.lineNumber - 2]
        souligne(numLigne, 'erreur')
      } else {
        // eslint-disable-next-line no-eval
        eval(prog)
      }
    }
  }
  document.getElementById('ALdroite').appendChild(document.createElement('hr'))
  // contrôle des variables à vérifier
  for (const nom in verifs) {
    isVerifOk[nom] = (String(verifs[nom]) === String(w[nom]))
    if (String(verifs[nom]) !== String(w[nom])) {
      afficher('La variable ' + nom + ' a une valeur ' + w[nom] + ' incorrecte')
    }
  }
  // destruction des variables utilisateur
  for (const i in vars) delete w[i]
}

function faitFichier (type, chaine) {
  const json = {}
  if (arguments.length === 0) { type = 'algo' }
  switch (type) {
    case 'algo':
      var donnee = litSource()
      donnee = special(donnee)
      var t = donnee.split('//br;')
      if (t[0] == 'début_algo') { t.shift() }
      if (t[t.length - 1] == 'fin_algo') { t.pop() }
      if (t[t.length - 1].indexOf('contrôler') > -1) { t.pop() }
      donnee = t.join('//br;')
      json.algo = donnee
      if (controles) {
        try {
          json.controles = JSON.parse(controles)
        } catch (e) {
          console.error(e)
          afficher('ligne controlées non valide :\n' + controles + '\n', e)
        }
      }
      break
    case 'repas':
      json.repas = chaine
      break
    case 'itineraire':
      json.itineraire = chaine
      break
  }
  const lien = document.getElementById('ALlien')
  if (lien) {
    if (!ALisIE) {
      lien.href = 'data:;charset=utf8;,' + encodeURIComponent(JSON.stringify(json))
    } else {
      const ifr = document.getElementById('ALiframe')
      const ifrDoc = ifr.contentWindow.document
      ifrDoc.open('text/plain', 'replace')
      ifrDoc.charset = 'utf-8'
      ifrDoc.write(JSON.stringify(json))
      ifrDoc.close()
      document.charset = 'utf-8'
      ifrDoc.lien.href = 'javascript:ALsauveIE()'
    }
  }
}

// reglage du nombre de décimales des sorties
function faitPrecision () {
  const entree = document.getElementById('ALinputPrecis')
  let n = parseInt(entree.value)
  if (isNaN(n) || n < 0) {
    n = 6
    entree.value = '6'
  }
  w.ALprecision = n
}

function initDemos () {
  const s = document.getElementById('ALselectDemo')
  let i = 0
  let opt
  let h1 = chercheElement('ALdemos', 'H1', 0)
  while (h1) {
    opt = document.createElement('option')
    opt.innerHTML = h1.innerHTML
    s.appendChild(opt)
    i++
    h1 = chercheElement('ALdemos', 'h1', i)
  }
}

function initialiseTortue () {
  const droite = document.getElementById('ALdroiteTortue')
  if (!w.ALtortue) {
    w.ALtortue = new Tortue(droite.offsetWidth - 20, droite.offsetHeight - 20)
  } else {
    w.ALtortue.reInitialise()
  }
}

function lancer (preserveIndexPasApas) {
  voirDiv('ALaide', false)
  if (!preserveIndexPasApas) {
    preserveIndexPasApas = false
  }
  w.ALstop = false
  const prog = parseAlgo(preserveIndexPasApas)
  if (dessinActif) w.ALrep = new ALrepere()
  exec(prog)
}

function litSource (avecLignes) {
  const h = document.getElementById('ALgauche')
  let reg, s
  const expo = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹']
  // suppression des balises pre surnuméraires des navigateurs webkit
  let pre = h.firstChild
  let texte = ''
  if (pre.innerHTML) { texte = pre.innerHTML }
  while (pre.nextSibling) {
    pre = pre.nextSibling
    if (pre.innerHTML) {
      if (texte != '') { texte += '<br>' }
      texte += pre.innerHTML
    }
  }
  texte = '<pre>' + texte + '</pre>'
  texte = texte.replace(/<sup>/gi, '&lt;sup&gt;')
  texte = texte.replace(/<\/sup>/gi, '&lt;/sup&gt;')
  for (let i = 0; i < expo.length; i++) {
    reg = new RegExp(expo[i], 'gi')
    s = '&lt;sup&gt;' + i + '&lt;/sup&gt;'
    texte = texte.replace(reg, s)
  }
  texte = texte.replace(/\n/g, '//br;')
  texte = texte.replace(/<br>/gi, '//br;')
  texte = texte.replace(/\n/g, '//br;')
  texte = texte.replace(/→/gi, ' → ')

  const div = document.createElement('div')
  div.innerHTML = texte
  texte = div.textContent
  if (avecLignes) {
    texte = texte.replace(/\/\/br/gi, '\n')
  }
  return texte
}

function metronome () {
  const freq = document.getElementById('ALfreq')
  freq.parentNode.style.display = 'none'
  setFreqTortue(25 * parseInt(freq.value))
  w.ALtimer = setInterval(pasApas, getFreqTortue() * 40)
}

function modeTortue () {
  // function redim (grand) {
  //   let rg, rt, rb, ld
  //   const t = ['ALdroite', 'ALaide', 'ALdroiteTortue']
  //   if (grand) {
  //     rg = '60%'
  //     rt = '62%'
  //     rb = '61%'
  //     ld = '41%'
  //   } else {
  //     rg = '51%'
  //     rt = '57%'
  //     rb = '53%'
  //     ld = '50%'
  //   }
  //   let e = document.getElementById('ALgauche')
  //   e.style.right = rg
  //   e = document.getElementById('ALtouches')
  //   e.style.right = rt
  //   e = document.getElementById('ALboutons')
  //   e.style.right = rb
  //   for (let i = 0; i < t.length; i++) {
  //     e = document.getElementById(t[i])
  //     e.style.left = ld
  //   }
  // }
  w.ALtortueActive = !w.ALtortueActive
  const d = document.getElementById('ALdroiteTortue')
  const r = document.getElementById('ALrepasTortue')
  if (w.ALtortueActive) {
    // redim(true);
    d.style.visibility = 'visible'
    r.style.display = 'block'
    initialiseTortue()
  } else {
    // redim(false);
    r.style.display = 'none'
    d.style.visibility = 'hidden'
  }
}

// traduction de l’algo en javascript
function parseAlgo (preservePasApas) {
  texteAffiche = ''

  function gras (s) {
    return '££b' + s + '££c'
  }

  function traduit (s) {
    function op (c) {
      const t = ['+', '-', '/', '*', '%', '<', '>', '=', '≤', '≥', '≠']
      for (let i = 0; i < t.length; i++) {
        if (c == t[i]) { return true }
      }
      return false
      // return c == '+' || c == '-' || c == '*' || c == '/' || c == '%'
    }
    // recherche des puissances
    function parsePuissance (s) {
      let j = s.lastIndexOf('</sup>')
      if (j == -1) { return s }
      // ce qui est avant la balise
      let s1 = s.substring(0, j)
      // on traite récusrivement les autres exposants :
      // il ne restera donc plus que la balise <sup> ouvrante
      s1 = parsePuissance(s1)
      // ce qui est après le dernier </sup>
      const s2 = s.substring(j + 6)
      // recherche de l’exposant
      j = s1.lastIndexOf('<sup>')
      const exposant = s1.substring(j + 5)
      s1 = s1.substring(0, j)
      // recherche de la mantisse
      let k = s1.length - 1; let debutM = -1
      const parenth = (s1.charAt(k) == ')')
      let finM
      if (parenth) { finM = k } else { finM = k + 1 }
      let nivPar = 0
      while (debutM == -1 && k >= 0) {
        if (s1.charAt(k) == ')') { nivPar++ }
        if (s1.charAt(k) == '(') { nivPar-- }
        k--
        if ((((nivPar < 0 || parenth) && nivPar == 0) || op(s1.charAt(k))) && !parenth) {
          debutM = k
        }
      }
      debutM++
      if (nivPar < 0) debutM++
      if (parenth) {
        return s1.substring(0, debutM) + 'Math.pow(' + s1.substring(debutM + 1, finM) + ',' + exposant + ')' + s2
      }
      return s1.substring(0, debutM) + 'Math.pow(' + s1.substring(debutM, finM) + ',' + exposant + ')' + s2
    }

    // transformer x<sup>y</sup> en Math.pow(x,y)
    s = parsePuissance(s)
    // opérateurs logiques
    if (s == 'ou') { return '||' }
    if (s == 'et') { return '&&' }
    // autres
    let reg
    const t1 = ['racine', 'vrai', 'faux', '=', '≤', '≥', '≠', 'π', 'faire', 'alors', "'"]
    const t2 = ['Math.sqrt', 'true', 'false', '==', '<=', '>=', '!=', 'Math.PI', '', '', "\\'"]
    for (let i = 0; i < t1.length; i++) {
      reg = new RegExp(t1[i], 'gi')
      s = s.replace(reg, t2[i])
    }
    return s
  }

  // cherche mot1 suivi eventuellement de mot 2
  function cherche (ligneCode, i) {
    let j
    let continuer = true
    while (i < ligneCode.length && continuer) {
      for (j = 2; j < arguments.length; j++) {
        if (ligneCode[i] == arguments[j]) { continuer = false }
      }
      if (continuer) { i++ }
    }
    return i
  }

  function trouve (ligneCode, i, mot) {
    return cherche(ligneCode, i, mot) < ligneCode.length
  }

  function chercheFonction (s, contenu) {
    let parenth = 0; let parMax = 0; let i; let c = ''; let f = ''; let x = ''
    for (i = 0; i < s.length; i++) {
      c = s.charAt(i)
      switch (c) {
        case '(' :
          parenth++
          parMax = Math.max(parenth, parMax)
          break
        case ')' :
          parenth--
          break
        default :
          switch (parenth) {
            case 0:
              f += c
              break
            case 1 :
              x += c
              break
            default :
              break
          } // parenth
      } // c
    } // for
    if (parenth == 0 && parMax == 1 && f != '' && x != '') {
      setVar(f, 'non définie')
      return f + '=function(' + x + "){this.code='" + contenu + "';return " + contenu + '};'
    }
    setVar(s, 'non définie')
    return s + '=' + contenu + ';'
  }

  function parseAffecter (ligneCode) {
    const mots = { affecter: 1, stocker: 1, mettre: 1 }
    let contenu = ''; let js = ''; let j
    const ifleche = cherche(ligneCode, 1, '→')
    if (ifleche < ligneCode.length - 1) {
      ligneCode[ifleche] = gras(ligneCode[ifleche])
      for (let i = 0; i < ifleche; i++) {
        contenu += traduit(ligneCode[i])
      }
      return chercheFonction(ligneCode[ifleche + 1], contenu)
    }
    if ((ligneCode[0] in mots)) {
      ligneCode[0] = gras(ligneCode[0])
      j = cherche(ligneCode, 3, 'valeur')
      if (ligneCode[1] == 'à' || ligneCode[1] == 'dans') {
        if (j < ligneCode.length - 1) {
          ligneCode[j] = gras(ligneCode[j])
          ligneCode[1] = gras(ligneCode[1])
          return chercheFonction(ligneCode[2], traduit(ligneCode[j + 1]))
        } else { return false }
      } else {
        if (j < ligneCode.length - 1) {
          js = chercheFonction(ligneCode[3], traduit(ligneCode[j + 1]))
        } else {
          if (ligneCode[2] == 'à' || ligneCode[2] == 'dans') { ligneCode[2] = gras(ligneCode[2]) }
          js = chercheFonction(ligneCode[3], traduit(ligneCode[1]))
        }
        return js
      }
    }
    const i = cherche(ligneCode, 1, 'prend')
    if (i < ligneCode.length - 2) {
      j = cherche(ligneCode, i, 'valeur')
      if (j < ligneCode.length - 1) {
        ligneCode[i] = gras(ligneCode[i])
        ligneCode[j] = gras(ligneCode[j])
        return chercheFonction(ligneCode[i - 1], traduit(ligneCode[j + 1]))
      }
    }
    return false
  }

  // tableaux
  function parseAjouter (ligneCode) {
    const mots = { ajouter: 1, soustraire: 2, multiplier: 3, diviser: 4 }
    if ((!(ligneCode[0] in mots) || ligneCode[2] != 'à') && ligneCode[2] != 'dans' && ligneCode[2] != 'par') { return false }
    const mot = ligneCode[0]
    ligneCode[0] = gras(ligneCode[0])
    ligneCode[2] = gras(ligneCode[2])
    if (mots[mot] < 3) { return 'ALajouter(' + traduit(ligneCode[1]) + ',' + traduit(ligneCode[3]) + ',' + mots[mot] + ');' }
    return 'ALajouter(' + traduit(ligneCode[3]) + ',' + traduit(ligneCode[1]) + ',' + mots[mot] + ');'
  }

  function parseAfficher (ligneCode) {
    const mots = { afficher: 1, ecrire: 1, écrire: 1 }
    if (!(ligneCode[0] in mots)) { return false }
    let js = 'ALafficher('
    texteAffiche = ''
    ligneCode[0] = gras(ligneCode[0])
    for (let i = 1; i < ligneCode.length; i++) {
      if (i > 1) { js += ',' }
      js += "'" + traduit(ligneCode[i]) + "'"
      texteAffiche += ligneCode[i] + ' '
    }
    js += ');'
    return js
  };

  function parseDemander (ligneCode) {
    const mots = { demander: 1, saisir: 1, lire: 1, entrer: 1, choisir: 1 }
    if (!(ligneCode[0] in mots)) { return false }
    ligneCode[0] = gras(ligneCode[0])
    let js = ''; let j
    if (texteAffiche === '') {
      for (j = 1; j < ligneCode.length; j++) {
        js += ligneCode[j] + "=ALdemander('Entrer','" + ligneCode[j] + "');"
        setVar(ligneCode[j], 'Non définie')
      }
    } else {
      for (j = 1; j < ligneCode.length; j++) {
        js += ligneCode[j] + "=ALdemander('" + texteAffiche + '\\nEntrer ' + ligneCode[j] + "');"
        setVar(ligneCode[j], 'Non définie')
      }
    }
    return js
  };

  function parseSi (ligneCode) {
    if (ligneCode[0] != 'si') { return false }
    ligneCode[0] = gras(ligneCode[0])
    let js = 'if('
    for (let i = 1; i < ligneCode.length; i++) {
      if (ligneCode[i] != 'alors') { js += traduit(ligneCode[i]) } else { ligneCode[i] = gras(ligneCode[i]) }
    }
    js += '){'
    return js
  };

  // enleve le premier terme si c’est le mot "alors" ou le mot "faire"
  // ces mots n’ont pas d’équivalent javascript
  function parseAlorsFaire (ligneCode) {
    if (ligneCode[0] != 'alors' && ligneCode[0] != 'faire') { return ['', ligneCode] }
    const s = gras(ligneCode[0])
    if (ligneCode.length == 1) { ligneCode[0] = '' } else { ligneCode.shift() }
    return [s, ligneCode]
  };

  function parseSinon (ligneCode) {
    if (ligneCode[0] != 'sinon') { return false }
    ligneCode[0] = gras(ligneCode[0])
    const js = '}else{'
    return js
  };

  function parseFin (ligneCode) {
    if (ligneCode[0] == 'finsi' || ligneCode[0] == 'finpour' || ligneCode[0] == 'fsi' || ligneCode[0] == 'fpour') {
      ligneCode[0] = gras(ligneCode[0])
      return '}'
    }
    if (ligneCode[0] == 'fin' && (trouve(ligneCode, 1, 'si') || trouve(ligneCode, 1, 'pour'))) {
      ligneCode[0] = gras(ligneCode[0])
      let i = cherche(ligneCode, 1, 'si')
      if (i >= ligneCode.length) { i = cherche(ligneCode, 1, 'pour') }
      if (i < ligneCode.length) { ligneCode[i] = gras(ligneCode[i]) }
      return '};'
    }
    return false
  };

  function parseTantQue (ligneCode) {
    const mots = { tant: 1, tantque: 1 }
    if (!(ligneCode[0] in mots)) { return false }
    let d = 1
    if (ligneCode[0] == 'tant') {
      ligneCode[1] = gras(ligneCode[1])
      d++
    }
    ligneCode[0] = gras(ligneCode[0])
    let js = 'while('
    for (let i = d; i < ligneCode.length; i++) {
      if (ligneCode[i] != 'faire') { js += traduit(ligneCode[i]) } else { ligneCode[i] = gras(ligneCode[i]) }
    }
    return js + '){'
  }

  function parseFinTantQue (ligneCode) {
    if ((ligneCode[0] == 'fintantque' || ligneCode[0] == 'ftantque' || ligneCode[0] == 'fin') && (trouve(ligneCode, 1, 'tant') || trouve(ligneCode, 1, 'tantque'))) {
      ligneCode[0] = gras(ligneCode[0])
      let i = cherche(ligneCode, 1, 'tant')
      if (i < ligneCode.length - 1) {
        ligneCode[i] = gras(ligneCode[i])
        ligneCode[i + 1] = gras(ligneCode[i + 1])
      } else {
        i = cherche(ligneCode, 1, 'tantque')
        if (i < ligneCode.length - 1) { ligneCode[i] = gras(ligneCode[i]) }
      }
      return '};'
    }
    return false
  }

  function parsePour (ligneCode) {
    if (ligneCode[0] != 'pour') { return false }
    ligneCode[0] = gras(ligneCode[0])
    let js = 'for (' + ligneCode[1] + '='
    setVar(ligneCode[1], 'Non définie')
    let i = 2
    i = cherche(ligneCode, i, 'de')
    i++
    if (i >= ligneCode.length) { return false }
    ligneCode[i - 1] = gras(ligneCode[i - 1])
    js += ligneCode[i] + ';'
    i = cherche(ligneCode, i, 'jusque', 'jusqu`à', 'à')
    i++
    if (i >= ligneCode.length) { return false }
    ligneCode[i - 1] = gras(ligneCode[i - 1])
    js += ligneCode[1] + '<=' + traduit(ligneCode[i]) + ';' + ligneCode[1] + '++){'
    i = cherche(ligneCode, i, 'faire')
    if (i < ligneCode.length) { ligneCode[i] = gras(ligneCode[i]) }
    return js
  }

  function parseRepeter (ligneCode) {
    if (ligneCode[0] != 'répéter') { return false }
    ligneCode[0] = gras(ligneCode[0])
    return 'do{'
  }

  function parseJusque (ligneCode) {
    let i = cherche(ligneCode, 0, 'jusque', 'jusqu`à')
    if (i != 0) { return false }
    ligneCode[0] = gras(ligneCode[0])
    let js = '} while(!('
    for (i = 1; i < ligneCode.length; i++) { js += traduit(ligneCode[i]) }
    js += '));'
    return js
  }

  function modeTortue (activer) {
    if (((!w.ALtortueActive && activer) || !activer) && w.ALtortueActive) {
      modeTortue()
    }
  }

  function parseAvancer (ligneCode) {
    return parse(ligneCode, { avancer: 1, avance: 1 })
  }
  function parse (ligneCode, mots) {
    if (!(ligneCode[0] in mots)) { return false }
    modeTortue(true)
    ligneCode[0] = gras(ligneCode[0])
    let js = 'ALtortue.avance('
    const i = cherche(ligneCode, 1, 'de')
    if (i >= ligneCode.length) {
      js += ligneCode[1]
    } else {
      js += ligneCode[i + 1]
      ligneCode[i] = gras(ligneCode[i])
    }
    js += ');'
    return js
  }

  function parseReculer (ligneCode) {
    const mots = { reculer: 1, recule: 1 }
    if (!(ligneCode[0] in mots)) { return false }
    modeTortue(true)
    ligneCode[0] = gras(ligneCode[0])
    let js = 'ALtortue.avance('
    const i = cherche(ligneCode, 1, 'de')
    if (i >= ligneCode.length) { js += '-' + ligneCode[1] } else {
      js += '-' + ligneCode[i + 1]
      ligneCode[i] = gras(ligneCode[i])
    }
    js += ');'
    return js
  }

  function parseTourner (ligneCode) {
    const mots = {
      tourner: 1,
      tourne: 1
    }
    if (!(ligneCode[0] in mots)) { return false }
    modeTortue(true)
    ligneCode[0] = gras(ligneCode[0])
    let js = 'ALtortue.tourne('
    let i = cherche(ligneCode, 1, 'droite')
    if (i < ligneCode.length) {
      js += '-' // tourner à droite
    } else {
      i = cherche(ligneCode, 1, 'gauche')
    }
    if (i < ligneCode.length) {
      ligneCode[i] = gras(ligneCode[i])
    } else {
      i = 0
    }
    const j = cherche(ligneCode, 1, 'de')
    if (j < ligneCode.length) {
      ligneCode[i] = gras(ligneCode[i])
      i = Math.max(i, j)
    }
    js += ligneCode[i + 1]
    js += ');'
    return js
  }

  function parseSauter (ligneCode) {
    return parse(ligneCode, { sauter: 1, saute: 1 })
  }

  function parseManger (ligneCode) {
    if (!(ligneCode[0] == 'manger' || ligneCode[0] == 'mange' || ligneCode[0] == 'départ')) { return false }
    modeTortue(true)
    ligneCode[0] = gras(ligneCode[0])
    return 'ALtortue.mange();'
  }

  function parseDessiner (ligneCode) {
    const mots = { point: 1, segment: 1, cercle: 1, rectangle: 1, couleur: 1 }
    if (!(ligneCode[0] in mots)) { return false }
    let js = ''
    dessinActif = true
    switch (ligneCode[0]) {
      case 'point' :
        js = 'ALrep.point(' + ligneCode[1] + ',' + ligneCode[2] + ');'
        break
      case 'segment' :
        js = 'ALrep.segment(' + ligneCode[1] + ',' + ligneCode[2] + ',' + ligneCode[3] + ',' + ligneCode[4] + ');'
        break
      case 'rectangle' :
        js = 'ALrep.rect(' + ligneCode[1] + ',' + ligneCode[2] + ',' + ligneCode[3] + ',' + ligneCode[4] + ',false);'
        break
      case 'cercle' :
        js = 'ALrep.cercle(' + ligneCode[1] + ',' + ligneCode[2] + ',' + ligneCode[3] + ');'
        break
      case 'couleur' :
        js = "ALrep.stroke('" + ligneCode[1] + "');"
        break
    }
    ligneCode[0] = gras(ligneCode[0])
    return js
  }

  let faireFichier = true
  function parseService (ligneCode) {
    let js
    switch (ligneCode[0]) {
      case 'démo' :
        js = 'ALservice(0);'
        break
      case 'repas' :
        js = 'ALservice(1);'
        faireFichier = false
        break
      case 'itinéraire' :
        js = 'ALservice(2);'
        faireFichier = false
        break
      case 'démo_repas' :
        js = 'ALservice(3);'
        break
      case 'démo_itinéraire' :
        js = 'ALservice(4);'
        break
      default :
        return false
    }
    ligneCode[0] = gras(ligneCode[0])
    return js
  }

  function parseControle (ligneCode) {
    if (ligneCode[0] != 'contrôler') { return false }
    controles = ligneCode[1]
  }

  function parseDebutFin (ligneCode) {
    if ((ligneCode.length > 1 || ligneCode[0] != 'début_algo') && ligneCode[0] != 'fin_algo') {
      return false
    }
    return 'ALrien();'
  }

  // laisser parseDemander au début
  const fonctions = [parseDemander, parseAffecter, parseAjouter, parseAfficher, parseSi, parseSinon, parseFin, parseTantQue, parseFinTantQue, parsePour, parseRepeter, parseJusque, parseAvancer, parseReculer, parseTourner, parseSauter, parseManger, parseDessiner, parseService, parseControle, parseDebutFin]
  const indentations = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 2], [-2, 2], [-2, 0], [0, 2], [-2, 0], [0, 2], [0, 2], [-2, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]

  function normalise (s) {
    // enlève les espaces multiples et  les espaces dans les parenthèses
    let t = ''; let parenthese = 0; let dejaBlanc = false; let c
    for (let i = 0; i < s.length; i++) {
      c = s.charAt(i)
      if (c == '(') { parenthese++ }
      if (c == ')') { parenthese-- }
      if (parenthese > 0) { dejaBlanc = true }
      if (c == ' ') {
        if (!dejaBlanc) {
          dejaBlanc = true
          t += c
        }
      } else {
        dejaBlanc = false
        t += c
      }
    }
    // a éviter si ok
    s = t
    s = s.toLowerCase()
    s = s.replace(/&lt;/gi, '<')
    s = s.replace(/&gt;/gi, '>')
    s = s.replace(/&le;/gi, '<=')
    s = s.replace(/&ge;/gi, '>=')
    s = s.replace(/'/g, '`')
    return s
  }

  // coloration des variables
  function coloreVar (s) {
    function spe (c) {
      const t = ['+', '-', '/', '*', '%', '(', ')', '[', ']', '<', '>', '=', '≤', '≥', '≠', '→', 'π']
      for (let i = 0; i < t.length; i++) {
        if (c == t[i]) { return true }
      }
      return false
    }
    let j = 0; let s1 = ''; let c
    while (j < s.length) {
      c = ''
      while (j < s.length && !spe(s.charAt(j))) {
        c += s.charAt(j)
        j++
      }
      if (c in vars) { c = '££v' + c + '££w' }
      s1 += c
      while (j < s.length && spe(s.charAt(j))) {
        s1 += s.charAt(j)
        j++
      }
    }
    return s1
  }

  modeTortue(false)
  vars = {}
  numLignes = []
  dessinActif = false

  // charger le texte de l’algorithme
  let prog = litSource()
  prog = normalise(prog)
  const codes = []
  let lignes = prog.split('//br;')

  // initialisation du pas à pas
  if (!preservePasApas) {
    // non pas à pas
    papReset()
    document.getElementById('ALpasapas').style.display = 'none'
    // enleve début_algo et fin_algo
    if (lignes[0] == 'début_algo') { lignes.shift() }
    if (lignes[lignes.length - 1] == 'fin_algo') { lignes.pop() }
  } else {
    //  pas à pas
    // introduit les lignes "début_algo" et "fin algo"
    if (lignes[0] != 'début_algo') {
      if (lignes[0] == '' || lignes[0] == ' ') { lignes[0] = 'début_algo' } else {
        const debut = ['début_algo']
        lignes = debut.concat(lignes)
      }
    }
    if (lignes[lignes.length - 1] == '' || lignes[lignes.length - 1] == ' ') { lignes[lignes.length - 1] = 'fin_algo' } else if (lignes[lignes.length - 1] != 'fin_algo') { lignes.push('fin_algo') }
  }
  film = []
  filmTortueEfface()
  filmTortueSetElt([0])
  filmDessinEfface()
  filmDessinSetElt([0])

  // suppression des lignes vides
  for (let i = lignes.length - 1; i >= 0; i--) {
    if (lignes[i] == '') {
      lignes.splice(i, 1)
    }
  }

  for (let i = 0; i < lignes.length; i++) {
    // elimine blancs au début et à la fin
    lignes[i] = lignes[i].replace(/^\s+/g, '').replace(/\s+$/g, '')
    codes.push(lignes[i].split(' '))
  }
  // traduction algo en javascript, coloration et indentation du source
  let j, k
  const tabjs = []
  let indente = 0
  let indentation = ''
  let tab
  let retour = []
  w.ALformatees = []
  let ligne = ''

  for (let i = 0; i < codes.length; i++) {
    retour = false
    tab = parseAlorsFaire(codes[i]) // elimine "alors" et "faire"
    for (let j = 0; j < fonctions.length; j++) {
      retour = fonctions[j](tab[1])
      // gestion du prompt sur 2 lignes
      if (j == 0) {
        texteAffiche = ''
      }
      if (retour) {
        if (preservePasApas) {
          tabjs.push(retour + ' ALfilmer(' + i + ');')
        } else {
          tabjs.push(retour + 'ALcompte();')
        }
        numLignes.push(i)
        break
      }
    }
    if (tab[0] != '') {
      // on réintègre "alors" ou "faire"
      codes[i].unshift(tab[0])
    }

    if (!retour || retour == 'ALrien();') {
      ligne = codes[i].join(' ')
      indentation = ''
      // correction de l’indentation
      // si la ligne commence par "alors" ou "faire"
      let indenteAlors
      if (tab[0] != '') {
        indenteAlors = Math.max(0, indente - 2)
      } else {
        indenteAlors = indente
      }
      for (k = 0; k < indenteAlors; k++) indentation += ' '
      if (!retour) {
        w.ALformatees.push(indentation + "<span class='comm'>" + special(ligne) + '</span>')
      } else {
        w.ALformatees.push(indentation + "<span class='deb'>" + special(ligne) + '</span>')
      }
    } else {
      indente += indentations[j][0]
      indentation = ''
      for (k = 0; k < indente; k++) { indentation += ' ' }
      for (k = 0; k < codes[i].length; k++) { codes[i][k] = coloreVar(codes[i][k]) }
      w.ALformatees.push(indentation + special(codes[i].join(' ')))
      indente += indentations[j][1]
    }
  }
  if (w.ALtortueActive) {
    ALnouvelleTortue()
  }
  ecritSource(w.ALformatees.join('<br>'))
  if (faireFichier) { faitFichier() } // préparation sauvegarde
  return tabjs.join('\n')
}

function pasApas () {
  if (clic) return
  // empêcher les ralentis tortue simultanés
  if (w.ALtortueActive) {
    const d = new Date()
    if (indexPaP) {
      if (d - indexPaP < getFreqTortue() * 40) { return }
    }
    indexPaP = d
  }
  voirDiv('ALaide', false)
  papInc()
  const indexPap = papGetIndex()
  if (indexPap == 0) {
    try {
      lancer(true)
      if (!w.ALtimer) {
        // eslint-disable-next-line no-alert
        alert('Vous pourvez maintenant voir le déroulement de l’algorithme.\nen appuyant à nouveau sur la trace de pas autant de fois qu’il le faudra.')
      }
      if (w.ALtortueActive) { ALnouvelleTortue() }
      if (dessinActif) w.ALrep = new ALrepere()
    } catch (err) {
      console.error(err)
    }
  }
  if (indexPap >= film.length) {
    if (w.ALtimer) {
      const enBoucle = document.getElementById('ALenBoucle')
      if (!enBoucle.checked) { clearInterval(w.ALtimer) }
    }
    parseAlgo()
  }
  let i
  if (indexPap > -1) {
    i = film[indexPap][0]
  } else {
    return
  }
  const pasapas = document.getElementById('ALpasapas')
  pasapas.style.display = 'block'
  pasapas.innerHTML = '<b>Variables et fonctions</b><br>' + film[indexPap][1]
  //  surligne l’instruction
  souligne(i, 'pas')
  if (w.ALtortueActive) {
    const filmElt = filmTortueGetElt(indexPap)
    switch (filmElt[0]) {
      case 0:
        break
      case 1:
        w.ALtortue.tourneRalenti(filmElt[1])
        break
      case 2:
        w.ALtortue.avanceRalenti(filmElt[1], filmElt[2])
        break
      case 3:
        w.ALtortue.mange()
        break
    }
  }
  // dessin
  if (dessinActif) {
    const filmDessinElt = filmDessinGetElt(indexPap)
    switch (filmDessinElt[0]) {
      case 0:
        break
      case 1:
        w.ALrep.stroke(filmDessinElt[1])
        break
      case 2:
        w.ALrep.segment(filmDessinElt[1], filmDessinElt[2], filmDessinElt[3], filmDessinElt[4])
        break
      case 3:
        w.ALrep.cercle(filmDessinElt[1], filmDessinElt[2], filmDessinElt[3])
        break
      case 4:
        w.ALrep.rect(filmDessinElt[1], filmDessinElt[2], filmDessinElt[3], filmDessinElt[4])
        break
      case 5:
        w.ALrep.point(filmDessinElt[1], filmDessinElt[2])
        break
    }
  }
}

function pasApasAuto (elt) {
  function progress (delai) {
    const pbar = document.getElementById('ALpbar')
    let pcnt = 0
    const intervalId = setInterval(function () {
      pcnt += 2
      if (pcnt <= pbar.max) {
        pbar.value = pcnt
      } else {
        pbar.value = 0
        clearInterval(intervalId)
      }
    }, delai / 50)
  }
  let delai = document.getElementById('ALdelai').value
  delai = parseInt(delai) * 1000
  progress(delai)
  setTimeout(metronome, delai)
}

function setVar (nom, valeur) {
  if (nom.indexOf('[') > -1) { return }
  vars[nom] = valeur
  w.ALvarAnciennes[nom] = valeur
  w[nom] = valeur
}

function souligne (num, nomClasse) {
  const ligne = w.ALformatees[num]
  w.ALformatees[num] = "<span id='aScroller' class='" + nomClasse + "'>" + ligne + '</span>'
  ecritSource(w.ALformatees.join('<br>'))
  w.ALformatees[num] = ligne
  if (document.getElementById('aScroller')) {
    document.getElementById('aScroller').scrollIntoView(false)
  }
}

function special (prog) {
  const t = ['<', '>', '££b', '££c', '££v', '££w']
  const u = ['&lt;', '&gt;', "<span class='mot'>", '</span>', "<span class='variable'>", '</span>']
  let reg
  for (let i = 0; i < t.length; i++) {
    reg = RegExp(t[i], 'g')
    prog = prog.replace(reg, u[i])
  }
  return prog
}

function stopMetronome () {
  setFreqTortue(25)
  if (!w.ALtimer) { return false }
  clearInterval(w.ALtimer)
  const enBoucle = document.getElementById('ALenBoucle')
  if (!enBoucle.checked) { enBoucle.checked = false }
  parseAlgo()
  if (w.ALtortue) w.ALtortue.reinitialise()
  return true
}

function voirDiv (div, ouvrir) {
  if (div.charAt) { div = document.getElementById(div) }
  if ((div.style.display === 'block' || arguments.length === 2) && ouvrir == false) {
    div.style.display = 'none'
  } else {
    div.style.display = 'block'
  }
}

// mise à jour de vars (jamais utilisé)
// function ALvinitialiseVars () {
//   for (const prop in Object.key(vars)) {
//     vars[prop] = null
//   }
// }

w.ALafficher = afficher
w.ALchargeDemo = function chargeDemo (sel) {
  const d = document.getElementById('ALgauche')
  const elt = chercheElement('ALdemos', 'PRE', sel.options.selectedIndex)
  d.innerHTML = '<pre>\n' + elt.innerHTML + '\n</pre>'
  parseAlgo()
}
w.ALcompte = compte
w.ALfaitPrecision = faitPrecision
w.ALfilmer = function filmer (numLigne) {
  if (papGetIndex() === -2) {
    // on filme seulement en mode pas à pas
    return
  }
  compte()
  const ligne = []
  let message = ''
  let nom, valeur, ajout
  // numero de la ligne du programme
  ligne.push(numLigne)
  // vars est la liste des noms des variables utilisateur
  for (nom in vars) {
    try {
      // w[nom] est la valeur de la variable dont le nom est donné
      valeur = w[nom]
      vars[nom] = valeur
    } catch (err) {
      valeur = 'non définie'
    }
    if ((typeof valeur) === 'function') {
      // eslint-disable-next-line new-cap
      const g = new valeur()
      valeur = g.code
    }
    if (String(vars[nom]) !== String(w.ALvarAnciennes[nom])) {
      ajout = "<span class='barre'>" + nom + ' : ' + w.ALvarAnciennes[nom] + '</span><br>'
      ajout += "<span class='change'>" + nom + ' : ' + valeur + '</span>'
      w.ALvarAnciennes[nom] = vars[nom]
    } else { ajout = nom + ' : ' + valeur }
    ajout += '<br>'
    message += ajout
  }
  ligne.push(message)
  film.push(ligne)
  filmTortueSetElt([0])
  filmDessinSetElt([0])
}
w.ALparseAlgo = parseAlgo
// correction du bug qui supprime le pre
w.ALpre = function pre (div, evt) {
  if (evt.keyCode != 8) { // backspace
    return
  }
  const elt = div.lastChild
  if (!elt || !elt.tagName) {
    ALinsere('<pre>&nbsp;</pre>')
  }
}

// function ALtransfere (elt) {
//   let texte = elt.textContent
//   texte = special(texte)
//   if (confirm('Transférer ce programme à droite en écrasant le programme courant ?')) {
//     ecritSource(texte)
//     ALformate()
//   }
// }

w.ALajouter = function ALajouter (y, x, op) {
  if (x.push && op == 1) { x.push(y) } else {
    switch (op) {
      case 1:
        w[x] += y
        break
      case 2:
        w[x] -= y
        break
      case 3:
        w[x] *= y
        break
      case 4:
        w[x] /= y
        break
    }
  }
}

// function ALretour () {
//   document.getElementById('doc').style.display = 'none'
//   document.getElementById('aide').style.display = 'block'
//   document.getElementById('ALRetour').style.display = 'none'
// }

// function ALvaEtVient (elt, fermer) {
//   let e = elt.nextSibling
//   while (!e.tagName || e.tagName.toUpperCase() != 'DIV') { e = e.nextSibling }
//   if (e.style.display == 'none' && !fermer) {
//     e.style.display = 'block'
//     elt.scrollIntoView(true)
//   } else {
//     e.style.display = 'none'; b
//     e = e.firstChild; outons
//     while (e) {
//       ALvaEtVient(e, true)
//       e = e.nextSibling
//     }
//   }
// }

w.ALmail = function ALmail () {
  let chaine_mail = 'mailto:?subject= Programme javascript'
  chaine_mail += '&body='
  let s = litSource(true)
  const t1 = ['<br>', '&lt;', '&gt;', '&le;', '&ge;', '&ne;', '&pi;', '&rarr;', '&']
  const t2 = ['\n', '<', '>', '≤', '≥', '≠', 'π', '→', '\\&']
  for (const [i, t] of t1.entries()) {
    const reg = new RegExp(t, 'gi')
    s = s.replace(reg, t2[i])
  }
  chaine_mail += encodeURIComponent(s)
  location.href = chaine_mail
}

w.ALservice = function ALservice (i) {
  let s
  switch (i) {
    case 0: // construction d’une démo
      s = litSource(true)
      var reg
      var t1 = ['<', '>', '≤', '≥', '≠', 'π', '→', 'démo', 'taper un algorithme ici :\n', '\n']
      var t2 = ['&lt;', '&gt;', '&le;', '&ge;', '&ne;', '&pi;', '&rarr;', '', '', '\\n']
      for (let i = 0; i < t1.length; i++) {
        reg = new RegExp(t1[i], 'gi')
        s = s.replace(reg, t2[i])
      }
      s = '"' + s + '"'
      break
    case 1: // construction d’un repas tortue à sauvgarder
      faitFichier('repas', '[' + w.ALtortue.chaineRepas + ']')
      break
    case 2: // construction d’un itinéraire pour la tortue à sauvgarder
      faitFichier('itineraire', w.ALtortue.chaineDessin + ']')
      break
    case 3: // construction d’un repas tortue à intégrer dans le source
      s = 'Dans le code-source de PSyLVIA, cherchez le mot lesRepas,\npuis collez à l’endroit indiqué l’instruction suivante :\n\nlesRepas.push([' + w.ALtortue.chaineRepas + ']);'
      break
    case 4: // construction d’un itinéraire pour la tortue à intégrer dans le source
      s = 'Dans le code-source de PSyLVIA, cherchez le mot lesDessins,\npuis collez à l’endroit indiqué l’instruction suivante :\n\nlesDessins.push(' + w.ALtortue.chaineDessin + ']);'
      break
  }
  if (i == 0 || i > 2) {
    const w2 = w.open()
    const newDoc = w2.document.open('text')
    newDoc.write(s)
    newDoc.close()
  }
}

w.ALimprime = function ALimprime () {
  const w2 = w.open()
  const s = document.getElementById('ALgauche').innerHTML
  w2.document.write(s)
  w2.print()
}

// sauvegarde d’urgence par cookie
// function ALecrireCookie (nom, val) {
//   const date = new Date()
//   date.setHours(date.getHours() + 1)
//   // date.setFullYear(date.getFullYear()+1);
//   document.cookie = nom + '=' + escape(val) + ';expires=' + date
// }

// function ALlireCookie (nom) {
//   let s = document.cookie
//   let i = s.indexOf(nom, 0)
//   if (i == -1) { return '' }
//   s = s.substring(i)
//   i = s.indexOf('=', 0)
//   const j = s.indexOf(';', 0)
//   if (j != -1) { s = s.substring(i + 1, j) } else { s = s.substring(i + 1) }
//   return unescape(s)
// }

// pas utilisé dans le contexte j3p
// w.ALsauveUrgence = function ALsauveUrgence () {
//   let donnee = litSource()
//   donnee = special(donnee)
//   const t = donnee.split('//br;')
//   if (t[0] == 'début_algo') { t.shift() }
//   if (t[t.length - 1] == 'fin_algo') { t.pop() }
//   donnee = t.join('//br;')
//   // sauvegarde d’urgence par cookie valable 1 heure
//   ALecrireCookie('psylvia_urgence', donnee)
// }

// pas utilisé dans le contexte j3p
// function ALrestaureUrgence () {
//   const s = ALlireCookie('psylvia_urgence')
//   if (!s) { return false }
//   if (confirm("Sauvegarde d’urgence de l’algorithme détectée.\nRestaurer ?")) {
//     ecritSource(s)
//     parseAlgo()
//     return true
//   }
//   return false
// }

// sauvegarde par lecture/écriture sur le disque

w.ALouvrir = function ALouvrir () {
  document.getElementById('ALstock').style.display = 'block'
}

w.ALsauveIE = function sauveIE () {
  const ifr = document.getElementById('ALiframe')
  ifr.contentWindow.document.r = ifr.contentWindow.document.execCommand('SaveAs', false, 'algo.txt')
  if (!ifr.contentWindow.document.r) {
    // eslint-disable-next-line no-alert
    alert('Echec de la sauvegarde')
  }
}

w.ALlitFichier = function litFichier (fileInput) {
  try {
    const reader = new FileReader()
    reader.readAsText(fileInput.files[0])
    reader.onload = function () {
      let s = reader.result
      s = s.replace(/\n/g, ' ')
      s = s.replace(/\r/g, '')
      const json = JSON.parse(s)
      const initTortue = [300, 300]
      if (json.algo) {
        verifs = {}
        if (json.controles) {
          verifs = json.controles
        }
        ecritSource(json.algo)
        parseAlgo()
      } else
        if (json.repas) {
          modeTortue()
          Tortue.prototype.repasLu = true
          // eslint-disable-next-line no-eval
          Tortue.prototype.repas = eval(json.repas)
          // bug ???---------------------------------------
          Tortue.prototype.dessin = initTortue
          w.ALtortue.positionneImg()
        }
      if (json.itineraire) {
        modeTortue()
        Tortue.prototype.dessinLu = true
        // eslint-disable-next-line no-eval
        Tortue.prototype.dessin = eval(json.itineraire)
        // bug ??? ---------------------------------------
        Tortue.prototype.repas = initTortue
        w.ALtortue.dessineItineraire()
        w.ALtortue.positionneImg()
      }
    }
  } catch (e) {
    console.error(e)
    j3pShowError('fonction non supportée par le navigateur : ' + e.message)
  }
  document.getElementById('ALstock').style.display = 'none'
}

// fin sauvegarde

w.ALfermer = function ALfermer (id) {
  const n = document.getElementById(id)
  n.style.display = 'none'
}

w.ALeffacer = function ALeffacer (sortie) {
  // let message
  // if (sortie) {
  //   message = 'Effacer les sorties'
  // } else {
  //   message = 'Effacer l’algorithme'
  // }
  // if (!confirm(message)) return
  if (sortie) {
    const b = document.getElementById('ALdroite')
    b.innerHTML = '<p><b>Sorties</b></p>'
    if (w.ALtortueActive) { ALnouvelleTortue() }
    return
  }
  const h = document.getElementById('ALgauche')
  h.innerHTML = ''
  h.focus()
  ALinsere('<pre>Taper un algorithme ici:<br></pre>')
  parseAlgo()
  h.blur()
  document.getElementById('ALpasapas').style.display = 'none'
  verifs = {}
}

// convertit une chaine en nombre SI PERTINENT
function ALnombre (s) {
  const n = parseInt(s)
  const x = parseFloat(s)
  if (isNaN(n) && isNaN(x)) { return s }
  if (x == n) { return n }
  return x
}

w.ALdemander = function ALdemander () {
  let message = ''
  for (let i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message)
  if (!x) {
    w.ALstop = true
    // introduire une erreur avec throw à la place
    throw Error('Programmme arrêté par l’utilisateur')
    // eval("x=avorte programme");
  }
  const s = x + ' '
  const t = s.split(/[,;]+/g)
  if (t.length < 2) { return ALnombre(x) }
  for (let i = 0; i < t.length; i++) {
    t[i] = ALnombre(t[i])
  }
  return t
}

// function ALelement (type, cible, classe) {
//   const elem = document.createElement(type)
//   if (classe) { elem.className = classe }
//   cible.appendChild(elem)
//   return elem
// }

function ALinsere (html) {
  const ie = w.ActiveXObject
  if (!ie) {
    document.execCommand('insertHTML', false, html)
    document.getElementById('ALgauche').focus()
  } else {
    // IE9 and non-IE
    const sel = w.getSelection()
    if (sel.getRangeAt && sel.rangeCount) {
      let range = sel.getRangeAt(0)
      range.deleteContents()
      // Range.createContextualFragment() would be useful here but is
      // non-standard and not supported in all browsers (IE9, for one)
      const el = document.createElement('div')
      el.innerHTML = html
      const frag = document.createDocumentFragment(); let node; let lastNode
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node)
      }
      range.insertNode(frag)
      // Preserve the selection
      if (lastNode) {
        range = range.cloneRange()
        range.setStartAfter(lastNode)
        range.collapse(true)
        sel.removeAllRanges()
        sel.addRange(range)
      }
    }
  }
}

w.ALsup = function ALsup (b) {
  document.execCommand('superscript', false, null)
  document.getElementById('ALgauche').focus()
}

function ALafficheBalai (cible) {
  const img = document.getElementById(cible)
  img.setAttribute('src', 'data:image/png;base64,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')
}

// fonctions mathématiques préprogrammées

w.abs = function abs (x) {
  return Math.max(-x, x)
}

w.ent = function ent (x) {
  return Math.floor(x)
}

w.sin = function sin (x) {
  return Math.sin(x)
}

w.cos = function cos (x) {
  return Math.cos(x)
}

w.tan = function tan (x) {
  return Math.tan(x)
}

w.ln = function ln (x) {
  return Math.log(x)
}

w.log = function log (x) {
  return Math.log(x) / Math.log(10)
}

w.exp = function exp (x) {
  return Math.exp(x)
}

w.bernoulli = function bernoulli (p) {
  if (Math.random() < p) { return 1 }
  return 0
}

w.aleatoire = function aleatoire (debut, fin) {
  const ampl = parseFloat(fin) - parseFloat(debut)
  const x = Math.random() * ampl + parseFloat(debut)
  return Math.round(x)
}

w.aleauniforme = function aleauniforme (debut, fin) {
  const ampl = parseFloat(fin) - parseFloat(debut)
  const x = Math.random() * ampl + parseFloat(debut)
  return x
}

w.aleanormal = function aleanormal (m, s) {
  return s * Math.sqrt(-2 * Math.log(Math.random())) * Math.cos(2 * Math.PI * Math.random()) + m
}

// tortue

function ALnouvelleTortue () {
  const droite = document.getElementById('ALdroiteTortue')
  while (droite.firstChild) { droite.removeChild(droite.firstChild) }
  w.ALtortueActive = false
  w.ALtortue = null
  modeTortue()
}

// --------------------- fonctions de dessin --------------------------------

w.ALdimGraph = function ALdimGraph () {
  w.ALfenetre.xMin = document.getElementById('ALxMin').value
  w.ALfenetre.yMin = document.getElementById('ALyMin').value
  w.ALfenetre.xMax = document.getElementById('ALxMax').value
  w.ALfenetre.yMax = document.getElementById('ALyMax').value
  w.ALfenetre.stroke = document.getElementById('ALstroke').value
  w.ALfenetre.axes = document.getElementById('ALaxes').checked
  document.getElementById('ALdimFenetre').style.display = 'none'
}

// initialisation générale

// fonction vide ajoutée pour J3P (qui sera éventuellement initialisée)
w.ALactionFusee = () => undefined

export default function Psylvia () {
  this.aMasquer = {}
  this.demos = {}
  this.precis = 0
  this.haut = 400
}

// réglage de la précision
Psylvia.prototype.precision = function (n) {
  this.precis = n
}

// variable à surveiller
Psylvia.prototype.surveiller = function (nom, valeur) {
  verifs[nom] = valeur
}

// vérifier qu’une variable a bien pris la valeur attendue
Psylvia.prototype.verifier = function (nom) {
  return isVerifOk[nom]
}

// ajouter une démo dans la liste
Psylvia.prototype.ajouteDemo = function (titre, algo) {
  this.demos[titre] = algo
}

// masquer certains élements
Psylvia.prototype.masquer = function () {
  const noms = {
    demos: 'ALselectDemo',
    repere: 'ALparamGraph',
    precision: 'ALprecis',
    ouvrir: 'ALiconeOuvrir',
    enregistrer: 'ALiconeEnregistrer',
    courrier: 'ALiconeCourriel',
    imprimer: 'ALiconeImprimer',
    repas: 'ALrepasTortue',
    balai: 'ALeffaceG',
    tortue: 'ALboutonTortue'
  }
  for (let i = 0; i < arguments.length; i++) { this.aMasquer[noms[arguments[i]]] = true }
}

// action en cas de clic sur la fusee
Psylvia.prototype.actionFusee = function (fonction) {
  actionFusee = fonction
}

Psylvia.prototype.hauteur = function (n) {
  this.haut = Math.max(n, 350)
}

// installation de PSyLVIA dans la page
Psylvia.prototype.installer = function (divGauche, divDroite, algo) {
  if (divGauche.charAt) { divGauche = document.getElementById(divGauche) }
  if (divDroite.charAt) { divDroite = document.getElementById(divDroite) }
  // hauteur des cadres
  divGauche.style.height = this.haut + 'px'
  divDroite.style.height = this.haut + 'px'

  // code HTML récupéré
  // elements droits
  let strVar = ''

  strVar += '<div id="ALdroite">'
  strVar += '      <p><b>Sorties :</b> </p>'
  strVar += '</div>  '

  strVar += '<div id="ALprecis">'
  strVar += 'Précision :'
  strVar += '<input style="width:2em;" id="ALinputPrecis" value="6" onchange="ALfaitPrecision()" > '
  strVar += '</div>'

  strVar += '<div id="ALafficheCoord">'
  strVar += '</div>'

  w.ALdroiteTortueOnClick = function () {
    if (papGetIndex() > -1) voirDiv('ALpasapas')
  }
  strVar += '<div id="ALdroiteTortue" onclick="ALdroiteTortueOnClick()">'
  strVar += '</div>'
  strVar += '<div id="ALrepasTortue">'
  strVar += ' Repas  et itinéraires :'
  w.ALinitialiseTortue = initialiseTortue
  strVar += ' <select id="ALlisteRepas" onchange="ALinitialiseTortue()">'
  strVar += ' </select>'
  strVar += '</div>'

  strVar += '<div id="ALpasapas">'
  strVar += '</div>   '

  strVar += '<img alt="effacer" id="ALeffaceD" title="Effacer les sorties" onclick="ALeffacer(true)"  />'
  strVar += '<!--    AIDE EN LIGNE   -->'
  strVar += '<div id="ALaide">'
  strVar += '<object   data="aide.html"></object>'
  strVar += '</div>'
  strVar += '<div id="ALicones">'
  strVar += '<img id="ALiconeOuvrir" title="Ouvrir un programme" onclick="ALouvrir()" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9oFAg8rEH0DeCIAAALjSURBVDjLzZLNaytVGIefMzmZaTO57W1za7UfduOluBCuggt3Lt0UumkX3bpWCkLXXQn9E/QPcO2lILiyIFyhKly4V5QSjXqJk2maaTKTTCfzcY6LZiZN04JLX5h5P3jf5/w45xXcsq2trUdKqbk8n5mZAcCyrHtjKWUpSZLzo6OjnrwNXF1d/Xx/f3/P933DsiwtpSTLMgAMw0BrrQGEEMB16nmecXp6ugc8lQcHB59tbm5+XCqVKJfLhuM4D5eWlmzLsgiCoIAJIdBa56Citr6+jm3bHB8fnwNIKeVby8vLb7daLdI0RQhBmqb4vk8QBFOA3Obm5qjVakRRhOM4/eFweA3s9XpOqVQqGjc2Nuh0OgRBQJIkU6A89jwPz/OoVqs0Go1mrVZrAMgsy85GUonjmPn5edrtNpeXl/eqy2MpJZZl4bru74eHhwpADgaDehzHmda61O12qVarOI5T3N1Ny0GmaRY113V1q9X6pujZ2dl5fXt7+6zf7z+wbZuhnuW3tsK4SdKT4FgZMBJ84fUu3HjxKxBKq6wu2+32RRiGYafTebC2tsb39ZR333+CHybcaTp3Gg08hkdoPq1YktOXf38nT05O0t3d3X4URcuLi4sYZoDbjRhE6XhejwEU+dhnSvHQNjlr9p5LgCiK/JWVFeI4pmzOEA4zlNYTQ4XP/yN6mmmGSYZQV0nYv/o6B15WKhXK5TIxIDI1AdCaabUakkyRZhpDCC66/Vfm0mvPJEAYht3Z2Vm6kUAJA6XGWpS6Hs4hWoPS+ro+ugGzbPCn1//15PCjtFDYbDZ50fqRN975sDhZ6bG6iXe5VUzTDM8PfwAogAsLC/QjG/8qRWl917bcuIbJJ//H6b7q+dEXBdB13W47qqDfXCGMs2mYvnclQUOrdf7Lz1/udQpgvV7/duG9Dz6RTsPsOY07Vk8jENN1URqEyvzjr5+eHgEGkN3sskdfmf9uCggB/y7x/0/7FwBJpbw8U5nDAAAAAElFTkSuQmCC" height="20" width="20">'
  strVar += '\n'
  strVar += '<a id="ALiconeEnregistrer"  href="#" id="ALlien"    onmouseover="ALparseAlgo()" download="algorithme.txt">\n'
  strVar += '<img title="Enregistrer le programme"  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAjgAAAI4Ba9/WyQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAndEVYdFRpdGxlAENsaXBhcnQgYnkgTmljdSBCdWN1bGVpIC0gYW50ZW5uYW9BmuMAAAATdEVYdEF1dGhvcgBOaWN1IEJ1Y3VsZWn15/GkAAAB2klEQVQ4jc2Uv27TUBSHv2vHdtqUgYSEgkRKIU1fAl4ABhgQE0IwMSEhHoCFCSExs7CBeBDIEqkLLKTt1iZNBWqqJG18HduHwdh1/ipDBn7Lvbo+5/PvHJ9rJSIsU8ZSaUAm3ij16CfkcwCViuRevrqbdywLELQ3lF6vz+lpV3zfxzBNjlonwdcv3Tb0duD7U5GDwQgQCutQvAJg2UO2bpc4bDZpNBrcKJfZuFng89s99vcNHjy8RLV6DchuQmkTDA08GQOSNNNQoETo/P5DKV/ANs0oQBz8oYWhzLFCVyoTJaelDIUOAq5vlBdtXWJmqkPthvT7/Yms7W2bQiHk6rpDp6PTqUmuisdGqRfHUCzFD7aqGscxo1ARBEUUG62tpqLbjf0c1UQ+3ZnpEGBv11m0XEDCeLekOVTTe/jx9S3uV4eY2WxyGHoeutWaifo2KPPsXWsqMKJqTQB47TZ2sUhwfr6Iw6TkEeAv9zLPH99bAHChxvs66a88AnRDE/F9AtddCGbmcgzCzEygAJhraxipHs6T4SSTML1kAGXbqMzUCzQhZVkjZsaAke3w7IxQp2/BHIerq/McnhzX6z948yFYuXiFqNjMv0WlzgBRtdruEDpe4vq//2P/Bc7JuZmdOjbHAAAAAElFTkSuQmCC" height="20" width="20">'
  strVar += '</a>'
  strVar += '\n'
  strVar += '<img id="ALiconeCourriel" title="Poster le programme" onclick="ALmail()" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9sGEAwTItbhHWEAAAFxSURBVEjH7ZUxa8JAFMef5gquGfoRHDoZ3PJFYibRyVEHN8FsLodZHQR3F0f3gNCKY4mDFYdEJFMEUcTk4O+kaNU2aim0+JuOe8f93rvH3RE9ePCnie0GiUTinTH2zBgT924qhHgKw9DfbDYvRwFFUd40TYPnebiH0WgEXdeRTqdfT+yqqlqe50HTNDiOc5Og1+shn89juVxCVVXrrAQAfN+HrusYj8dXCdrtNsrlMoQQAHAkiX+WybJMzWaTDMMg27Yj9YBzTrPZjDjnJEnS5YW7Snas12vkcjkMBoOL2YdhiGKxiE6ncxL78rgOCYIAhUIBlnUSwmKxQDabRb/fP5tAZAkACCFQKpXQ7Xb3c67rIpPJYDKZXKzyUMK+O29Jksg0TapUKrRarSiZTBLnnBqNBsmyHKln8Ug3NhajWq1Gw+GQ6vU6tVqtyIJIlRxSrVZvegHiv/F2PSRXsW/8dDq1U6lU8FMbz+fzj//3M24B0jrsahNDZBkAAAAASUVORK5CYII=" height="25" width="25">'
  strVar += '\n'
  strVar += '<img id="ALiconeImprimer" title="imprimer le programme" onclick="ALimprime()" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9sGEAwdCJPZ+TkAAAJmSURBVDjLrVUxb9NAFP7OvnOdmIahRiVdMhSpRTQSTK2o2LqgShSxsXepMiL1r2QLQqrEwFAh0YFuDMwsRYqUIqJKbSQiUqhbBzt37zG4MXENbSR60tnvPt37/Pn5fT7gmoe4CNTr9QdKqeVxkgeDwceNjY1Po5i8uGlpaelNuVyeHYew0+l8AXDnUkKllOz3+4jjOIMzcxpblgXHcSClzOVbuRoIgYmJCTBzOokosxZCwHVdWFYuPa/QsiwUCoWMotEYAGzbhuu6EEKMR+i6LowxGTLXdaGUyu29kpCIoLWG4zhpCYZKhg8RQsCyrMsV1mq1Kc/zHnU6HRkEAYIgyCQMYyEElFLwPA+9Xk9ubr54GgThh3q9fpz2Ya1Wm1pfX2/Ozc35u7vvobWB1jpHNFpD27bBzFhefoi9vc9HW1tb841GI5AAsLKy8rJarfoAMD9/F3EcZz6EECJdj+JSSijlYHFxcabb7b5qNBrPJAD4vl/p9b6DiFEqTebaBsyglIdAxEh4CT9/HONXFMH3p2bTGvb7/ajZbMIrFtFq7WNt7cnY3m2322i3vyIeDKKUMIoiPT19C63WPqSUeLezAzDAyeX8nqjKYoAhg5nybZwEgc4QFotFLCzcAxH9mcaksfkHTkRI3jLSqfXC8Mz5n18WMyMMz+xU4cHBwVmpVELSGQIAp03O5z5OFDKYR5Sd+9wYwuHh0SmQUIhKpXJ/dfXx65ulG5NKKctRDpSjYMjAaAIxgQzDkAYbgiEGkYEhAzZMp2F4sr399nm3290bdmsRwDSAwt/seMXQACIA3wAE130C4DcE02Xwf+tkyAAAAABJRU5ErkJggg==" height="20" width="20">'
  strVar += '\n'
  strVar += "<img alt=\"aide\" title=\"Aide\" onclick=\"voirDiv('ALaide'),voirDiv('ALenHaut');\" src=\"data:image/gif;base64,R0lGODlhFAAUAOfSAAkicQklgQwmcAkmeQ4ncAsneQwqgBQuegwxdAwxfgkyfRAwjAs0hw42fg42hhA3fhM2hxE4hww6mBQ6kBU7kRQ7nBA9ohY8nBg9khQ9phI+ohc9qSI/iCU/ixBEohhDmhVEoxdFoxtFpRhGpCNGhxhGrh1HpxNJtxdJrRtIrxxJsCJJoB9JsyJJrCBKqB1KsRpKxCBKtB5LsB1KvR1NpSFLtR9MsRlOrx1RrxxSth9SuSlSpSBTujJSmiNVuyNUxSZVvh5XzChVyDdWlShXwCVW0yZYyDpXmCdYxypYzDJZsiNcxStZzTtZpTNbtThcpjpcqD9cpztdqSdgxy1g0zpfvDtgsz5grCti0zBi0i9j1zRkxjdkv0Nkp0RlqDlmwTln0U1noTxp0E1oq0Fr1VBspDxu1FFsr0Vu1Uhu0FFxq0dw10Ny01JyrEV001R0rkx32F94uWJ5rE9621R81lh90mh8rmd9qWB9vlN+32t8rVeA3W5/qG2AsWSBzHKHsHeHr2WJ03mKu3GPy3yOtnORzYGSsYCSuoGTu3iU0oaTvoWWtYWWvYSYzIaaxI2dx4ae1Iqfyo6fyoig1pShwJOjzZijwpeo052ox5ypyKCrypyt0KGvz6iy0qe01ai2zqu2y624za2727O+07S+3rW/1bW/37bA1rrA1L7ByL7F2r/G28HI28DL4MnM08jN4MvS3c3S5czU3s3V39fX0dHZ49na0tvb09jb4tnc49rd5N7f5N7h6OLi6OTi49/j6+Pj6eHk6+jm5+jp7ufq8enq7+zs8u7s7fDv6O/w9fLw8fHx6/Xz9Pj09/n6//z6+/v89P/++f///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAEKAP8ALAAAAAAUABQAAAj+AP8JHPivyZg3bbr0IMhw4BlNsmCxOhUKE6AjDQVKYQQr1y5ds1iNwkRJUZkODJ8cUsWqVq9iw4rpWpUJEaEwHAj28dSpFC9nxGIFi9bslaI/ejAKhCKp0iVSyZ4R48QpGTNjn+zIUUNC4JZBjSKJMgYt2qZHwJQp4+Tkipch/zyISVMnUCJTv1oV8nPsGDBHJ3DQ2HEgAxgzbuDMybOHDptJy5Cx4iIDxYgRD0ZQOUwGzRo0bszgEnbqi44XJkJgDsFksxgzsLVA8rXph48YKUaAGNGgAhImWLJkAZOlCCxPMIDokLEhxO4EEogYEZKEifUgqPD44GHjhu4QIRB5/HMBhMiSKUaMLIlTJYeN3M5HTBBIoQYPHz6AzBAEypIVFCI4B94AA13AAgsxsKCEK7fYsogGAo4AAUERfKBCCiW0kMottPBhAQiqLSAAQw5QcFkIURhyxwq7hQABABn9wwAGqpkgwgghUFBAjAQp0IABASRAQEYBAQA7\" />"
  strVar += '</div>'
  strVar += '\n'
  strVar += '<div id="ALrythme">'
  strVar += '<p>Pas à pas automatique</p>'
  strVar += 'Une étape par'
  strVar += '<input style="width:2em;" id="ALfreq"  value="1"> seconde(s)<br>'
  strVar += 'Délai intitial'
  strVar += '<input style="width:2em;" value="2" id="ALdelai" > seconde(s)<br>'
  strVar += '<input type="checkbox" id="ALenBoucle" /> En boucle<br>'
  strVar += '<progress id="ALpbar" value="0" min="0" max="100"></progress> '
  w.ALonClickLancer = function () {
    clic = false
    pasApasAuto(this)
  }
  strVar += '<input type="button"  onclick="ALonClickLancer()" value="Lancer" />'
  w.ALonClickFermer = function () {
    clic = false
    this.parentNode.style.display = 'none'
  }
  strVar += '<input type="button" onclick="ALonClickFermer()" value="Fermer" />'
  strVar += '</div>'

  strVar += '<div id="ALstock">'
  strVar += "  <a style=\"position:absolute; top: 2px; right: 10px;\" href=\"javascript:ALfermer('ALstock');\" alt=\"Fermer\">"
  strVar += '  <img title="Fermer" alt="Fermer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH1gQFFCUoDIRw0QAAAaJJREFUOMulk0FLG0EYhp9ZV9zpKnFbgzSbo80PEA8RLbSXQv5DjulRf0x7bI/5Dx5bQSh4UrxIPJq0DdsQ4kLWZZP5euhszBpzqQMDwzvzvXzf+74Dz1zqMdCGEDgCGkDNwh3gBPjchN5Sgja0gE/1MNQlrREAEYwx3N0nnP/6nQDHTfi6QNCG1ivP+7JXrfIniojjmIkxCLDiOKz7Pi+DgMt+n0GafsxJ1FzbNx92dvTP21uSNEWgsAHWVld5vb3NabebAG+a0HPs3VG9UtGDKCJJU+oi7IvMCg9FOBQhyTIGwyF75bK2OpETNDa05i6OZ0UAByIcyANigNF4jHZdrMgzgpoSYWpnPlML5vBdKQSYymyoGoCbPxARTH5+wu+CJuYBzzvoTI3gOA4CvJVFivdWE6UU5h9DZ57gJL5PWPd9zKO2v82NI8CG5zGeTLDBKtr4rlrV3X6fJMsK9okV0HNdwiDgRxQVbbTxPL6KIirlMiXfR1nRDIBSlLQmDDa5Ho2waewtjfLu1pZ+4a6AgCCIwDjLuBgOl0f5fz/Ts9dfScq9YFxk3JAAAAAASUVORK5CYII%3D" height="16" width="16">'
  strVar += '  </a>  '
  strVar += '  <h3>Ouvrir un programme</h3>'
  strVar += '  <p id="ALlisteStock">'
  strVar += '  </p>'
  strVar += '  <input type="file" onchange="ALlitFichier(this)">'
  strVar += '</div>'

  strVar += '<div id="ALdemos" style="display:none">'

  strVar += '<!-- ne pas toucher à ces lignes -->'
  strVar += '<h1>'
  strVar += 'Exemples'
  strVar += '</h1>'
  strVar += '<pre>'
  strVar += 'Taper l’algorithme ici :'
  strVar += '</pre>  '
  strVar += '</div>'

  strVar += '<!-- iframe caché pour sauvegarde sous IE -->'
  strVar += '<iframe id="ALiframe"></iframe>'
  divDroite.innerHTML = strVar

  // -------- remplissage de la div gauche ----------
  strVar = ''
  w.ALonMouseUpGauche = function () {
    // bogue sous firefox, fonction desactivee
    if (isFirefox) { return }
    const b = document.getElementById('ALbex')
    if (document.queryCommandState('superscript')) { b.className = 'exp' } else {
      b.className = ''
    }
  }
  strVar += '<div id="ALgauche" contenteditable="true" spellcheck="false" onmouseup="ALonMouseUpGauche()"  onkeyup="ALpre(this, event)">'
  strVar += '</div>'

  strVar += '<div id="ALboutons">  '

  w.ALonClickExec = () => {
    lancer()
    actionFusee()
  }
  strVar += '<img alt="exe"  onclick="ALonClickExec()" title="Exécuter" src="data:image/png;base64,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" /> '

  w.ALonClickPasApas = () => {
    w.AL1clic = false
    if (papGetIndex() === -1) {
      setTimeout(function () {
        if (!stopMetronome()) pasApas()
        w.AL1clic = true
      }, 1000)
    } else {
      pasApas()
    }
  }
  w.ALonDblClickPasApas = () => {
    if (!w.AL1clic && papGetIndex() === -1) {
      clic = true
      voirDiv('ALrythme')
    }
  }
  strVar += '<img alt="Pas a pas" onclick="ALonClickPasApas" ondblclick="ALonDblClickPasApas" title="Exécuter pas à pas" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAoCAYAAACfKfiZAAACpUlEQVRYhbWYPWgUQRTHfyyLhOMM4QhBJEhQOVKEIJpCFCxCELGwEdRCNIWKiIgfwUIhECxFLAJKsAjRwuIaLUQsRESsVA4RTSESNIkp/EANQfwiFm8mN5mbu5vZzP1h4O7Nm3m/ffN2dnZBlAJDwCTwB5gDJoCNuLUD2APkLPtm4BBQqDHOqRR4ACw62jyw2/BNgPtG/zOgRfWdNOzvgDZfgLM1guu2AHQp3wFH/wl1Ed8t+xEjRl75VCkBDjcAzAEX1W9XarcDa4FWy14AVgG3kUzOArtcAeapn4FFNRhgDVIjZt91FfynZR8ARizblAtg2gPgl+E/ZE3YqezDhr2kbGVrnmkXwLgHwFtrTC9yJ9jr2gP0Gf9L1jznlX29Ob6orrAewCVj0hTYCVwB7qqrnAJeAU+AG8A+oB2pg3HkbtHBB6kso84UB6heW93KSCEmwHH8lkwv2y2VLa0Wlt8tC2b6+oB7BsgXYBQpsMSRTt/2DynUvMqK2fcIh1JkE0kMm1lgWdtrZD8ZU1AvgHUuAFu9asBKAXQxt1NjU6qlsUjBdZsICZ7gt1GFtm4zQD11IcUTW0d9ATob9GfV0hO2EcDXJgF0Ax0+AB+Av02C2OQD8AO40ySAog8AwBlgpgkArb4AM8AW4FpkkNVZB7Yhj9LLwCey7wXD2dkryiOP5SwAp2IAaF3IAHAwJgDAy0CAreBXhL4qNXZZpjexAT4H+H5E9pioAB0Bvs/1j5gAewN8H0aMC8iLakgB9sQMniJv1b7BZ83BMZbgGMYJx0M3I8RcUgE5voekvxgT4Gpg8McxgxeofiNu1LbFBBgMDO7cKVdShBsCfL8B52IDTHr6/Qb2I+fLqEqBp9RP+xzQHzuwqRxyFihTeat+j3xJO43Hl7L/Wx2ZHkyGHkQAAAAASUVORK5CYII=" />'

  strVar += "<img id=\"ALparamGraph\" alt=\"graphique\" title=\"Fenêtrage des sorties graphiques hors tortue\" onclick=\"voirDiv('ALdimFenetre');\" src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAArCAYAAAADgWq5AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgbDQAaIKZUJwAAA4RJREFUWMPtmF1oHFUUx3/37ux0KW2VGktYakiLBLvbLlJDEFl07YO1YpFms5tEGghUEGoFUegXIhF9U18C9lVRsbShSI0PDUIDwYdYMTSzmU1sAy32wzau6wexJJvdO33IpNDdmWTXfK1l/jAwnDlz+M+Zc//n3AuV4SgQ5H8EE3h6NQlIHlDsAr4E/gT6gHerPcMZIAXkgHHgklfDD2oNe4QBrC5kfwxtNQkfBK4BDcBZWylcMZhe37vm0Yd+Wk3CJ4DHbHV4Bdg9n3Mve7//g0c+osV8kcRwffWrRMJ49t593HiCZPolOobXOrmOJDlsxmkql4C2PN/lGyGeinBmh8GZyBhYYyTNZ0iYASCLpl1HqY0Bmdv8d/65dywhdcheKCey+A8ZPgAMLujZkoohRgfoSar77K8aDzMt6vD7M/h8k+RyjfSEzy91DW8F9gMbgD12q14gFaMDEI6V2L+O/IXlmyA/00B+JlQJ2Uoy/DLwBhAFRpD+Qdp+fn9hfRM6Su5EcQEK21HWBjQJiFv41HjZLPX1U3y+ZWp5SwIg1q9RUxNFiiiWOEFPOFu9na5tLEhNTZRM5gdOhz8EQsT6tSqVNbOWuFkkVRa0mFESp12TlG5lZypO48rLmsWTSMZJjsSwhMQCRCqP0HQIHSdhDMyuIClRFkifBuR+s57/VMqChEx4sYuuEzhiq8VNhDZE+9CBYqfu6UP1T4nh3m7x1len1L5TrJFXSyIVRBNKGvgLU/fZZ3wyKG807xbnzn0mOyfdFl25WAfUA5eBZmCTk9PoPjb+2LLuZLqZOvdyuRikdbTBoYx20XklsFSdbtK+csBNYMLJads3ZGGyff5lrtdx51+jtIyUKieLKzoPp5Ly7fcKXS/Q23inlInQ97zZrafjPF41hKfR927jlx0kjO0lDyd+Px+73XdYSS6bcUIrP0vMh+Z0LZqKoEQewTg94V8BvuiIrL02veXQ8dDZj0UXajGEDwLHgFogi9Au0j7UuiRpL1hbUWxGWP8g/AGkGkJYucWqhLdr9ghXgE8cbI1Am4Pd7fTzA5cYry0H4f0OtiZ7s1qMDnDsgm4xEk4q0QfuuleEWZWY7XhzCNrdr7iV67bvQu/P2W85xAjY53pzeH0pVOK2iwyerEBlrrjE6FuO8fI7B5vhkEWAbx3+xnwx9JUZ4D1Z8wh7hD3CHuFycRekDBTXUqtfqwAAAABJRU5ErkJggg==\" />"

  strVar += '<img alt="Mise en forme" title="Colorier et indenter" onclick="ALparseAlgo()"  src="data:image/png;base64,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" />'

  w.ALmodeTortue = modeTortue
  strVar += '<img id="ALboutonTortue" alt="tortue" title="Mode tortue" onclick="ALmodeTortue();"  src="data:image/png;base64,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" />'
  strVar += '<img alt="effacer" id="ALeffaceG" title="Effacer l’algorithme" onclick="ALeffacer(false)" />'
  strVar += '</div>'
  strVar += '<div id="ALlisteDemo" >'
  strVar += '<select id="ALselectDemo" onchange="ALchargeDemo(this)">'
  strVar += '</select>'
  strVar += '</div>'
  strVar += '<div id="ALtouches">'
  strVar += '<button onclick="ALsup(this);" id="ALbex" title="activer ou désactiver les exposants">'
  strVar += 'x<sup>n</sup>'
  strVar += '</button>\n'
  strVar += "<button  onclick=\"ALinsere('&pi;')\" title=\"insère &pi;\">&pi; </button>\n"
  strVar += "<button  onclick=\"ALinsere('&le;')\" title=\"insère &le;\">&le; </button>\n"
  strVar += "<button  onclick=\"ALinsere('&ge;')\" title=\"insère &ge;\">&ge; </button>\n"
  strVar += "<button  onclick=\"ALinsere('&ne;')\" title=\"insère &ne;\">&ne; </button>\n"
  strVar += "<button  onclick=\"ALinsere('&rarr;')\" title=\"insère &rarr;\">&rarr; </button>"
  strVar += '</div>'

  strVar += '<div id="ALavertissement">'
  strVar += '<h2>Attention !</h2>'
  strVar += '<p>'
  strVar += 'Si vous voyez ce message, cela veut dire que l’exécution des programmes'
  strVar += 'est désactivée sur votre navigateur. '
  strVar += '</p>'
  strVar += '<ul>'
  strVar += '<li>'
  strVar += '<b>Internet Explorer :</b>'
  strVar += 'vous devez peut-être répondre positivement à une invite éventuelle <b>en bas de la fenêtre</b>.'
  strVar += '</li>'
  strVar += '<li>'
  strVar += '<b>Sinon :</b>'
  strVar += 'Vous avez probablement désactivé le &laquo;javascript&raquo; (et pas &laquo;java&raquo;) sur votre'
  strVar += 'navigateur. Cherchez comment le réactiver.'
  strVar += '</li>'
  strVar += '</ul>'
  strVar += '</div>'
  strVar += '<div id="ALdimFenetre">'
  strVar += '<p>'
  strVar += 'Fenêtre graphique (hors tortue) :'
  strVar += '</p>'
  strVar += '<ul>'
  strVar += '<li>'
  strVar += 'x<sub>min</sub> : <input id="ALxMin" value="-5"/>'
  strVar += '</li>'
  strVar += '<li>'
  strVar += 'y<sub>min</sub> : <input id="ALyMin" value="-5"/>'
  strVar += '</li>'
  strVar += '<li>'
  strVar += 'x<sub>max</sub> : <input id="ALxMax" value="5"/>'
  strVar += '</li>'
  strVar += '<li>'
  strVar += 'y<sub>max</sub> : <input id="ALyMax" value="5"/>'
  strVar += '</li>'
  strVar += '<li>'
  strVar += 'Couleur de trait : <input id="ALstroke" value="noir"/>'
  strVar += '</li>'
  strVar += '<li>'
  strVar += '<input type="checkbox" id="ALaxes" />  Axes visibles<br>'
  strVar += '</li>'
  strVar += '</ul>'
  strVar += '<input type="button" onclick="ALdimGraph()" value="ok"/>'
  strVar += '</div>'
  divGauche.innerHTML = strVar

  // fin de l’injection code html  dans la page ----------------------------------

  // injection de l’algorithme passé en argument
  if (algo) {
    const d = document.getElementById('ALgauche')
    d.innerHTML = '<pre>\n' + algo + '\n</pre>'
    parseAlgo()
  }
  // désactivation de la correction automatique
  document.body.setAttribute('spellcheck', 'false')
  // activation de la sauvegarde d’urgence
  // document.body.setAttribute('onbeforeunload', 'ALsauveUrgence()')
  // masquer certains élements
  let elt
  for (var nom in this.aMasquer) {
    elt = document.getElementById(nom)
    if (elt) {
      elt.style.display = 'none'
      elt.style.visibility = 'hidden'
    }
  }
  // remplissage des démos
  elt = document.getElementById('ALdemos')
  let h1, pre, texte
  for (nom in this.demos) {
    h1 = document.createElement('h1')
    pre = document.createElement('pre')
    texte = document.createTextNode(nom)
    h1.appendChild(texte)
    texte = document.createTextNode(this.demos[nom])
    pre.appendChild(texte)
    elt.appendChild(h1)
    elt.appendChild(pre)
  }
  // précision
  document.getElementById('ALinputPrecis').value = this.precis
  // initialisations
  this.init() // ex ALinit
}

Psylvia.prototype.init = function init (algoInitial) {
  document.execCommand('enableObjectResizing', false, 'false')
  document.getElementById('ALavertissement').style.display = 'none'
  // document.getElementById("ALinputPrecis").value=w.ALprecision
  faitPrecision()
  ALafficheBalai('ALeffaceG')
  ALafficheBalai('ALeffaceD')
  initDemos()
  document.getElementById('ALselectDemo').selectedIndex = 0
  const g = document.getElementById('ALgauche')
  g.focus()
  Tortue.prototype.faitRepas()
  if (!algoInitial) {
    ALinsere('<pre>Taper un algorithme ici :<br></pre>')
  }
  g.blur()
  parseAlgo()
  modeTortue()
}