import { HttpClient } from "@angular/common/http";
import { AppUtils, Fraction } from "../app-utils";
import { CabriDataService } from "../services/cabri-data.service";
import { ConnectionStatus, NetworkService } from "../services/network.service";
declare var window: {
store: any;
document: any;
URL: any;
};
declare var MathJax: {
startup: any;
svg: any;
tex: any;
tex2svg: any;
tex2svgPromise: any;
loader: any;
Hub: any;
config: any;
tex2mml: any;
defsGlobalCaching: any;
};
export class Probleme {
consigne: string;
consigneTTS: string;
listes = [];
saveListes = [];
problemes = [];
cabri: CabriDataService;
networkService: NetworkService;
randomI: number;
constructor(cabri: CabriDataService, http: HttpClient, networkService: NetworkService) {
this.cabri = cabri;
this.networkService = networkService;
this.debug(cabri.currentActivity);
this.debug(cabri.currentExercice);
// filter compatible problems
this.problemes = cabri.resoproData.problems
.filter(p => {
return this.isCompatible(p);
})
.slice();
console.log(this.cabri.currentActivity.currentVariables);
console.log(this.problemes)
// choose one randomly
this.randomI = Math.floor(Math.random() * this.problemes.length);
this.consigne = this.problemes[this.randomI].consigne;
this.debug(this.problemes[this.randomI]);
if (this.networkService.isConnected) {
// switch background
const backgrounds = cabri.resoproData.environnements.filter(e => {
this.debug(e);
return e.id === this.problemes[this.randomI].environment && e.image_url;
});
this.debug(backgrounds);
if (backgrounds && backgrounds.length > 0) {
const randomB = Math.floor(Math.random() * backgrounds.length);
cabri.forceBackgroundTexture = backgrounds[randomB].image_url;
window.store.getters.cabri.Scene.meshes.forEach(async m => {
if (m.id === "background") {
const textureContext = m.material.diffuseTexture.getContext();
const canvasWidth = window.document.getElementById("renderCanvas1").clientWidth;
const canvasHeight = window.document.getElementById("renderCanvas1").clientHeight;
AppUtils.setCabriBackground(
http,
m.material.diffuseTexture,
textureContext,
backgrounds[randomB].image_url,
canvasWidth,
canvasHeight
);
}
});
}
}
}
async init() {
const prononciationsFractions = {
2: "demi",
3: "tiers",
4: "quart",
5: "cinquième",
6: "sixième",
7: "septième",
8: "huitième",
9: "neuvième",
10: "dixième",
11: "onzième",
12: "douzième"
}
this.consigneTTS = this.consigne;
for (let i = 1; i <= 4; i++) {
const key = `nb${i}`;
const value = this.cabri.currentActivity.currentVariables[key];
if (value) {
if (value instanceof Fraction) {
this.consigneTTS = this.consigneTTS.replace(
new RegExp(`\\$${key}\\$`, "g"),
value.numerateur + prononciationsFractions[value.denominateur]
)
const element = await MathJax.tex2svgPromise(value.toLatex());
this.consigne = this.consigne.replace(
new RegExp(`\\$${key}\\$`, "g"),
element.outerHTML
);
} else {
this.consigne = this.consigne.replace(
new RegExp(`\\$${key}\\$`, "g"),
value.toFixed(8).replace(/\.?0+$/, "").replace(".",",").replace(/\B(?=(\d{3})+(?!\d))/g, "\u00A0")
);
this.consigneTTS = this.consigneTTS.replace(
new RegExp(`\\$${key}\\$`, "g"),
value.toFixed(8).replace(/\.?0+$/, "").replace(".",",").replace(/\B(?=(\d{3})+(?!\d))/g, "\u00A0")
);
}
}
}
this.cabri.resoproData.listes.forEach(element => {
this.listes[element.list_key.toLowerCase()] = JSON.parse(JSON.stringify(element.list_values));
this.saveListes[element.list_key.toLowerCase()] = JSON.parse(JSON.stringify(element.list_values));
});
// custom lists
if (this.problemes[this.randomI].cl1) {
// tslint:disable-next-line: no-string-literal
this.listes["cl1"] = this.problemes[this.randomI].cl1.split("\r\n");
}
if (this.problemes[this.randomI].cl2) {
// tslint:disable-next-line: no-string-literal
this.listes["cl2"] = this.problemes[this.randomI].cl2.split("\r\n");
}
if (this.problemes[this.randomI].cl3) {
// tslint:disable-next-line: no-string-literal
this.listes["cl3"] = this.problemes[this.randomI].cl3.split("\r\n");
}
// search lists in consigne
let reg = new RegExp("(\\$[^\\$]*\\$)", "gi");
let result;
let securityCounter = 0;
// tslint:disable-next-line: no-conditional-assignment
while ((result = reg.exec(this.consigne)) && result?.length > 0 && securityCounter < 100) {
this.debug(result);
const listKey = result[0];
let listKey2;
let variableName;
if (listKey.indexOf("=") > -1) {
const tmp = listKey.replace(new RegExp("\\$", "g"), "").toLowerCase();
const tmp2 = tmp.split("=");
variableName = tmp[0];
listKey2 = tmp2[1];
} else {
listKey2 = listKey.replace(new RegExp("\\$", "g"), "").toLowerCase();
}
this.debug(listKey2);
if (this.listes[listKey2]) {
// pick a random word in list
const randomWord = this.pickOneWord(listKey2);
// save it for reuse
if (variableName) {
this.listes[variableName] = [randomWord];
this.saveListes[variableName] = [randomWord];
}
// put it in consigne
this.consigne = this.consigne.replace(listKey, randomWord);
this.consigneTTS = this.consigneTTS.replace(listKey, randomWord);
}
this.debug(this.consigne);
// reset RegEX to avoid bug
reg = new RegExp("(\\$[^\\$]*\\$)", "gi");
securityCounter++;
}
this.debug(result);
}
pickOneWord(listKey) {
// pick a random word in list
const randomIndex = Math.floor(Math.random() * this.listes[listKey].length);
const randomWord = this.listes[listKey][randomIndex];
// remove the selected word from array
this.listes[listKey] = this.listes[listKey].filter(item => item !== randomWord);
// repopulate list if empty
if (this.listes[listKey].length === 0 && this.saveListes[listKey]) {
this.listes[listKey] = this.saveListes[listKey];
}
return randomWord;
}
isCompatible(p: any) {
// exercice's numbers
const nb1 = this.cabri.currentActivity.currentVariables.nb1;
const nb2 = this.cabri.currentActivity.currentVariables.nb2;
const nb3 = this.cabri.currentActivity.currentVariables.nb3;
const nb4 = this.cabri.currentActivity.currentVariables.nb4;
const result = this.cabri.currentActivity.currentVariables.result;
const op = this.cabri.currentActivity.currentVariables.operation;
const opCustom = this.cabri.currentActivity.currentVariables._customOperation;
const type_pb = this.cabri.currentActivity.currentVariables.type_pb;
const discordant = type_pb != 11 ? this.cabri.currentActivity.currentVariables.discordant : undefined;
// if problem concordant, p.analogie === "1", else "2"
if (p.cycle_3 && p.cycle_3 === "1") {
if (discordant !== undefined && p.analogie !== undefined && p.analogie !== discordant) {
return false;
}
if (!opCustom && (type_pb !== undefined && p.type_pb !== undefined && p.type_pb != type_pb)) {
return false;
}
if (p.operation_custom && opCustom && p.operation_custom !== opCustom) {
return false;
}
}
if (op !== p.operation) {
return false;
}
const nb1dec = nb1 instanceof Fraction ? 10 : (nb1.toString().indexOf(".") > -1) ? Number(nb1.toFixed(8)).toString().length - 1 - nb1.toString().indexOf(".") : 0;
const nb2dec = nb2 instanceof Fraction ? 10 : (nb2.toString().indexOf(".") > -1) ? Number(nb2.toFixed(8)).toString().length - 1 - nb2.toString().indexOf(".") : 0;
const nb3dec = nb3 instanceof Fraction ? 10 : (nb3 && nb3.toString().indexOf(".") > -1) ? Number(nb3.toFixed(8)).toString().length - 1 - nb3.toString().indexOf(".") : 0;
const nb4dec = nb4 instanceof Fraction ? 10 : (nb4 && nb4.toString().indexOf(".") > -1) ? Number(nb4.toFixed(8)).toString().length - 1 - nb4.toString().indexOf(".") : 0;
const nb1decMax = Number(p.nb1_dec ?? 0);
const nb2decMax = Number(p.nb2_dec ?? 0);
const nb3decMax = Number(p.nb3_dec ?? 0);
const nb4decMax = Number(p.nb4_dec ?? 0);
if (nb1dec > nb1decMax || nb2dec > nb2decMax || nb3dec > nb3decMax || nb4dec > nb4decMax) {
return false;
}
if ((nb3 && p.consigne.indexOf("$nb3$") == -1) || (nb4 && p.consigne.indexOf("$nb4$") == -1)) {
return false;
}
if ((!nb3 && p.consigne.indexOf("$nb3$") > -1) || (!nb4 && p.consigne.indexOf("$nb4$") > -1)) {
return false;
}
// problem's constraints nb1
let tmp = p.bornes_nb1.split("<");
let min = Number(tmp[0]);
let max = Number(tmp[2]);
if (nb1 < min || nb1 > max) {
return false;
}
// problem's constraints nb2
tmp = p.bornes_nb2.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (nb2 < min || nb2 > max) {
return false;
}
// problem's constraints nb3
if (nb3 && p.bornes_nb3) {
tmp = p.bornes_nb3.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (nb3 < min || nb3 > max) {
return false;
}
}
// problem's constraints nb4
if (nb4 && p.bornes_nb4) {
tmp = p.bornes_nb4.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (nb4 < min || nb4 > max) {
return false;
}
}
// problem's constraints result
tmp = p.bornes_resultat.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (result < min || result > max) {
return false;
}
return true;
}
debug($message, on = false) {
if (on) {
console.error($message);
}
}
}
export class PrintProbleme {
consigne: string;
listes = [];
saveListes = [];
problemes = [];
cabri: CabriDataService;
networkService: NetworkService;
constructor(cabri: CabriDataService, http: HttpClient, networkService: NetworkService) {
this.cabri = cabri;
this.networkService = networkService;
this.debug(cabri.currentActivity);
this.debug(cabri.currentExercice);
// filter compatible problems
this.problemes = cabri.resoproData.problems;
this.problemes.forEach(p => {
this.consigne = p.consigne;
this.debug(p);
this.consigne = this.consigne.replace(new RegExp("\\$nb1\\$", "g"), String(Math.round(Math.random() * 10000)));
this.consigne = this.consigne.replace(new RegExp("\\$nb2\\$", "g"), String(Math.round(Math.random() * 10000)));
cabri.resoproData.listes.forEach(element => {
this.listes[element.list_key.toLowerCase()] = JSON.parse(JSON.stringify(element.list_values));
this.saveListes[element.list_key.toLowerCase()] = JSON.parse(JSON.stringify(element.list_values));
});
// custom lists
if (p.cl1) {
// tslint:disable-next-line: no-string-literal
this.listes["cl1"] = p.cl1.split("\r\n");
}
if (p.cl2) {
// tslint:disable-next-line: no-string-literal
this.listes["cl2"] = p.cl2.split("\r\n");
}
if (p.cl3) {
// tslint:disable-next-line: no-string-literal
this.listes["cl3"] = p.cl3.split("\r\n");
}
// search lists in consigne
let reg = new RegExp("(\\$[^\\$]*\\$)", "gi");
let result;
let securityCounter = 0;
// tslint:disable-next-line: no-conditional-assignment
while ((result = reg.exec(this.consigne)) && result?.length > 0 && securityCounter < 100) {
this.debug(result);
const listKey = result[0];
let listKey2;
let variableName;
if (listKey.indexOf("=") > -1) {
const tmp = listKey.replace(new RegExp("\\$", "g"), "").toLowerCase();
const tmp2 = tmp.split("=");
variableName = tmp[0];
listKey2 = tmp2[1];
} else {
listKey2 = listKey.replace(new RegExp("\\$", "g"), "").toLowerCase();
}
this.debug(listKey2);
if (this.listes[listKey2]) {
// pick a random word in list
const randomWord = this.pickOneWord(listKey2);
// save it for reuse
if (variableName) {
this.listes[variableName] = [randomWord];
this.saveListes[variableName] = [randomWord];
}
// put it in consigne
this.consigne = this.consigne.replace(listKey, randomWord);
}
this.debug(this.consigne);
// reset RegEX to avoid bug
reg = new RegExp("(\\$[^\\$]*\\$)", "gi");
securityCounter++;
}
console.log(this.consigne);
window.document.getElementById("exportpro").innerHTML += this.consigne + "\n";
this.debug(result);
});
}
pickOneWord(listKey) {
// pick a random word in list
const randomIndex = Math.floor(Math.random() * this.listes[listKey].length);
const randomWord = this.listes[listKey][randomIndex];
// remove the selected word from array
this.listes[listKey] = this.listes[listKey].filter(item => item !== randomWord);
// repopulate list if empty
if (this.listes[listKey].length === 0 && this.saveListes[listKey]) {
this.listes[listKey] = this.saveListes[listKey];
}
return randomWord;
}
isCompatible(p: any) {
// exercice's numbers
const nb1 = this.cabri.currentActivity.currentVariables.nb1;
const nb2 = this.cabri.currentActivity.currentVariables.nb2;
const result = this.cabri.currentActivity.currentVariables.result;
const op = this.cabri.currentActivity.currentVariables.operation;
if (op !== p.operation) {
return false;
}
// problem's constraints nb1
let tmp = p.bornes_nb1.split("<");
let min = Number(tmp[0]);
let max = Number(tmp[2]);
if (nb1 < min || nb1 > max) {
return false;
}
// problem's constraints nb2
tmp = p.bornes_nb2.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (nb2 < min || nb2 > max) {
return false;
}
// problem's constraints result
tmp = p.bornes_resultat.split("<");
min = Number(tmp[0]);
max = Number(tmp[2]);
if (result < min || result > max) {
return false;
}
return true;
}
debug($message, on = false) {
if (on) {
console.error($message);
}
}
}