modules/pyramide.js

import { fraction } from './fractions.js'
import { randint, stringNombre, choice } from './outils.js'
import { boite } from './2d.js'

export default class Pyramide {
  /**
 *
 * @param {object} param0
 * @param {string} param0.operation
 * @param {number} param0.nombreEtages
 * @param {number[]|number[][]} param0.rangeData
 * @param {number[]}  param0.exclusions
 * @param {boolean} param0.fractionOn
 */
  constructor ({ operation = '+', nombreEtages = 3, rangeData = [1, 10], exclusions = [], fractionOn = false } = {}) {
    this.operation = operation
    this.nombreEtages = nombreEtages
    this.rangeData = rangeData
    this.valeurs = []
    this.isVisible = []
    this.fractionOn = fractionOn
    for (let y = nombreEtages - 1; y >= 0; y--) {
      this.valeurs[y] = []
      this.isVisible[y] = []
      for (let x = 0, num, den; x <= y; x++) {
        if (y === nombreEtages - 1) {
          if (this.fractionOn) {
            den = choice(rangeData[1])
            num = randint(rangeData[0][0], rangeData[0][1], exclusions.concat([den]))
            this.valeurs[y][x] = fraction(num, den).simplifie()
          } else {
            this.valeurs[y][x] = randint(rangeData[0], rangeData[1], exclusions)
          }
        } else {
          switch (operation) {
            case '+':
              if (this.fractionOn) {
                this.valeurs[y][x] = this.valeurs[y + 1][x].sommeFraction(this.valeurs[y + 1][x + 1]).simplifie()
              } else {
                this.valeurs[y][x] = this.valeurs[y + 1][x] + this.valeurs[y + 1][x + 1]
              }
              break
            case '*':
              if (this.fractionOn) {
                this.valeurs[y][x] = this.valeurs[y + 1][x].produitFraction(this.valeurs[y + 1][x + 1]).simplifie()
              } else {
                this.valeurs[y][x] = this.valeurs[y + 1][x] * this.valeurs[y + 1][x + 1]
              }

              break
          }
        }
        this.isVisible[y][x] = false
      }
    }
  }

  visible = (x, y) => { return this.isVisible[y][x] }
  estSolvable = function (x, y) {
    if (this.visible(x, y)) return true
    else if (y === this.nombreEtages - 1) return false
    else return this.estSolvable(x, y + 1) && this.estSolvable(x + 1, y + 1)
  }

  choisisUneCaseNonVisible = function () {
    let x, y
    let trouve = false
    let cpt = 0
    do {
      cpt++
      y = randint(1, this.nombreEtages - 1)
      x = randint(0, y)
      let seul = true
      for (let i = 0; i < y; i++) {
        if (i !== x && !this.visible(i, y)) seul = false
      }
      if (seul && cpt < 20) trouve = false
      else trouve = !this.visible(x, y)
    } while (!trouve)
    return [x, y]
  }

  aleatoirise = function () {
    let solvable = false
    do {
      const [x, y] = this.choisisUneCaseNonVisible()
      this.isVisible[y][x] = true
      solvable = this.estSolvable(0, 0)
    } while (!solvable)
  }

  representeMoi = function (xO = 0, yO = 0) {
    const objets = []
    const hCase = this.fractionOn ? 2 : 1
    for (let y = this.nombreEtages; y > 0; y--) {
      for (let x = 0; x < y; x++) {
        if (this.isVisible[y - 1][x]) {
          objets.push(boite({
            Xmin: xO + x * 4 + (this.nombreEtages - y) * 2,
            Ymin: yO + (this.nombreEtages - y) * hCase,
            Xmax: xO + x * 4 + 4 + (this.nombreEtages - y) * 2,
            Ymax: yO + (1 + this.nombreEtages - y) * hCase,
            texteIn: this.fractionOn ? `$${this.valeurs[y - 1][x].texFractionSimplifiee}$` : stringNombre(this.valeurs[y - 1][x], 0),
            texteOpacite: 1
          }))
        } else {
          objets.push(boite({
            Xmin: xO + x * 4 + (this.nombreEtages - y) * 2,
            Ymin: yO + (this.nombreEtages - y) * hCase,
            Xmax: xO + x * 4 + 4 + (this.nombreEtages - y) * 2,
            Ymax: yO + (1 + this.nombreEtages - y) * hCase,
            texteIn: '',
            texteOpacite: 1
          }))
        }
      }
    }
    return objets
  }
}