legacy/outils/algo/algo.js

import { j3pAjouteBouton, j3pAjouteDiv, j3pDetruit, j3pGetRandomInt, j3pRemplace } from 'src/legacy/core/functions'
/*
 * Auteur : JP Branchard
 *
 *   Copyright (C) 2009 J-P Branchard <Jean-Pierr.Branchard@ac-grenoble.fr>
//   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 2 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, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *   Remanié par E.Ostenne
 *   http://emmanuel.ostenne.free.fr/mepirem/algo/
 *
 *   Intégration à j3p et remaniement par JP Vanroyen - Septembre 2012
 *   Mode pas à pas et
 *   Valeur des variables
 */

/*
 *   L’algorithme est dans une zone d’id appelé idalgo
 *   idmessage contient l’ID de la zone message
 *   idsortie contient l’ID de la zone sortie du programme
 */

/**
 * À documenter
 * @param conteneur
 * @param idalgo
 * @param idmessage
 * @param idsortie
 * @param zonebouton
 * @constructor
 */
function Algo (conteneur, idalgo, idmessage, idsortie, zonebouton) {
  this.idalgo = idalgo
  this.idsortie = idsortie
  this.sortieauto = ''
  this.idmessage = idmessage
  this.textealgo = document.getElementById(this.idalgo).value
  this.message = ''
  this.lignes = []
  this.tableIndex = 0
  this.conteneur = conteneur
  this.pasapasetape = 0
  this.tabcode = []
  this.demande = ''
  this.param = {}

  this.variables = []
  this.valeursvariables = {}

  this.pardefaut = document.getElementById(this.idalgo).value

  j3pAjouteBouton(zonebouton, 'algoboutonexe', 'MepBoutonsDG', 'EXE', 'j3p.algoj3p.lancer()')
  j3pAjouteBouton(zonebouton, 'algoboutoneffp', 'MepBoutonsDG', 'Effacer le programme', 'j3p.algoj3p.effacersortie(false)')
  j3pAjouteBouton(zonebouton, 'algoboutoneffs', 'MepBoutonsDG', 'Effacer la sortie', 'j3p.algoj3p.effacersortie(true)')
  j3pAjouteBouton(zonebouton, 'pasapas', 'MepBoutonsDG', 'Pas à pas', 'j3p.algoj3p.pasapas(true)')
  j3pAjouteBouton(zonebouton, 'pasapasavance', 'MepBoutonsDG', 'Avance', 'j3p.algoj3p.pasapasavance(true)')
  document.getElementById('pasapasavance').style.display = 'none'
}

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

Algo.prototype.listedesvariables = function () {
  this.variables = []
  this.textealgo = document.getElementById(this.idalgo).value
  this.tabcode = this.textealgo.split('\n')
  let k
  for (k = 0; k < this.tabcode.length; k++) {
    const ch = this.tabcode[k].trim()
    if (ch.indexOf('afficher') === -1) {
      const pos = ch.indexOf('=')
      if (ch.substring(0, 3) === 'var') {
        this.variables.push(ch.substring(3, pos).trim())
      } else {
        this.variables.push(ch.substring(0, pos).trim())
      }
    }
  }
  // console.log('les variables ' + this.variables)
  this.valeursvariables = {}
  for (k = 0; k < this.variables.length; k++) {
    this.valeursvariables[this.variables[k]] = 'indéfinie'
  }
}

