exercices/6e/6I10.js

import Exercice from '../Exercice.js'
import { mathalea2d, colorToLatexOrHTML } from '../../modules/2dGeneralites.js'
import { context } from '../../modules/context.js'
import { listeQuestionsToContenu, choice } from '../../modules/outils.js'
import { point, polygone, grille, texteParPosition } from '../../modules/2d.js'

export const amcReady = true
export const amcType = 'AMCOpen'
export const titre = 'Programmer des déplacements (Scratch)'

/**
 * * Colorier le déplacement d'un lutin
 * * 6I10
 * @author Erwan Duplessy // (Ajout paramètre 3 par EE)
 * Ajout AMC : Janvier 2022 par EE
 */
export const uuid = 'c8fe9'
export const ref = '6I10'
export default function ColorierDeplacement () {
  Exercice.call(this) // Héritage de la classe Exercice()
  this.typeExercice = 'Scratch'
  this.sup = 1 // nombre de commandes = this.sup + 2
  this.sup2 = false // 1 : sans boucle ; true : avec boucle
  this.sup3 = false
  this.nbQuestions = 1
  this.nbQuestionsModifiable = false
  this.titre = titre
  this.consigne = 'Dans le quadrillage, effectuer le programme.'
  this.nbCols = 1
  this.nbColsCorr = 1
  this.nbQuestionsModifiable = false
  context.isHtml ? this.spacing = 2 : this.spacing = 1
  context.isHtml ? this.spacingCorr = 2 : this.spacingCorr = 1
  this.listePackages = 'scratch3' // pour dessiner les blocs en LaTeX/Tikz

  this.nouvelleVersion = function () {
    this.listeQuestions = [] // Liste de questions
    this.listeCorrections = [] // Liste de questions corrigées
    this.autoCorrection = []
    function scratchblocksTikz (codeSvg, codeTikz) {
      // c'est une ancienne façon de faire. Maintenant il existe une fonction scratchblock() qui effectue la conversion scratch Latex -> scratchblock
      if (context.isHtml) {
        return codeSvg
      } else {
        return codeTikz
      };
    };

    let texte = '' // texte de l'énoncé
    let texteCorr = '' // texte du corrigé
    let codeTikz = '' // code pour dessiner les blocs en tikz
    let codeSvg = '' // code pour dessiner les blocs en svg
    const nbCommandes = Number(parseInt(this.sup)) + 2 // nombre de commandes de déplacement dans un script
    let nbRepetition = 1 // Nombre de fois où la boucle est répétée.
    if (this.sup2) {
      nbRepetition = 3
    }
    // 0 : gauche, 1 : droite, 2 : haut, 3 : bas, 4 : colorier.
    const mvtOppose = [1, 0, 3, 2, 4]
    const lstCommandesTikz = ['\\blockmove{Aller à gauche}', '\\blockmove{Aller à droite}', '\\blockmove{Aller en haut}', '\\blockmove{Aller en bas}', '\\blockmove{Colorier la case}']
    const lstCommandesSVG = ['Aller à gauche', 'Aller à droite', 'Aller en haut', 'Aller en bas', 'Colorier']
    const lstAjoutXY = [[-1, 0], [1, 0], [0, 1], [0, -1], [0, 0]]
    codeTikz += '\\medskip \\begin{scratch} <br>'
    codeSvg += '<pre class=\'blocks\'>'
    let n = 0 // variable temporaire pour stocker le numéro de la commande
    const lstNumCommande = [] // liste des commandes successives
    const lstX = [0] // liste des abscisses successives
    const lstY = [0] // liste des ordonnées successives
    if (this.sup2) {
      codeSvg += `répéter (${nbRepetition}) fois <br>`
      codeTikz += `\\blockrepeat{répéter \\ovalnum{${nbRepetition}} fois} {`
    }
    n = 4
    for (let i = 0; i < nbCommandes; i++) {
      n = this.sup3 ? choice([0, 1, 2, 3], [mvtOppose[n]]) : choice([0, 1, 2, 3]) // choix d'un déplacement
      codeTikz += lstCommandesTikz[n] // ajout d'un déplacement
      codeSvg += lstCommandesSVG[n] + '<br>' // ajout d'un déplacement
      codeTikz += lstCommandesTikz[4] // ajout de l'instruction "Colorier"
      codeSvg += lstCommandesSVG[4] + '<br>' // ajout de l'instruction "Colorier"
      lstNumCommande.push(n) // ajout d'un déplacement
      lstNumCommande.push(4) // ajout de l'instruction "Colorier"
      lstX.push(lstX[lstX.length - 1] + lstAjoutXY[n][0]) // calcul de la nouvelle abscisse
      lstY.push(lstY[lstY.length - 1] + lstAjoutXY[n][1]) // calcul de la nouvelle ordonnée
    }
    for (let j = 0; j < nbRepetition - 1; j++) {
      for (let i = 0; i < 2 * nbCommandes; i++) {
        lstX.push(lstX[lstX.length - 1] + lstAjoutXY[lstNumCommande[i]][0])
        lstY.push(lstY[lstY.length - 1] + lstAjoutXY[lstNumCommande[i]][1])
      }
    }
    if (this.sup2) {
      codeSvg += 'fin <br>'
      codeTikz += '}'
    }
    codeSvg += '</pre>'
    codeTikz += '\\end{scratch}'

    const xLutinMin = Math.min(...lstX)
    const xLutinMax = Math.max(...lstX)
    const yLutinMin = Math.min(...lstY)
    const yLutinMax = Math.max(...lstY)

    if (context.isHtml) {
      texte += '<table style="width: 100%"><tr><td>'
    } else {
      texte += '\\begin{minipage}[t]{.25\\textwidth}'
    }

    texte += scratchblocksTikz(codeSvg, codeTikz)

    if (context.isHtml) {
      texte += '</td><td>'
      texte += '             '
      texte += '</td><td style="vertical-align: top; text-align: center">'
    } else {
      texte += '\\end{minipage} '
      texte += '\\hfill \\begin{minipage}[t]{.74\\textwidth}'
    }

    const xGrilleMin = xLutinMin - 1
    const xGrilleMax = xLutinMax + 2
    const yGrilleMin = yLutinMin - 2
    const yGrilleMax = yLutinMax + 1

    const r2 = grille(xGrilleMin, yGrilleMin, xGrilleMax, yGrilleMax, 'black', 0.8, 1)
    const lstObjet = [r2] // liste de tous les objets Mathalea2d

    let p // carré gris représentant le lutin en position de départ
    p = polygone(point(lstX[0], lstY[0]), point(lstX[0] + 1, lstY[0]), point(lstX[0] + 1, lstY[0] - 1), point(lstX[0], lstY[0] - 1))
    p.opacite = 0.5
    p.couleurDeRemplissage = colorToLatexOrHTML('black')
    p.opaciteDeRemplissage = 0.5
    p.epaisseur = 0
    lstObjet.push(p)
    let txt = '' // variable temporaire
    for (let j = 0; j < (xGrilleMax - xGrilleMin); j++) {
      txt = String.fromCharCode(65 + j) // ascii 65 = A
      lstObjet.push(texteParPosition(txt, xGrilleMin + j + 0.5, yGrilleMax + 0.5, 'milieu', 'black', 1)) // affiche de A à J... en haut de la grille
    }
    for (let i = 0; i < (yGrilleMax - yGrilleMin); i++) {
      lstObjet.push(texteParPosition(String(i), xGrilleMin - 0.25, yGrilleMax - i - 0.5, 'gauche', 'black', 1)) // affiche de 0 à 9... à gauche de la grille
    }

    texte += 'Au départ, le lutin est situé dans la case grisée. Chaque déplacement se fait dans une case adjacente. Exécuter le programme.<br><br>'
    if (!context.isHtml) { texte += '\\begin{center}' }
    texte += mathalea2d({ xmin: xGrilleMin - 3, xmax: xGrilleMax + 1, ymin: yGrilleMin - 1, ymax: yGrilleMax + 1, pixelsParCm: 20, scale: 0.5 }, lstObjet)
    if (context.isHtml) {
      texte += '</td></tr></table>'
    } else {
      texte += '\\end{center}\\end{minipage} '
      texte += '\\hfill \\null'
    }

    // CORRECTION
    // 0 : gauche, 1 : droite, 2 : haut, 3 : bas, 4 : colorier.
    let xLutin = 0 // position initiale du carré
    let yLutin = 0 // position initiale du carré
    const couleur = 'red'

    // on fait un dessin par passage dans la boucle
    if (context.isHtml) {
      texteCorr += '<table style="width:100%"><tr><td style="text-align:center">'
    } else {
      texteCorr += '\\begin{minipage}{.49\\textwidth}'
    }
    for (let k = 0; k < nbRepetition; k++) {
      for (let i = k * lstNumCommande.length; i < (k + 1) * lstNumCommande.length; i++) {
        switch (lstNumCommande[i % lstNumCommande.length]) {
          case 0:
            xLutin += -1; break
          case 1:
            xLutin += 1; break
          case 2:
            yLutin += 1; break
          case 3:
            yLutin += -1; break
          case 4:
            p = polygone(point(xLutin, yLutin), point(xLutin + 1, yLutin), point(xLutin + 1, yLutin - 1), point(xLutin, yLutin - 1))
            p.couleurDeRemplissage = couleur
            p.opaciteDeRemplissage = 0.25
            p.epaisseur = 0
            lstObjet.push(p)
        }
      }
      if (this.sup2) {
        texteCorr += `Passage n° ${k + 1} dans la boucle : <br>`
      }
      texteCorr += mathalea2d({ xmin: xGrilleMin - 3, xmax: xGrilleMax + 1, ymin: yGrilleMin - 1, ymax: yGrilleMax + 1, pixelsParCm: 20, scale: 0.4 }, lstObjet)
      if (context.isHtml) {
        if (k % 3 === 2) {
          texteCorr += '</td></tr><tr><td style="text-align:center">' // retour à la ligne après 3 grilles dessinées en HTML
        } else {
          texteCorr += '</td><td></td><td style="text-align:center">'
        }
      } else {
        texteCorr += '\\end{minipage}'
        if (k % 2 === 1) { texteCorr += '\\\\ ' } // retour à la ligne après 2 grilles dessinées en LaTeX
        texteCorr += '\\begin{minipage}{.49\\textwidth}'
      }
    }
    context.isHtml ? texteCorr += '</td></tr></table>' : texteCorr += '\\end{minipage}'

    if (context.isAmc) {
      this.autoCorrection = [{ propositions: [{ statut: 3, sanscadre: true }] }]
    }

    this.listeQuestions.push(texte)
    this.listeCorrections.push(texteCorr)
    listeQuestionsToContenu(this)
  }
  this.besoinFormulaireNumerique = ['Nombre d\'instructions de déplacements', 3, '1 : 3 instructions\n2 : 4 instructions\n3 : 5 instructions']
  this.besoinFormulaire2CaseACocher = ['Avec une boucle']
  this.besoinFormulaire3CaseACocher = ['Sans retour sur ses pas']
}