import Exercice from '../Exercice.js'
import { mathalea2d } from '../../modules/2dGeneralites.js'
import { listeQuestionsToContenu, randint, lettreDepuisChiffre, choice, couleurTab, miseEnEvidence, sp, rangeMinMax, numAlpha, enleveElement, combinaisonListes } from '../../modules/outils.js'
import { point, pointSurSegment, segment, polygoneAvecNom, labelPoint, droite, pointIntersectionDD, codageAngle, angleOriente, polyline } from '../../modules/2d.js'
import { min, max } from 'mathjs'
import { ajouteChampTexteMathLive } from '../../modules/interactif/questionMathLive.js'
import { setReponse } from '../../modules/gestionInteractif.js'
import { context } from '../../modules/context.js'
import { propositionsQcm } from '../../modules/interactif/questionQcm.js'
export const titre = 'Nommer un angle'
export const interactifType = ['qcm', 'mathLive']
export const interactifReady = true
export const amcType = 'AMCHybride' // Question numérique
export const amcReady = true // Il reste à gérer les options numériques
export const dateDePublication = '13/04/2022'
/**
* Nommer un angle
* Ref 6G22
* @author Eric Elter
* Publié le 13/04/2022
*/
export const uuid = 'e10d1'
export const ref = '6G22'
export default function NommerUnAngle () {
Exercice.call(this) // Héritage de la classe Exercice()
this.consigne = ''
this.nbQuestions = 2
this.sup = 2
this.sup2 = 1
this.sup3 = false
this.nouvelleVersion = function () {
this.listeQuestions = [] // Liste de questions
this.listeCorrections = [] // Liste de questions corrigées
this.autoCorrection = []
this.interactifType = this.sup2 === 2 ? 'mathLive' : 'qcm'
let propositionsDuQcm = []
for (let i = 0, texteAMC, troisBonnesReponses, listePt1, listePt3, resultatOK1, resultatOK2, resultat3, resultatPasOK1, resultatPasOK2, choixAngle, pt1, pt2, pt3, tailleAngle, aleaChoixCouleurRemplissage, couleurRemplissageAngle, couleurAngle, segmentsCorrection, resultat; i < this.nbQuestions; i++) {
const propositionsAMC = []
// let figureExo
// On prépare la figure...
const marquageAngle = this.sup3 ? combinaisonListes(['X', 'OO', '|||'], 3) : ['', '', '']
const ChoixHorizontal = choice([-1, 1])
const numB = randint(1, 26, [4, 5, 15, 23, 24, 25])
const numA = randint(1, 26, [4, 5, 15, 23, 24, 25, numB])
const numC = randint(1, 26, [4, 5, 15, 23, 24, 25, numB, numA])
const numM = randint(1, 26, [4, 5, 15, 23, 24, 25, numB, numA, numC])
const numN = randint(1, 26, [4, 5, 15, 23, 24, 25, numB, numA, numC, numM])
const numI = randint(1, 26, [4, 5, 15, 23, 24, 25, numB, numA, numC, numM, numN])
/* A décommenter pour débugguer (et commenter les 6 lignes du dessus)
const numA = 1
const numB = 2
const numC = 3
const numI = 9
const numM = 13
const numN = 14
*/
const ordB = randint(0, 2)
const B = point(0, ordB, lettreDepuisChiffre(numB))
const absA = ChoixHorizontal * randint(7, 12)
const ordA = randint(4, 8)
const A = point(absA, ordA, lettreDepuisChiffre(numA))
const absC = ChoixHorizontal * randint(7, 12, [absA])
const ordC = -1 * randint(2, 5)
const C = point(absC, ordC, lettreDepuisChiffre(numC))
const fractionSegmentAB = this.sup === 1 ? randint(2, 8) : randint(4, 6)
const fractionSegmentBC = this.sup === 1 ? randint(2, 8, [fractionSegmentAB]) : randint(4, 6, [fractionSegmentAB])
const AB = segment(A, B).longueur
const BC = segment(B, C).longueur
const M = pointSurSegment(B, A, AB * fractionSegmentAB / 10, lettreDepuisChiffre(numM))
const N = pointSurSegment(B, C, BC * fractionSegmentBC / 10, lettreDepuisChiffre(numN), 'below')
const p1 = polygoneAvecNom(B, A, C)
const I = pointIntersectionDD(droite(A, N), droite(C, M), lettreDepuisChiffre(numI), 'left')
const listePoints = [numA, numB, numC, numM, numN, numI]
const objetsEnonce = []
const objetsCorrection = []
const sommetsDejaTrouves = []
const choixCouleurRemplissage = rangeMinMax(0, 7)
// couleurRemplissageAngle = ['none'] // Correction J-C : on définira ces couleurs en testant this.sup3
// couleurAngle = 'black'
let texte = ''
const O = point(0, 0) // Sert à construire les symboles pour les questions
const M1 = point(4, 0) // Sert à construire les symboles pour les questions
let texteCorr = ''
let positionIbis = ChoixHorizontal === -1 ? 'right' : 'left'
const Ibis = point(I.x, I.y, lettreDepuisChiffre(numI), positionIbis)
for (let jj = 0, marquageAngleConsigne; jj < this.sup; jj++) {
marquageAngleConsigne = []
const choixSommet = choice(listePoints, sommetsDejaTrouves)
if (!this.sup3) {
aleaChoixCouleurRemplissage = choice(choixCouleurRemplissage)
couleurRemplissageAngle = couleurTab(aleaChoixCouleurRemplissage)
couleurAngle = couleurRemplissageAngle[0]
enleveElement(choixCouleurRemplissage, aleaChoixCouleurRemplissage)
} else {
couleurRemplissageAngle = ['none']
couleurAngle = 'black'
}
sommetsDejaTrouves[jj] = choixSommet
switch (choixSommet) {
case numA: // Si le sommet est A, alors il y a 3 choix possibles d'angles
pt2 = A
tailleAngle = min(segment(pt2, M).longueur, segment(pt2, N).longueur, segment(pt2, I).longueur, 4) / 2 * 0.9
choixAngle = 1
switch (choixAngle) {
case 1 :
listePt1 = [B, M]
listePt3 = [N, I]
break
case 2 :
listePt1 = [C]
listePt3 = [N, I]
break
case 3 :
listePt3 = [B, M]
listePt1 = [C]
break
}
break
case numC : // Si le sommet est C, alors il y a 3 choix possibles d'angles
pt2 = C
choixAngle = randint(1, 3)
tailleAngle = min(segment(pt2, M).longueur, segment(pt2, N).longueur, segment(pt2, I).longueur, 4) / 2 * 0.9
switch (choixAngle) {
case 1 :
listePt1 = [B, N]
listePt3 = [M, I]
break
case 2 :
listePt3 = [M, I]
listePt1 = [A]
break
case 3 :
listePt3 = [B, N]
listePt1 = [A]
break
}
break
case numB :
pt2 = B
tailleAngle = min(segment(pt2, M).longueur, segment(pt2, N).longueur, segment(pt2, I).longueur, 4) / 2 * 0.9
listePt1 = [C, N]
listePt3 = [A, M]
break
case numM : // Si le sommet est M, alors il y a 2 choix possibles d'angles
pt2 = M
tailleAngle = min(segment(pt2, A).longueur, segment(pt2, C).longueur, segment(pt2, I).longueur, 4) / 2 * 0.9
listePt1 = [C, I]
listePt3 = [randint(1, 2) === 1 ? A : B]
positionIbis = ChoixHorizontal === -1 ? 'left' : 'right'
break
case numN : // Si le sommet est N, alors il y a 2 choix possibles d'angles
pt2 = N
tailleAngle = min(segment(pt2, A).longueur, segment(pt2, C).longueur, segment(pt2, I).longueur, 4) / 2 * 0.9
listePt1 = [A, I]
listePt3 = [randint(1, 2) === 1 ? C : B]
break
case numI:
pt2 = I
choixAngle = randint(1, 4)
switch (choixAngle) {
case 1:
listePt1 = [M]
listePt3 = [A]
break
case 2:
listePt1 = [C]
listePt3 = [A]
positionIbis = ChoixHorizontal === -1 ? 'right' : 'left'
break
case 3:
listePt1 = [N]
listePt3 = [C]
break
case 4:
listePt1 = [N]
listePt3 = [M]
positionIbis = ChoixHorizontal === -1 ? 'left' : 'right'
break
}
tailleAngle = min(segment(pt2, listePt1[0]).longueur, segment(pt2, listePt3[0]).longueur, 4) / 2 * 0.9
}
pt1 = choice(listePt1) // Une fois la possibilité d'angle choisie, il y a deux points possibles.
pt3 = choice(listePt3)
segmentsCorrection = polyline([listePt1[0], pt2, listePt3[0]], this.sup3 ? 'black' : couleurRemplissageAngle[0])
resultat = []
for (const item1 in listePt1) {
for (const item3 in listePt3) {
resultat.push(`\\widehat{${listePt1[item1].nom}${pt2.nom}${listePt3[item3].nom}}`)
resultat.push(`\\widehat{${listePt3[item3].nom}${pt2.nom}${listePt1[item1].nom}}`)
}
}
// Les 5 résultats suivants sont pour le QCM
// 2 résultats corrects, 2 résultats faux et un 5e résultat faux ou vrai, selon l'exercice.
resultatOK1 = choice(resultat)
resultatOK2 = choice(resultat, [resultatOK1])
resultatPasOK1 = `\\widehat{${pt2.nom}${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}}`
resultatPasOK2 = `\\widehat{${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}${pt2.nom}}`
troisBonnesReponses = false
if (choixSommet === numI) { // Si I est le sommet, que deux bonnes réponses.
resultat3 = choice([`\\widehat{${listePt3[0].nom}${listePt1[0].nom}${pt2.nom}}`, `\\widehat{${pt2.nom}${listePt3[0].nom}${listePt1[0].nom}}`])
} else {
troisBonnesReponses = choice([true, false])
if (troisBonnesReponses) { // Une 3e réponse vraie
resultat3 = choice(resultat, [resultatOK1, resultatOK2])
} else if (choice([true, false])) { // Une 3e réponse fausse
resultat3 = `\\widehat{${pt2.nom}${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}}`
while (resultat3 === resultatPasOK1) resultat3 = `\\widehat{${pt2.nom}${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}}`
} else {
resultat3 = `\\widehat{${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}${pt2.nom}}`
while (resultat3 === resultatPasOK2) resultat3 = `\\widehat{${listePt1[randint(0, listePt1.length - 1)].nom}${listePt3[randint(0, listePt3.length - 1)].nom}${pt2.nom}}`
}
}
segmentsCorrection.epaisseur = 3
const ang = angleOriente(pt1, pt2, pt3)
objetsEnonce.push(codageAngle(pt1, pt2, ang, tailleAngle, marquageAngle[jj], couleurAngle, 2, 1, couleurRemplissageAngle[0], 1, false, true))
texteAMC = 'Comment peut-on nommer l\'angle '
marquageAngleConsigne.push(codageAngle(M1, O, 79, 1, marquageAngle[jj]))
texteAMC += this.sup3
? 'marqué par le symbole' + mathalea2d({ xmin: 0, ymin: 0, xmax: 1.2, ymax: 1.2, pixelsParCm: 20, scale: 0.5, style: 'display:inline' }, marquageAngleConsigne) + `${sp()}?`
: `${couleurRemplissageAngle[1]}${sp()}?`
texte += this.sup > 1 ? `${jj === 0 ? '' : '<br>'}${numAlpha(jj)}` : ''
texte += texteAMC
if (this.interactif && this.interactifType === 'mathLive') {
texte += ajouteChampTexteMathLive(this, i * this.sup + jj, 'inline largeur25')
}
setReponse(this, i * this.sup + jj, resultat, { formatInteractif: 'texte' })
objetsCorrection.push(codageAngle(pt1, pt2, ang, tailleAngle, marquageAngle[jj], couleurAngle, 2, 1, couleurRemplissageAngle[0], 1, false, true), segmentsCorrection)
texteCorr += this.sup > 1 ? `${jj === 0 ? '' : '<br>'}${numAlpha(jj)}` : ''
texteCorr += 'L\'angle '
texteCorr += this.sup3
? 'marqué par le symbole' + mathalea2d({ xmin: 0, ymin: 0, xmax: 1.2, ymax: 1.2, pixelsParCm: 20, scale: 0.5, style: 'display:inline' }, marquageAngleConsigne)
: `${couleurRemplissageAngle[1]}`
texteCorr += ` se nomme, au choix : $${this.sup3 ? miseEnEvidence(resultat[0], 'black') : miseEnEvidence(resultat[0], couleurRemplissageAngle[0])}$`
for (let ee = 1; ee < resultat.length; ee++) {
texteCorr += `, $${this.sup3 ? miseEnEvidence(resultat[0], 'black') : miseEnEvidence(resultat[ee], couleurRemplissageAngle[0])}$`
}
texteCorr += '.'
propositionsDuQcm = [{
texte: `$${resultatOK1}$`,
statut: true
},
{
texte: `$${resultatOK2}$`,
statut: true
},
{
texte: `$${resultat3}$`,
statut: troisBonnesReponses
},
{
texte: `$${resultatPasOK1}$`,
statut: false
},
{
texte: `$${resultatPasOK2}$`,
statut: false
}]
if (this.interactif && this.interactifType === 'qcm') {
this.autoCorrection[i * this.sup + jj].enonce = `${texte}\n`
this.autoCorrection[i * this.sup + jj].propositions = propositionsDuQcm
this.autoCorrection[i * this.sup + jj].options = {}
texte += propositionsQcm(this, i * this.sup + jj).texte
}
if (context.isAmc) {
propositionsAMC[jj] = {
type: 'qcmMult', // on donne le type de la première question-réponse qcmMono, qcmMult, AMCNum, AMCOpen
enonce: texteAMC,
propositions: propositionsDuQcm
}
}
}
const params = { xmin: min(0, absA, absC) - 1, ymin: ordC - 1, xmax: max(0, absA, absC) + 1, ymax: ordA + 1, pixelsParCm: 20, scale: 0.5 }
objetsEnonce.push(p1[0], p1[1], segment(A, N), segment(C, M), labelPoint(M, N, Ibis))
objetsCorrection.push(p1[0], p1[1], segment(A, N), segment(C, M), labelPoint(M, N, Ibis))
const figureExo = mathalea2d(params, objetsEnonce)
texte += '<br>' + figureExo
texteCorr += '<br>' + mathalea2d(params, objetsCorrection)
if (context.isAmc) {
this.autoCorrection[i] = {
enonce: figureExo,
enonceAvant: true, // EE : ce champ est facultatif et permet (si false) de supprimer l'énoncé ci-dessus avant la numérotation de chaque question.
enonceCentre: true, // EE : ce champ est facultatif et permet (si true) de centrer le champ 'enonce' ci-dessus.
melange: true, // EE : ce champ est facultatif et permet (si false) de ne pas provoquer le mélange des questions.
options: { avecSymboleMult: true }, // facultatif. Par défaut, multicols est à false. Ce paramètre provoque un multicolonnage (sur 2 colonnes par défaut) des propositions : pratique quand on met plusieurs AMCNum. !!! Attention, cela ne fonctionne pas, nativement, pour AMCOpen. !!!
propositions: propositionsAMC
}
}
this.listeQuestions.push(texte)
this.listeCorrections.push(texteCorr)
listeQuestionsToContenu(this)
}
}
this.besoinFormulaireNumerique = ['Nombre d\'angles à trouver', 3, '1, 2 ou 3 angles']
if (context.isHtml) this.besoinFormulaire2Numerique = ['Exercice interactif', 2, '1 : QCM\n2 : Texte']
this.besoinFormulaire3CaseACocher = ['Figure en noir et blanc']
}