Algo.prototype.pasapasavance = function () {
  document.getElementById('divpasapas').innerHTML = ''
  const conteneurcode = document.getElementById('divpasapas')
  let k, pos1, pos2
  for (k = 0; k < this.tabcode.length; k++) {
    const p = document.createElement('p')
    if (this.pasapasetape === k) {
      p.innerHTML = '<b>' + this.tabcode[k] + '</b>'
    } else {
      p.innerHTML = this.tabcode[k]
    }
    conteneurcode.appendChild(p)
  }
  let code = ''
  for (k = 0; k <= this.pasapasetape - 1; k++) {
    if (this.tabcode[k].indexOf('afficher') === -1) {
      code += this.tabcode[k]
    }
  }

  code += this.tabcode[this.pasapasetape]

  if (this.tabcode[this.pasapasetape].indexOf('demanderchaine') !== -1) {
    pos1 = this.tabcode[this.pasapasetape].indexOf('var')
    pos2 = this.tabcode[this.pasapasetape].indexOf('=')
    this.demande = this.tabcode[this.pasapasetape].substring(pos1 + 3, pos2)
    pos1 = this.tabcode[this.pasapasetape].indexOf('demanderchaine')
    this.tabcode[this.pasapasetape] = j3pRemplace(this.tabcode[this.pasapasetape], pos1, pos1 + 13, 'demanderchainepasapas')
    code = ''
    for (k = 0; k <= this.pasapasetape; k++) {
      code += this.tabcode[k]
    }
  }

  if (this.tabcode[this.pasapasetape].indexOf('demandernombre') !== -1) {
    pos1 = this.tabcode[this.pasapasetape].indexOf('var')
    pos2 = this.tabcode[this.pasapasetape].indexOf('=')
    this.demande = this.tabcode[this.pasapasetape].substring(pos1 + 3, pos2)
    pos1 = this.tabcode[this.pasapasetape].indexOf('demandernombre')
    this.tabcode[this.pasapasetape] = j3pRemplace(this.tabcode[this.pasapasetape], pos1, pos1 + 13, 'demandernombrepasapas')
    code = ''
    for (k = 0; k <= this.pasapasetape; k++) {
      code += this.tabcode[k]
    }
  }

  // console.log('dans pasapasavance excecution de ' + code)
  this.lancerpasapas(code)
  this.pasapasetape++

  // document.title='this.pasapasetape='+this.pasapasetape+'  '+this.tabcode.length;

  if (this.pasapasetape === this.tabcode.length) {
    document.getElementById('pasapas').value = 'Pas à pas'
    this.pasapasetape = 0
    j3pDetruit('divpasapas')
    document.getElementById(this.idalgo).style.display = ''
    document.getElementById('algoboutonexe').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDG'
    document.getElementById('pasapasavance').style.display = 'none'
  }
}

Algo.prototype.lancerpasapas = function (code) {
  code = code.toLowerCase()
  let prog = code
  this.textealgo = document.getElementById(this.idalgo).value

  try {
    prog = this.transforme(prog, false)
    // eslint-disable-next-line no-eval
    eval(prog)
    // afficher("Exécution en ",t1.getTime()-t0.getTime()," millisecondes");
  } catch (err) {
    console.error(err)
    // this.afficher(err.name," : ",err.message);
    this.afficher(err.name, ' : ', '<b>' + err.message + '</b>')
    this.afficher('~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
    //    afficher("Sous Firefox, vous pouvez activer Outils/console d’erreur : celle-ci affiche l’instruction erronée (ou quelquefois l’instruction juste après)");
    //    //on le remet pour activer la console d’erreur de Firefox :
    //    eval(prog);
  }
}

Algo.prototype.pasapas = function () {
  //    this.lancerautoaveccode('var c=4;\nvar a =demandernombre("Entrer a");\nvar b =demandernombre("Entrer b");\nvar m = (a+b)/2;\nafficher("la moyenne est égale à "+m);',{a:14,b:17})
  //    return;

  if (document.getElementById('pasapas').value === 'Quitter le pas à pas') {
    document.getElementById('pasapas').value = 'Pas à pas'
    this.pasapasetape = 0
    j3pDetruit('divpasapas')
    document.getElementById(this.idalgo).style.display = ''
    document.getElementById('algoboutonexe').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDG'
    document.getElementById('pasapasavance').style.display = 'none'
  } else {
    document.getElementById('algoboutonexe').className = 'MepBoutonsDGDisabled'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDGDisabled'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDGDisabled'
    this.pasapasetape = 0
    document.getElementById('pasapasavance').style.display = ''
    this.textealgo = document.getElementById(this.idalgo).value
    this.tabcode = this.textealgo.split('\n')
    const element = document.getElementById(this.idalgo)
    element.style.display = 'none'

    document.getElementById('pasapas').value = 'Quitter le pas à pas'

    j3pAjouteDiv(this.conteneur, 'divpasapas', '')

    this.pasapasavance()
  }
}

Algo.prototype.effacersortie = function (bool) {
  // false : on efface le programme
  if (bool) {
    this.message = 'Effacer les sorties'
  } else {
    this.message = 'Effacer le programme'
  }
  // eslint-disable-next-line no-alert
  if (!confirm(this.message)) {
    return
  }
  if (bool) {
    const b = document.getElementById(this.idsortie)
    while (b.firstChild) { b.removeChild(b.firstChild) }
    return
  }
  const h = document.getElementById(this.idalgo)
  h.value = this.pardefaut// j3p.stockage[0].remarques;//"";j3pstockage[0].remarques
  h.focus()
}

Algo.prototype.transforme = function (prog, bool) {
  function verification (ch) {
    if (ch.indexOf('eval') !== -1) { return { bool: false, mes: 'fonction eval non autorisée' } }
    if (ch.indexOf('$') !== -1) { return { bool: false, mes: 'caractère $ non autorisé' } }
    if (ch.indexOf('document') !== -1) { return { bool: false, mes: 'mot clef document non autorisé' } }
    if (ch.indexOf('getElementById') !== -1) { return { bool: false, mes: 'méthode getElementById non autorisée' } }
    if (ch.indexOf('body') !== -1) { return { bool: false, mes: 'mot clef body non autorisé' } }
    if (ch.indexOf('this') !== -1) { return { bool: false, mes: 'mot clef this non autorisé' } }
    if (ch.indexOf('j3p') !== -1) { return { bool: false, mes: 'mot clef <b>j3p</b> non autorisé' } }
    return { bool: true, mes: 'isOK' }
  }

  if (!verification(prog).bool) {
    return 'j3p.algoj3p.afficher("<i>Programme incorrect</i>:<br> ' + verification(prog).mes + '")'
  }

  if (bool) {
    prog = 'afficher("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");' + prog
  }

  let pos1
  while (prog.indexOf('afficher(') !== -1) {
    pos1 = prog.indexOf('afficher(')
    prog = j3pRemplace(prog, pos1, pos1 + 7, 'j3p.algoj3p.abcdefgh')
  }
  while (prog.indexOf('abcdefgh') !== -1) {
    pos1 = prog.indexOf('abcdefgh')
    prog = j3pRemplace(prog, pos1, pos1 + 7, 'afficher')
  }
  while (prog.indexOf('demanderchaine(') !== -1) {
    pos1 = prog.indexOf('demanderchaine(')
    prog = j3pRemplace(prog, pos1, pos1 + 13, 'j3p.algoj3p.abcdefghijklmn')
  }
  while (prog.indexOf('abcdefghijklmn') !== -1) {
    pos1 = prog.indexOf('abcdefghijklmn')
    prog = j3pRemplace(prog, pos1, pos1 + 13, 'demanderchaine')
  }

  while (prog.indexOf('demandernombre(') !== -1) {
    pos1 = prog.indexOf('demandernombre(')
    prog = j3pRemplace(prog, pos1, pos1 + 13, 'j3p.algoj3p.abcdefghijklmn')
  }
  while (prog.indexOf('abcdefghijklmn') !== -1) {
    pos1 = prog.indexOf('abcdefghijklmn')
    prog = j3pRemplace(prog, pos1, pos1 + 13, 'demandernombre')
  }
  while (prog.indexOf('demanderchainepasapas(') !== -1) {
    pos1 = prog.indexOf('demanderchainepasapas(')
    prog = j3pRemplace(prog, pos1, pos1 + 20, 'j3p.algoj3p.abcdefghijklmnopqrstu')
  }
  while (prog.indexOf('abcdefghijklmnopqrstu') !== -1) {
    pos1 = prog.indexOf('abcdefghijklmnopqrstu')
    prog = j3pRemplace(prog, pos1, pos1 + 20, 'demanderchainepasapas')
  }

  while (prog.indexOf('demandernombrepasapas(') !== -1) {
    pos1 = prog.indexOf('demandernombrepasapas(')
    prog = j3pRemplace(prog, pos1, pos1 + 20, 'j3p.algoj3p.abcdefghijklmnopqrstu')
  }
  while (prog.indexOf('abcdefghijklmnopqrstu') !== -1) {
    pos1 = prog.indexOf('abcdefghijklmnopqrstu')
    prog = j3pRemplace(prog, pos1, pos1 + 20, 'demandernombrepasapas')
  }

  if (bool) {
    prog += 'j3p.algoj3p.afficher("~~~~~~~~~~TERMINE~~~~~~~~~~")'
  }
  return prog
}

Algo.prototype.lancerauto = function () {
  document.getElementById(this.idalgo).value = document.getElementById(this.idalgo).value.toLowerCase()
  this.listedesvariables()
  try {
    const prog = document.getElementById(this.idalgo).value
    this.transformeauto(prog, false)
  } catch (err) {
    console.error(err)
    this.afficher(err.name, ' : ', err.message)

    // afficher("Sous Firefox, vous pouvez activer Outils/console d’erreur : celle-ci affiche l’instruction erronée (ou quelquefois l’instruction juste après)");
    // eval(prog);
  }
}

//  lancerautoaveccode('afficher("Bonjour tout le monde !");',{})

Algo.prototype.lancerautoaveccode = function (code, param) {
  code = code.toLowerCase()
  this.listedesvariables()
  this.sortieauto = ''
  const prog = code
  try {
    this.transformeauto(prog, param)
  } catch (err) {
    console.error(err)
    this.afficher(err.name, ' : ', err.message)

    // afficher("Sous Firefox, vous pouvez activer Outils/console d’erreur : celle-ci affiche l’instruction erronée (ou quelquefois l’instruction juste après)");
    // eval(prog);
  }
}

Algo.prototype.lancer = function () {
  document.getElementById(this.idalgo).value = document.getElementById(this.idalgo).value.toLowerCase()
  this.listedesvariables()
  let prog = document.getElementById(this.idalgo).value
  try {
    prog = this.transforme(prog, true)
    eval(prog) // eslint-disable-line no-eval
  } catch (err) {
    console.error(err)
    this.afficher(err.name, ' : ', '<b>' + err.message + '</b>')
    this.afficher('~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
    // afficher("Sous Firefox, vous pouvez activer Outils/console d’erreur : celle-ci affiche l’instruction erronée (ou quelquefois l’instruction juste après)");
    // eval(prog);
  }
}

Algo.prototype.afficher = function () {
  const idLieu = this.idsortie
  const lieu = document.getElementById(idLieu)
  const p = document.createElement('p')
  let texte = ''
  for (let i = 0; i < arguments.length; i++) { texte += arguments[i] + ' ' }
  p.innerHTML = texte
  lieu.appendChild(p)
  p.scrollIntoView(false)
}

Algo.prototype.afficherauto = function () {
  let texte = ''
  for (let i = 0; i < arguments.length; i++) { texte += arguments[i] + ' ' }

  this.sortieauto += texte + '\n'
}

Algo.prototype.demander = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')
  if (x === 'stop') {
    throw Error('Abandon volontaire')
  }
  const s = x + ' '
  const t = s.split(/[,;]+/g)
  if (t.length < 2) {
    return nombre(x)
  }
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }
  return t
}

Algo.prototype.demanderchaine = function () {
  let message = ''
  for (let i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')
  if (x === 'stop') {
    throw Error('Abandon volontaire')
  }
  const s = x + ' '
  const t = s.split(/[,;]/g)
  if (t.length < 2) {
    return s
  }// nombre(x);
  for (let i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }
  return t
}

Algo.prototype.demanderchaine = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')
  if (x === 'stop') throw Error('Abandon volontaire')
  const s = x + ' '
  const t = s.split(/[,;]+/g)
  if (t.length < 2) {
    return s
  }// nombre(x);
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }
  return t
}

Algo.prototype.demanderauto = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')
  if (x === 'stop') throw Error('Abandon volontaire')
  const s = x + ' '
  const t = s.split(/[,;]+/g)
  if (t.length < 2) {
    return nombre(x)
  }
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }
  return t
}

Algo.prototype.demandernombre = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')

  if (x == null) {
    document.title = 'stop'
    document.getElementById('pasapas').value = 'Pas à pas'
    this.pasapasetape = 0
    j3pDetruit('divpasapas')
    document.getElementById(this.idalgo).style.display = ''
    document.getElementById('algoboutonexe').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDG'
    document.getElementById('pasapasavance').style.display = 'none'
    return
  }

  if (x === 'stop') throw Error('Abandon volontaire')
  const s = x + ' '
  const t = s.split(/[,;]+/g)

  if (t.length < 2) {
    // document.title="var "+j3p.algoj3p.demande+"= "+t[0]+";";
    this.tabcode[this.pasapasetape] = 'var ' + this.demande + '= ' + nombre(x) + ';'

    return nombre(x)
  }
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }

  return t
}

Algo.prototype.demandernombreauto = function () {
  const x = j3pGetRandomInt(0, 100)

  return nombre(x)
}

Algo.prototype.demanderchaineauto = function () {
  return 'abcd'
}

Algo.prototype.demanderchainepasapas = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour arrêter)')

  if (x == null) {
    document.title = 'stop'
    document.getElementById('pasapas').value = 'Pas à pas'
    this.pasapasetape = 0
    j3pDetruit('divpasapas')
    document.getElementById(this.idalgo).style.display = ''
    document.getElementById('algoboutonexe').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDG'
    document.getElementById('pasapasavance').style.display = 'none'
    return
  }

  if (x === 'stop') throw Error('Abandon volontaire')
  const s = x + ' '
  const t = s.split(/[,;]+/g)

  if (t.length < 2) {
    this.tabcode[this.pasapasetape] = 'var ' + this.demande + '= "' + nombre(x) + '";'

    return s
  }
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }

  return t
} // demanderchainepasapas

Algo.prototype.demandernombrepasapas = function () {
  let message = ''
  let i
  for (i = 0; i < arguments.length; i++) { message += arguments[i] + ' ' }
  // eslint-disable-next-line no-alert
  const x = prompt(message + ' (ou taper stop pour abandonner)')

  if (x == null) {
    document.title = 'stop'
    document.getElementById('pasapas').value = 'Pas à pas'
    this.pasapasetape = 0
    j3pDetruit('divpasapas')
    document.getElementById(this.idalgo).style.display = ''
    document.getElementById('algoboutonexe').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffp').className = 'MepBoutonsDG'
    document.getElementById('algoboutoneffs').className = 'MepBoutonsDG'
    document.getElementById('pasapasavance').style.display = 'none'
    return
  }

  if (x === 'stop') throw Error('Abandon volontaire')
  const s = x + ' '
  const t = s.split(/[,;]+/g)

  if (t.length < 2) {
    this.tabcode[this.pasapasetape] = 'var ' + this.demande + '= ' + s + ';'

    return s
  }
  for (i = 0; i < t.length; i++) { t[i] = nombre(t[i]) }

  return t
}

Algo.prototype.extraitnomvar = function (ch) {
  // var a = 4

  ch = ch.trim()
  if (ch.indexOf('var') !== -1) {
    ch = ch.substring(3)
    ch = ch.trim()
  }
  // a = 4
  return ch.substring(0, ch.indexOf('=')).trim()
}

Algo.prototype.transformeauto = function (prog, param) {
  function verification (ch) {
    if (ch.indexOf('eval') !== -1) { return { bool: false, mes: 'fonction eval non autorisée' } }
    if (ch.indexOf('$') !== -1) { return { bool: false, mes: 'caractère $ non autorisé' } }
    if (ch.indexOf('document') !== -1) { return { bool: false, mes: 'mot clef document non autorisé' } }
    if (ch.indexOf('getElementById') !== -1) { return { bool: false, mes: 'méthode getElementById non autorisée' } }
    if (ch.indexOf('body') !== -1) { return { bool: false, mes: 'mot clef body non autorisé' } }
    if (ch.indexOf('this') !== -1) { return { bool: false, mes: 'mot clef this non autorisé' } }
    if (ch.indexOf('j3p') !== -1) { return { bool: false, mes: 'mot clef <b>j3p</b> non autorisé' } }
    return { bool: true, mes: 'isOK' }
  }

  if (!verification(prog).bool) {
    this.afficher('<i>Programme incorrect</i>:<br> ' + verification(prog).mes)
  }

  let pos1, posdebut, posfin, k, lignecode, toto
  while (prog.indexOf('afficher(') !== -1) {
    pos1 = prog.indexOf('afficher(')
    // this.sortieauto
    prog = j3pRemplace(prog, pos1, pos1 + 7, 'j3p.algoj3p.abcdefgh')
  }
  while (prog.indexOf('abcdefgh') !== -1) {
    pos1 = prog.indexOf('abcdefgh')
    prog = j3pRemplace(prog, pos1, pos1 + 7, 'afficherauto')
  }
  while (prog.indexOf('demanderchaine(') !== -1) {
    pos1 = prog.indexOf('demanderchaine(')
    posfin = prog.indexOf(';', pos1)
    k = 0
    while ((prog.charAt(pos1 - k) !== '\n') && (pos1 - k >= 0)) { k++ }
    posdebut = pos1 - k + 1
    lignecode = prog.substring(posdebut, posfin + 1)
    toto = this.extraitnomvar(lignecode)
    prog = j3pRemplace(prog, posdebut, posfin, 'var ' + toto + '="' + param[toto] + '"')
  }

  while (prog.indexOf('demandernombre(') !== -1) {
    pos1 = prog.indexOf('demandernombre(')
    posfin = prog.indexOf(';', pos1)
    k = 0
    while ((prog.charAt(pos1 - k) !== '\n') && (pos1 - k >= 0)) { k++ }
    posdebut = pos1 - k + 1
    lignecode = prog.substring(posdebut, posfin + 1)
    toto = this.extraitnomvar(lignecode)
    prog = j3pRemplace(prog, posdebut, posfin, 'var ' + toto + '=' + param[toto])
  }

  return prog
}

Algo.prototype.Recuperederniercode = function () {
  const pere = document.getElementById(this.idsortie)

  let ch = ''
  let k
  for (k = 0; k < pere.childNodes.length; k++) {
    const ele = pere.childNodes.item(k)
    if (k < pere.childNodes.length - 1) {
      ch += ele.innerHTML + '\n'
    } else {
      ch += ele.innerHTML
    }
  }
  const tab = ch.split('\n')
  tab.pop()

  const tab2 = []
  k = tab.length - 1
  while (tab[k].indexOf('~~~') === -1) {
    k--
  }
  for (let j = k + 1; j < tab.length; j++) {
    tab2.push(tab[j])
  }
  ch = tab2.join('\n') + '\n'

  return ch
}

Algo.prototype.Corrige = function () {
  this.Recuperederniercode()
  this.lancerauto()
}

// et on exporte notre constructeur en global
window.Algo = Algo