const isTrue = (currentValue) => currentValue[0] == true;



function generate_perso_level() {

    var isEtNonAllowed = false;
    var isOuNonAllowed = false;
    var isNotAllowed = false;
    var isOuAllowed = false;
    timeEnd = 25;
    double = false;
    isTuto = false;

    createStage("play_container");
    stage.add(layer);
    var logiqueCount = 0;
    for (let i = 0; i < colonneTot; i++) {
        liveColonneNumber.push([]);
    }
    for (let i = 0; i < colonneTot; i++) {
        for (let j = 0; j < numberPerColonne[i]; j++) {
            logiqueCount++;
            let numberRandom = getRandomArbitrary(0, arrayPorte.length);
            insertLogiqueColonne("logique" + logiqueCount, arrayPorte[numberRandom][1], i);
        }
    }


    logiques.forEach(function (element) {
        createLinkAuto(element.name);
    });
    initEndGame();

    timer.stop();
}



function loadPerso() {

    arrayPorte = [
        [document.querySelector("#logique1").checked, "et"],
        [document.querySelector("#logique2").checked, "ou"],
        [document.querySelector("#logique3").checked, "inv"],
        [document.querySelector("#logique4").checked, "etnon"],
        [document.querySelector("#logique5").checked, "nonou"]
    ];
    document.querySelector("#PersoSetupPage").style.display = 'none';
    document.querySelector("#playPage").style.display = 'block';
    resetAllTabs(false);
    niveauActuel = 1;
    timeTot = 0;
    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;
    if (document.querySelector("#colonne_number_setup").value == 0) {
        var porteTotal = parseInt(document.querySelector("#colonne_number_setup_global").value);
        colonneTot = 0;
        while (porteTotal > 2) {
            porteTotal = porteTotal / 2;
            numberPerColonne.push(porteTotal);
            colonneTot++;
        }
        numberPerColonne.push(porteTotal);
        colonneTot++;

    } else {
        colonneTot = parseInt(document.querySelector("#colonne_number_setup").value);
        document.querySelectorAll(".input_refresh").forEach(function (element) {
            numberPerColonne.push(parseInt(element.value));
        });
    }
    arrayPorte = arrayPorte.filter(function (e) {
        if (e[0] === true) return e;
    })
    generate_perso_level();
    isLineCollapsing()
    click = 0;
    let i = 0;
    var error = false;
    while (checkIfEnd()) {
        if (i === NOMBRETEST) {
            error = true;
            break;
        }
        resetAllTabs(false);
        generate_perso_level();
        isLineCollapsing();
        i++;
    }
    if (error) {
        document.location.reload(true);
    }

}

function spin(button) {
    button.childNodes[3].classList = "fa fa-spinner";
}

function stopspin(button) {
    button.childNodes[3].classList = "fa fa-arrow-right";
}

function buttonSpin(button, type) {
    spin(button);
    if (type === 'gen') {
        setTimeout(calcul(true), 20);
    } else
        setTimeout(loadPerso, 1000);
}

document.querySelector("#colonne_number_setup_global_gen").addEventListener('input', (event) => {
    if (parseInt(document.querySelector("#colonne_number_setup_global_gen").value) <= 0) document.querySelector("#colonne_number_setup_global_gen").value = 1;
    calcul();
});

function calcul(launch) {
    var number_const = parseInt(document.querySelector("#colonne_number_setup_global_gen").value);
    var number = number_const;
    var col = new Array();
    let i = 0;
    let reste = 0;
    //Calcul
    if (number === 1) {
        col = [1];
    }
    while (number > 1) {
        number = number / 2;
        if (!Number.isInteger(number) && number > 1) reste = 1;
        if (parseInt(number) + reste != 0)
            col[i] = parseInt(number) + reste;
        reste = 0;
        i++;
    }
    //armonisation : 
    if (col.reduce((a, b) => a + b, 0) > number_const) {
        let arm = col.reduce((a, b) => a + b, 0) - number_const;
        for (let i = col.length - 1; i > col.length - 1 - arm; i--) {
            col[i]--;
        }
    } else if (col.reduce((a, b) => a + b, 0) < number_const) {
        let arm = number_const - col.reduce((a, b) => a + b, 0);
        for (let i = col.length - 1; i > col.length - 1 - arm; i--) {
            col[i]++;
        }
    }
    document.querySelector("#colonnes_live").innerHTML = "Nombre de colonnes : " + col.length + " (" + col + ")";

    var matchs = [];
    var fork = [];
    var count = [];
    for (let i = 0; i < col.length; i++) count[i] = 0;
    var error = null;
    var warning = null;

    document.querySelectorAll(".div_gen_col_fork").forEach(function (element) {
        element.childNodes[0].innerHTML = "Ajouter un fork pour la colonne " + element.childNodes[1].value + " qui se divise en " + element.childNodes[2].value + " ";
        count[(parseInt(element.childNodes[1].value) - 1)] = count[(parseInt(element.childNodes[1].value) - 1)] + parseInt(element.childNodes[2].value);
        matchs.push([(parseInt(element.childNodes[1].value) + 1), parseInt(element.childNodes[2].value)]);
        fork.push([parseInt(element.childNodes[1].value), parseInt(element.childNodes[2].value)]);
        if (parseInt(element.childNodes[1].value) < 1 || parseInt(element.childNodes[1].value) > col.length - 1) {
            error = "Problème sur le numéro de colonne";
            element.childNodes[1].style.borderColor = "red";
        } else {
            element.childNodes[1].style.borderColor = "white";
        }
        if (count[(parseInt(element.childNodes[1].value) - 1)] > col[parseInt(element.childNodes[1].value)] * 2 || count[(parseInt(element.childNodes[1].value) - 1)] > col[parseInt(element.childNodes[1].value) - 1]) {
            error = "Problème nombre de porte dans la colonne";
            element.childNodes[2].style.borderColor = "red";
        } else {
            element.childNodes[2].style.borderColor = "white";
        }
        //calcul des erreur de sorties/entrees potentiels :
        if (count[(parseInt(element.childNodes[1].value) - 1)] > col[parseInt(element.childNodes[1].value)])
            warning = "Problèmes possible lors de la génération ";
        if (element.childNodes[1].value === "" || element.childNodes[1].value === null || element.childNodes[1].value === undefined || element.childNodes[2].value === "" || element.childNodes[2].value === null || element.childNodes[2].value === undefined)
            error = "Element(s) vide";
    });
    if (error !== null) {
        ErrorMessage(error);
        stopspin(document.querySelector("#generate_button_perso"));
        document.querySelector("#generate_button_perso").addEventListener('mouseenter', e => {
            document.querySelector("#generate_button_perso").style.cursor = 'not-allowed';
        });
        document.querySelector("#generate_button_perso").addEventListener('mouseleave', e => {
            document.querySelector("#generate_button_perso").style.cursor = 'default';
        });
    } else {
        ErrorMessage("");
        document.querySelector("#generate_button_perso").addEventListener('mouseenter', e => {
            document.querySelector("#generate_button_perso").style.cursor = 'pointer';
        });
        document.querySelector("#generate_button_perso").addEventListener('mouseleave', e => {
            document.querySelector("#generate_button_perso").style.cursor = 'default';
        });
    }
    if (warning)
        WarningMessage(warning)
    else WarningMessage("");
    var listePorteLogique = [
        [document.querySelector("#logique1").checked, "et"],
        [document.querySelector("#logique2").checked, "ou"],
        [document.querySelector("#logique3").checked, "inv"],
        [document.querySelector("#logique4").checked, "etnon"],
        [document.querySelector("#logique5").checked, "nonou"]
    ];
    if (launch !== undefined && launch !== null && launch === true && error === null) {
        for (let i = 0; i < 200; i++) {
            tentative = i;
            if (generator(fork, col, listePorteLogique) === false)
                break;
        }
    }
}

function addGenForkInput() {
    var div = document.createElement("div");
    div.classList = "div_gen_col_fork";
    var span = document.createElement("span");
    span.innerHTML = "Ajouter un fork pour la colonne 1 qui se divise en 2";
    div.appendChild(span);
    var input = document.createElement("input");
    input.addEventListener('input', (event) => {
        calcul();
    });
    input.value = 1;
    input.setAttribute("type", "number");
    div.append(input);
    input = document.createElement("input");
    input.addEventListener('input', (event) => {
        calcul();
    });
    input.value = 2;
    input.setAttribute("type", "number");
    div.append(input);
    var i = document.createElement("i");
    i.className = "fa fa-trash";
    i.onclick = function () {
        this.parentElement.remove();
        calcul();
    }
    div.append(i);
    document.querySelector("#gen_fork_div").appendChild(div);
    calcul();
}

function tuto(niveau) {
    finish = false;
    isTutoriel = true;
    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;
    var firstTime = [];
    switch (niveauActuel) {
        case 1:
            firstTime.push("et");
            break;
        case 2:
            firstTime.push("inv");
            break;
        case 3:
            firstTime.push("ou");
            break;
        case 4:
            firstTime.push("etnon");
            break;
        case 5:
            document.querySelector("#niveauSuivantText").innerHTML = "Terminer le tutoriel";
            document.querySelector("#next_level_button").children[1].className = "fa fa fa-check niveauSuivantIcon";
            firstTime.push("nonou");
            break;
        default:
            finish = true;
            break;
    }
    if (!finish) {
        if (firstTime.length > 0) {
            if (allowedInfoPorte) {
                openModal('firstTime' + firstTime[0]);
                timer.pause();
            }
            generator([], [1], [[true, firstTime[0]]], "tuto");
            while (checkIfEnd()) {
                switchsInfoCopy.forEach(function (element) {
                    if (getRandomArbitrary(0, 2) === 1)
                        activeSwitch(element.id);
                    checkAllSortieLogique();
                });
            }

        }
    } else {

    }
}


function createGameOne(niveau) {
    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;
    var numberColonne1 = 2;
    var numberColonne2 = 1;
    var isEtNonAllowed = false;
    var isOuNonAllowed = false;
    var isNotAllowed = false;
    var isOuAllowed = false;
    double = false;
    var firstTime = [];
    switch (niveauActuel) {
        case 1:
            firstTime.push("et");
            break;
        case 2:
            numberColonne1 = 2;
            numberColonne2 = 0;
            timeEnd = 15;
            break;
        case 3:
            numberColonne1 = 2;
            numberColonne2 = 1;
            timeEnd = 15;
            break;
        case 4:
            numberColonne1 = 3;
            numberColonne2 = 1;
            timeEnd = 20;
            break;
        //Fin premiere serie
        case 5:
            firstTime.push("inv");
            isNotAllowed = true;
            timeEnd = 20;
            break;
        case 6:
            numberColonne1 = 2;
            numberColonne2 = 0;
            isNotAllowed = true;
            timeEnd = 20;
            break;
        case 7:
            numberColonne1 = 2;
            numberColonne2 = 1;
            isNotAllowed = true;
            timeEnd = 20;
            break;
        case 8:
            numberColonne1 = 3;
            numberColonne2 = 1;
            isNotAllowed = true;
            timeEnd = 20;
            break;
        case 9:
            numberColonne1 = 4;
            numberColonne2 = 2;
            isNotAllowed = true;
            double = true;
            timeEnd = 25;
            break;
        case 10:
            firstTime.push("ou");
            break;
        case 11:
            isNotAllowed = true;
            isOuAllowed = true;
            numberColonne1 = 3;
            numberColonne2 = 1;
            timeEnd = 20;
            break;
        case 12:
        case 13:
        case 14:
            isNotAllowed = true;
            isOuAllowed = true;
            numberColonne1 = 3;
            numberColonne2 = 1;
            timeEnd = 20;
            break;
        default:
            isEtNonAllowed = true;
            isOuNonAllowed = true;
            timeEnd = 20;
            numberColonne1 = 4;
            numberColonne2 = 4;
            break;
    }
    isTuto = false;
    createStage("play_container");
    stage.add(layer);
    colonneTot = 3;
    numberPerColonne = [numberColonne1, numberColonne2, 2];
    var logiqueCount = 0;

    if (firstTime.length > 0) {
        numberColonne1 = 1;
        numberColonne2 = 0;
        numberPerColonne = [numberColonne1, numberColonne2];
        liveColonneNumber.push([]);
        timeEnd = 20;
        insertLogiqueColonne("logique" + logiqueCount, firstTime[0], 0);
        if (allowedInfoPorte) {
            openModal('firstTime' + firstTime[0]);
            timer.pause();
        }
    } else {
        for (let i = 0; i < colonneTot; i++) {
            liveColonneNumber.push([]);
        }
        for (let i = 0; i < colonneTot; i++) {
            for (let j = 0; j < numberPerColonne[i]; j++) {
                logiqueCount++;
                let type = null;
                let x = 1;
                if (isOuAllowed) x++;
                if (isEtNonAllowed) x++;
                if (isOuNonAllowed) x++;
                if (isNotAllowed) x++;
                let numberRandom = getRandomArbitrary(0, x);
                switch (numberRandom) {
                    case 0:
                        type = "et";
                        break;
                    case 1:
                        type = "inv";
                        break;
                    case 2:
                        type = "ou";
                        break;
                    case 3:
                        type = "etnon";
                        break;
                    case 4:
                        type = "nonou";
                        break;
                }
                insertLogiqueColonne("logique" + logiqueCount, type, i);
            }
        }
    }

    logiques.forEach(function (element) {
        createLinkAuto(element.name);
    });
    initEndGame();
}


function generator(matchs, col, listePorteLogique, mode, time) {
    var regen = false;
    endHeight = 100;
    isTutoriel = false;
    isTuto = false;
    hideDiv(document.querySelector('#TestNouveauGenerateur'));
    showDiv(document.querySelector('#playPage'));
    resetAllTabs(false);
    createStage("play_container");
    stage.add(layer);
    if (time === undefined || time === null || time === -1)
        timeEnd = 999;
    else timeEnd = time;

    var groupes = [];
    var colCopy = [];
    var links = [];
    var orphelins = [];
    var logiquesTemp = [];
    for (let i = 0; i < col.length; i++) colCopy[i] = col[i];
    //liste porte logique
    if (listePorteLogique === null || listePorteLogique === undefined)
        arrayPorte = [
            [document.querySelector("#logique1").checked, "et"],
            [document.querySelector("#logique2").checked, "ou"],
            [document.querySelector("#logique3").checked, "inv"],
            [document.querySelector("#logique4").checked, "etnon"],
            [document.querySelector("#logique5").checked, "nonou"]
        ];
    else arrayPorte = listePorteLogique;
    arrayPorte = arrayPorte.filter(function (e) {
        if (e[0] === true) return e;
    });
    //Creation des logiques obj : 
    var logiqueCount = 1;
    for (let i = 0; i < col.length; i++) {
        for (let j = 0; j < col[i]; j++) {
            var newLogique = {
                id: "logique" + logiqueCount,
                col: i + 1,
                id1: null,
                id2: null,
                id3: null,
                type: null,
            };

            logiquesTemp.push(newLogique);
            logiqueCount++;
        }
    }

    for (let i = col.length; i > 0; i--) {
        var logiqueCol = [];
        logiquesTemp.forEach(function (logique) {
            if (logique.col === i) logiqueCol.push(logique);
        });
        //Création des liens
        if (logiqueCol.length !== 0) {
            matchs.forEach(function (element) {
                if (element[0] === i) {
                    //Selection de la sortie au hasard dans la colonne i
                    var index = getRandomArbitrary(0, logiqueCol.length);
                    var logiqueUse = logiqueCol[index];
                    //Création du rond du fork
                    circles.push(["circle" + circles.length, logiqueUse.id]);
                    logiqueCol.splice(index, 1);
                    //Selection du groupes
                    groupes.forEach(function (group, index) {
                        if (group.length === element[1]) {
                            group.forEach(function (logique) {
                                var signal = null;

                                logiquesTemp.forEach(function (log) {
                                    if (log.id === logique[0]) {
                                        if (logique[1] === "id1")
                                            signal = log.id1;
                                        else signal = log.id2;
                                    }
                                });
                                links.push([logiqueUse.id, logique[0], logique[1], signal]);
                            });
                            groupes.splice(index, 1);
                        }
                    });
                }
            });
        }

        //Attribution des links aux orphelins :
        var free = [], usedLogique = [];
        logiquesTemp.forEach(function (logique) {
            isLogiqueFree = [];
            if (logique.col === i + 1) {
                //Si c'est un non
                if (logique.type === "inv") {
                    var isOk = true;
                    links.forEach(function (link) {
                        if (link[1] === logique.id)
                            isOk = false;
                    });
                    usedLogique.forEach(function (uLogique) {
                        if (uLogique[0] === logique.id) isOk = false;
                    });
                    if (isOk)
                        isLogiqueFree.push("id1");
                } else {
                    var isId1 = true;
                    var isId2 = true;
                    links.forEach(function (link) {
                        if (link[1] === logique.id) {
                            if (link[2] === "id1") isId1 = false;
                            else isId2 = false;
                        }
                    });
                    //Already use in this column
                    usedLogique.forEach(function (uLogique) {
                        if (uLogique[0] === logique.id) {
                            if (uLogique[1] === "id1") isId1 = false;
                            else isId2 = false;
                        }
                    });

                    if (isId1) isLogiqueFree.push("id1");
                    if (isId2) isLogiqueFree.push("id2");
                }
            }
            isLogiqueFree.forEach(function (id) {
                if (id === "id1")
                    free.push([logique.id, id, logique.id1]);
                else
                    free.push([logique.id, id, logique.id2]);
            });
        });
        logiqueCol.forEach(function (logique) {
            //Check si il reste des portes à droite :
            if (free.length > 0) {
                isDone = false;
                free.forEach(function (fr, index) {
                    if (!isDone) {
                        var signal = null;
                        logiquesTemp.forEach(function (logique) {
                            if (logique.id === fr[0]) {
                                if (fr[1] === "id1") signal = logique.id1;
                                else signal = logique.id2;
                            }
                        });
                        links.push([logique.id, fr[0], fr[1], signal]);
                        free.splice(index, 1);
                        isDone = true;
                    }
                });
            } else {
                links.push([logique.id, "end", null, 1]);
            }
        });

        //calcul de id3 :
        logiquesTemp.forEach(function (logique) {
            if (logique.col === i) {
                if (i === col.length) {
                    logique.id3 = 1;
                } else {
                    //Attribution du signal id3
                    var isNull = null;
                    //console.log("Colonne : " + i + " ---------------------")
                    links.forEach(function (link) {
                        if (isNull === null) {
                            if (link[0] === logique.id) {
                                logique.id3 = link[3];
                                isNull = 1;
                            }
                        }
                    });
                    if (isNull === null) logique.id3 = 1;
                }
            }
        });

        //Calcul du signal souhaité à chaque porte de la colonne i
        var logiqueTemp2 = [];
        for (let k = 0; k < logiquesTemp.length; k++) logiqueTemp2[k] = logiquesTemp[k];
        logiquesTemp.forEach(function (logique) {
            if (logique.col === i) {
                //Type au hasard :
                logique.type = arrayPorte[getRandomArbitrary(0, arrayPorte.length)][1];
                //Attribution du signal :
                //Si dernière colonne
                if (i === col.length) {
                    //Opération pour les entrée :
                    switch (logique.type) {
                        case "et":
                            logique.id1 = 1;
                            logique.id2 = 1;
                            break;
                        case "ou":
                            switch (getRandomArbitrary(0, 3)) {
                                case 0:
                                    logique.id1 = 1;
                                    logique.id2 = 1;
                                    break;
                                case 1:
                                    logique.id1 = 0;
                                    logique.id2 = 1;
                                    break;
                                case 2:
                                    logique.id1 = 1;
                                    logique.id2 = 0;
                                    break;
                            }
                            break;
                        case "inv":
                            logique.id1 = 0;
                            break;
                        case "nonou":
                            logique.id1 = 0;
                            logique.id2 = 0;
                            break;
                        case "etnon":
                            switch (getRandomArbitrary(0, 3)) {
                                case 0:
                                    logique.id1 = 0;
                                    logique.id2 = 0;
                                    break;
                                case 1:
                                    logique.id1 = 0;
                                    logique.id2 = 1;
                                    break;
                                case 2:
                                    logique.id1 = 1;
                                    logique.id2 = 0;
                                    break;
                            }
                            break;
                    }
                } else {
                    //Calcul valeur d'entrée
                    if (logique.id3 === 1) {
                        switch (logique.type) {
                            case "et":
                                logique.id1 = 1;
                                logique.id2 = 1;
                                break;
                            case "ou":
                                switch (getRandomArbitrary(0, 3)) {
                                    case 0:
                                        logique.id1 = 1;
                                        logique.id2 = 1;
                                        break;
                                    case 1:
                                        logique.id1 = 0;
                                        logique.id2 = 1;
                                        break;
                                    case 2:
                                        logique.id1 = 1;
                                        logique.id2 = 0;
                                        break;
                                }
                                break;
                            case "inv":
                                logique.id1 = 0;
                                break;
                            case "nonou":
                                logique.id1 = 0;
                                logique.id2 = 0;
                                break;
                            case "etnon":
                                switch (getRandomArbitrary(0, 3)) {
                                    case 0:
                                        logique.id1 = 0;
                                        logique.id2 = 0;
                                        break;
                                    case 1:
                                        logique.id1 = 0;
                                        logique.id2 = 1;
                                        break;
                                    case 2:
                                        logique.id1 = 1;
                                        logique.id2 = 0;
                                        break;
                                }
                                break;
                        }
                    } else {
                        switch (logique.type) {
                            case "et":
                                switch (getRandomArbitrary(0, 3)) {
                                    case 0:
                                        logique.id1 = 0;
                                        logique.id2 = 0;
                                        break;
                                    case 1:
                                        logique.id1 = 0;
                                        logique.id2 = 1;
                                        break;
                                    case 2:
                                        logique.id1 = 1;
                                        logique.id2 = 0;
                                        break;
                                }
                                break;
                            case "ou":
                                logique.id1 = 0;
                                logique.id2 = 0;
                                break;
                            case "inv":
                                logique.id1 = 1;
                                break;
                            case "nonou":
                                switch (getRandomArbitrary(0, 3)) {
                                    case 0:
                                        logique.id1 = 1;
                                        logique.id2 = 1;
                                        break;
                                    case 1:
                                        logique.id1 = 0;
                                        logique.id2 = 1;
                                        break;
                                    case 2:
                                        logique.id1 = 1;
                                        logique.id2 = 0;
                                        break;
                                }
                                break;
                            case "etnon":
                                logique.id1 = 1;
                                logique.id2 = 1;
                                break;
                        }
                    }

                }
            }
        });
        //Check si y a assez de portes :

        var usedLogique = [];
        matchs.forEach(function (element) {
            if (element[0] === i - 1) {
                //Création d'un nouveau groupe :
                var newGroupe = [];
                //Calcul des logiques libres 
                var free = [];
                logiquesTemp.forEach(function (logique) {
                    isLogiqueFree = [];
                    if (logique.col === i) {
                        //Si c'est un non
                        if (logique.type === "inv") {
                            var isOk = true;
                            links.forEach(function (link) {
                                if (link[1] === logique.id)
                                    isOk = false;
                            });
                            usedLogique.forEach(function (uLogique) {
                                if (uLogique[0] === logique.id) isOk = false;
                            });
                            if (isOk) {
                                isLogiqueFree.push("id1");
                            }

                        } else {
                            var isId1 = true;
                            var isId2 = true;
                            links.forEach(function (link) {
                                if (link[1] === logique.id) {
                                    if (link[2] === "id1") isId1 = false;
                                    else isId2 = false;
                                }
                            });
                            //Already use in this column
                            usedLogique.forEach(function (uLogique) {
                                if (uLogique[0] === logique.id) {
                                    if (uLogique[1] === "id1") isId1 = false;
                                    else isId2 = false;
                                }
                            });

                            if (isId1) {
                                isLogiqueFree.push("id1");
                            }
                            if (isId2) {
                                isLogiqueFree.push("id2");
                            }
                        }
                    }
                    isLogiqueFree.forEach(function (id) {
                        if (id === "id1")
                            free.push([logique.id, id, logique.id1]);
                        else
                            free.push([logique.id, id, logique.id2]);
                    });
                });
                //On a tableau des portes free, maintenant on doit choisir :
                //On compte les nombres de portes logiques :
                var number1 = 0, number0 = 0;
                var count = 0;
                //Compte des 0 :
                var alreadyUse = [];
                free.forEach(function (fr) {
                    if (fr[2] === 0) {
                        var isAllowed = true;
                        alreadyUse.forEach(function (logique) {
                            if (logique === fr[0]) isAllowed = false;
                        });
                        if (isAllowed) {
                            number0++;
                            alreadyUse.push(fr[0]);
                        }
                    }
                });
                //Compte des 1 :
                var alreadyUse = [];
                free.forEach(function (fr) {
                    if (fr[2] === 1) {
                        var isAllowed = true;
                        alreadyUse.forEach(function (logique) {
                            if (logique === fr[0]) isAllowed = false;
                        });
                        if (isAllowed) {
                            number1++;
                            alreadyUse.push(fr[0]);
                        }
                    }
                });
                //Selection entre les 0 ou les 1:
                //On selectionne les 1
                if (number1 >= element[1]) {
                    //Selection des portes :
                    free.forEach(function (fr) {
                        if (count < element[1]) {
                            if (fr[2] === 1) {
                                var isAllowed = true;
                                newGroupe.forEach(function (logique) {
                                    if (logique[0] === fr[0]) isAllowed = false;
                                });
                                if (isAllowed) {
                                    newGroupe.push([fr[0], fr[1]]);
                                    usedLogique.push([fr[0], fr[1]]);
                                    count++;
                                }
                            }
                        }
                    });
                }
                //On selectionne les 0
                else if (number0 >= element[1]) {
                    free.forEach(function (fr) {
                        if (count < element[1]) {
                            if (fr[2] === 0) {
                                var isAllowed = true;
                                newGroupe.forEach(function (logique) {
                                    if (logique[0] === fr[0]) isAllowed = false;
                                });
                                if (isAllowed) {
                                    newGroupe.push([fr[0], fr[1]]);
                                    usedLogique.push([fr[0], fr[1]]);
                                    count++;
                                }
                            }
                        }
                    });
                }
                //Problème retour en arrière : 
                else {
                    regen = true;
                    /*console.log("gros problème");
                    console.log("0 : " + number0);
                    console.log("1 : " + number1);
                    console.log("colonne : " + i);
                    console.log("Demandé : " + element[1] + " colonne : " + element[0]);
                    logiquesTemp.forEach(function (logique) {
                        if (logique.col = col.length) {

                        }
                        if (logique.col === i)
                            console.log(logique);
                    });*/
                    /*
                    //On prend le plus grand :
                    //1
                    if (number1 >= number0) {
                        //check si il y a des logiques complétements vide
                        var free0 = [];
                        var isFullEmpty = [];
                        free.forEach(function (fr) {
                            if (fr[2] === 0)
                                free0.push(fr);
                        });
                        free.forEach(function (fr) {
                            free0.forEach(function (fr0) {
                                if (fr[0] === fr0[0] && fr[2] !== 0)
                                    isFullEmpty.push(fr[0])
                            })
                        });
                        //Changement de type du complétement vide
                        isFullEmpty.forEach(function (logiqueId) {
                            logiquesTemp.forEach(function (logique) {
                                if (logique.id === logiqueId) {
                                    if (logique.id3 === 1) {
                                        switch (logique.type) {
                                            case "et":
                                                type.id1 = 1;
                                                type.id2 = 1;
                                                break;
                                            case "ou":
                                                type.id1 = 1;
                                                type.id2 = 1;
                                                break;
                                        }
                                    }
                                }
                                console.log(logique.id + " : " + logique.type)
                            });
                        });
                    }
                    //0 
                    else {

                    }*/

                }
                groupes.push(newGroupe);
            }
        });
    }
    if (!regen) {
        //Génération de la vue
        initTimer();
        colonneTot = col.length;
        tempMatchs = [];
        tempFork = [];
        for (let i = 0; i < matchs.length; i++)
            tempMatchs[i] = matchs[i];
        for (let i = 0; i < matchs.length; i++)
            tempFork[i] = matchs[i - 1];
        tempCol = col;

        colonneTot = col.length;
        for (let i = 0; i < colonneTot; i++) {
            var pos = 0;
            logiquesTemp.forEach(function (logique) {
                if (logique.col - 1 === i) {
                    createLogique(stage.width() / (colonneTot + 1) * (i + 1), (stage.height() / col[i] / 2 - imageHeight) + (stage.height() / 1.5 / col[i] * pos), logique.id, logique.type)
                    pos++;
                }
            });
        }
        links.forEach(function (link) {
            if (link[1] !== "end")
                createLink(findLogique(link[0]), findLogique(link[1]), link[2]);
        });
        //On place les rond si fork :
        //On check la valeur entre 2 colonne :
        var d1 = 0, tot = 0;
        logiques.forEach(function (logique) {
            if (d1 === 0) d1 = logique.x;
            else if (d1 !== logique.x && tot === 0) {
                tot = logique.x - d1;
            }
        });
        circles.forEach(function (cir) {
            logiques.forEach(function (logique) {

                if (logique.name === cir[1]) {
                    var circle = new Konva.Circle({
                        id: cir[0],
                        x: logique.x + imageWidth + (tot / 100 * pourcentageBreak),
                        y: logique.y + imageHeight / 2,
                        radius: 10,
                        fill: 'black',
                        stroke: 'black',
                        strokeWidth: 4,
                    });
                    layer.add(circle);
                }
            })
        });
        //On init la fin
        initEndGame(mode);

        //On change les lignes de places :

        logiques.forEach(function (logique) {
            if (logique.type !== "inv") {
                var distance1;
                var distance2;
                if (getLogiqueFromLine(logique.id1) === null)
                    distance1 = getSwitchFromLine(logique.id1).y;
                else distance1 = getLogiqueFromLine(logique.id1).y;
                if (getLogiqueFromLine(logique.id2) === null)
                    distance2 = getSwitchFromLine(logique.id2).y;
                else distance2 = getLogiqueFromLine(logique.id2).y;

                if (distance2 < distance1) {

                    if (getLogiqueFromLine(logique.id1) === null && getLogiqueFromLine(logique.id2) === null) {
                        let switch1Id = getSwitchFromLine(logique.id1).id;
                        let switch2Id = getSwitchFromLine(logique.id2).id;
                        removeLine(logique.id1);
                        removeLine(logique.id2);
                        logique.id1 = null;
                        logique.id2 = null;
                        createLink(stage.findOne("#" + switch1Id), logique);
                        createLink(stage.findOne("#" + switch2Id), logique);
                    }
                }



            }
        });


    }
    return regen;

}


function generate2(col, matchs, fork, portes) {
    isTutoriel = false;
    isTuto = false;
    hideDiv(document.querySelector('#TestNouveauGenerateur'));
    showDiv(document.querySelector('#playPage'));
    resetAllTabs(false);
    if (portes === null || portes === undefined)
        arrayPorte = [
            [document.querySelector("#logique1").checked, "et"],
            [document.querySelector("#logique2").checked, "ou"],
            [document.querySelector("#logique3").checked, "inv"],
            [document.querySelector("#logique4").checked, "etnon"],
            [document.querySelector("#logique5").checked, "nonou"]
        ];
    else arrayPorte = portes;



    arrayPorte = arrayPorte.filter(function (e) {
        if (e[0] === true) return e;
    })

    var numberCol = col.length;
    var numberPerCol = [];
    numberPerColonne = [];
    tempMatchs = [];
    tempFork = [];
    for (let i = 0; i < col.length; i++) {
        numberPerCol[i] = col[i];
        numberPerColonne[i] = col[i];
    }
    for (let i = 0; i < matchs.length; i++)
        tempMatchs[i] = matchs[i];
    for (let i = 0; i < fork.length; i++)
        tempFork[i] = fork[i];
    tempPortes = portes;
    tempCol = numberPerColonne;

    colonneTot = col.length;
    var compt = new Array();
    var listeSame = [];
    let num = 1;

    //attribution
    for (let i = numberCol; i > 0; i--) {
        matchs.forEach(function (element) {
            if (element[0] == i) {
                for (let j = 0; j < element[1]; j++) {
                    compt.push([i, "same" + num]);
                    numberPerCol[i - 1]--;
                    listeSame.push(["same" + num, null]);
                }
                num++;
            }
        });
        for (let j = 0; j < numberPerCol[i - 1]; j++)
            compt.push([i, "normal"]);
    }

    //attribution groupe
    var listeLogiqueObj = new Array();
    let i = 0;
    let colTemp = col;
    compt.forEach(function (element) {
        if (colTemp[element[0] - 1] !== 0) {
            var newLogiqueObj = {
                id: "logique" + i,
                col: element[0],
                id1: null,
                id2: null,
                id3: null,
                matchId1: null,
                matchId2: null,
                type: null,
            }
            if (element[1] === "normal") {
                newLogiqueObj.matchId1 = null;
            } else {
                newLogiqueObj.matchId1 = element[1];
            }
            listeLogiqueObj.push(newLogiqueObj);
            colTemp[element[0] - 1]--;
        } else {
            var allowed = [];
            listeLogiqueObj.forEach(function (logique) {
                if (logique.col === element[0] && logique.matchId1 !== element[1])
                    allowed.push(logique);
            });
            allowed[getRandomArbitrary(0, allowed.length)].matchId2 = element[1];
        }
        i++;
    });

    //Attribution des types
    //num = liste de comptatibilité

    let num2 = getRandomArbitrary(0, arrayPorte.length);
    for (x in listeLogiqueObj) {
        if (listeLogiqueObj[x].matchId1 !== null) {
            if (getElementArray(listeLogiqueObj[x].matchId1, listeSame)[1] === null) {
                getElementArray(listeLogiqueObj[x].matchId1, listeSame)[1] = arrayPorte[num2][1];
                if (listeLogiqueObj[x].matchId2 !== null && getElementArray(listeLogiqueObj[x].matchId2, listeSame)[1] === null) {
                    getElementArray(listeLogiqueObj[x].matchId2, listeSame)[1] = arrayPorte[num2][1];
                }
                num2 = getRandomArbitrary(0, arrayPorte.length);
            } else {
                listeSame[x] = getElementArray(listeLogiqueObj[x].matchId1, listeSame);
            }
        }
    }

    createStage("play_container");
    stage.add(layer);
    timeEnd = 999;

    for (let i = 0; i < colonneTot; i++) {
        liveColonneNumber.push([]);
    }
    var col = [];
    listeLogiqueObj.forEach(function (logique) {
        if (col[logique.col - 1] === null || col[logique.col - 1] === undefined || col[logique.col - 1] === 0)
            col[logique.col - 1] = 1;
        else col[logique.col - 1]++;
    });
    numberPerColonne = col;
    initTimer();
    //creation logique
    listeLogiqueObj.forEach(function (logique) {
        if (getTypeFromSameMatch(listeSame, logique.matchId1) === null) logique.type = arrayPorte[getRandomArbitrary(0, arrayPorte.length)][1];
        else logique.type = getTypeFromSameMatch(listeSame, logique.matchId1);
        insertLogiqueColonne(logique.id, logique.type, logique.col - 1);
    });

    var logiquesGen;
    //creation de liens entre les portes logiques :
    for (let col = 1; col < colonneTot; col++) {
        //recuperer tout les logiques : 
        logiquesGen = new Array();
        listeLogiqueObj.forEach(function (logique) {
            if (logique.col === col && logique.id3 === null) logiquesGen.push(logique);
        });
        //check si y a des fork
        while (getNumberFork(fork, col) > 0) {
            fork.forEach(function (element) {
                if (element[0] === col) {
                    //selection de la sortie a forker :
                    let logiqueFork = logiquesGen[getRandomArbitrary(0, logiquesGen.length)];
                    //recupération des logiques d'entree :
                    let logiqueEntre = new Array();
                    let sameId = null;
                    listeLogiqueObj.forEach(function (logique) {
                        if (logique.col === col + 1) {
                            if (sameId === null) {
                                sameId = logique.matchId1;
                                logiqueEntre.push(logique);
                            } else if (sameId === logique.matchId1)
                                logiqueEntre.push(logique);
                        }
                    });
                    logiqueFork.id3 = "done";
                    var loEntre = null;
                    //creation du lien avec fork :
                    for (let i = 0; i < logiqueEntre.length; i++) {
                        createLink(findLogique(logiqueFork.id), findLogique(logiqueEntre[i].id));
                        loEntre = findLogique(logiqueEntre[i].id);
                    }
                    logiques.forEach(function (logique) {
                        if (logique.name === logiqueFork.id) createCircle(logique.x + imageWidth + ((loEntre.x - findLogique(logiqueFork.id).x) / 100 * pourcentageBreak), findLogique(logiqueFork.id).y + imageHeight / 2, logique.id3);
                    });
                    fork.splice(fork.indexOf(element), 1);
                }
            });
        }

    }
    //creation des autres liens :
    //recupération des logiques restants :
    for (x in listeLogiqueObj) {
        if (listeLogiqueObj[x].id3 === null && listeLogiqueObj[x].col !== colonneTot) {
            //liste des logiques possible :
            let logiquesGen = new Array();
            listeLogiqueObj.forEach(function (logique) {
                if (logique.col === listeLogiqueObj[x].col + 1) {
                    if (logique.type === 2 && checkLogiqueLines(logique.id, "id1") === false) {
                        logiquesGen.push(logique);
                    } else if (logique.type !== 2) {
                        if (checkLogiqueLines(logique.id, "id1") === false || checkLogiqueLines(logique.id, "id2") === false) {
                            logiquesGen.push(logique);
                        }
                    }
                }
            });
            //attribution du logique le plus proche :
            let logiqueFinal = null;
            logiquesGen.forEach(function (logique) {
                if (logiqueFinal === null) {
                    logiqueFinal = logique;
                } else if (Math.abs(findLogique(listeLogiqueObj[x].id).y - findLogique(logique.id).y) < Math.abs(findLogique(listeLogiqueObj[x].id).y - findLogique(logiqueFinal.id).y)) {
                    logiqueFinal = logique;
                }
            });
            createLink(findLogique(listeLogiqueObj[x].id), findLogique(logiqueFinal.id));
        }
    }
    initEndGame();
    perfectClick = 0;
    var endStateTab = [], v = 0;
    logiques.forEach(function (logique) {
        logique.id3.forEach(function (element) {
            if (getLogiqueFromLineEnter(element) === null || getLogiqueFromLineEnter(element) == undefined) {
                console.log(element);
            }
        });
    });
    endLines.forEach(function (line) {
        endStateTab[v] = ["line" + line, getLineState("line" + line)];
        v++;
    });
    endStateTab.forEach(function (element) {
        if (element[1] === false) {

            switch (getLogiqueFromLine(element[0]).type) {
                case "inv":
                    //il faut les 2 allumé
                    /* console.log(getLineState(getLogiqueFromLine(element[0]).id1));
                     console.log(getLineState(getLogiqueFromLine(element[0]).id2));
                     console.log(getLogiqueFromLine(element[0]).id1);*/
                    setLineTrue(getLogiqueFromLine(element[0]).id1);
                    break;
                default:
                    setLineTrue(getLogiqueFromLine(element[0]).id1);
                    setLineTrue(getLogiqueFromLine(element[0]).id2);
                    break;
            }
        }
    });
    changePorte.forEach(function (element) {
        activeSwitch(element);
        checkAllSortieLogique();
        stage.draw();
    });
    checkAllSortieLogique();
    console.log(perfectClick);

}

function setLineTrue(line) {
    var isSwitch = false;
    switchsInfoCopy.forEach(function (element) {
        element.id3.forEach(function (id3) {
            if (id3 === line) {
                if (getLineState(id3) === false) {
                    perfectClick++;
                    activeSwitch(element.id);
                    stage.draw();
                    changePorte.push(element.id);
                    isSwitch = true;
                }
            }
        })
    });
    if (!isSwitch && getLogiqueFromLine(line) != null) {
        switch (getLogiqueFromLine(line).type) {
            case "et":
                if (getLineState(getLogiqueFromLine(line).id1) === false)
                    setLineTrue(getLogiqueFromLine(line).id1);
                if (getLineState(getLogiqueFromLine(line).id2) === false)
                    setLineTrue(getLogiqueFromLine(line).id2);
                break;
            case "ou":
                if (getLineState(getLogiqueFromLine(line).id1) === false && getLineState(getLogiqueFromLine(line).id2) === false)
                    setLineTrue(getLogiqueFromLine(line).id1);
                break;
            case "inv":
                setLineTrue(getLogiqueFromLine(line).id1);
                break;
        }

    }
    checkAllSortieLogique();
    //setLineTrue(getLogiqueFromLine(line).id1);

}

function getNumberFork(arr, col) {
    let num = 0;
    arr.forEach(function (item) {
        if (item[0] === col) num++;
    });
    return num;
}

function getElementArray(one, array) {
    retour = null;
    array.forEach(function (element) {
        if ((element[0] === one && retour === null)) {
            retour = element;
        }
    });
    return retour;
}

function getTypeFromSameMatch(listeMatch, sameId) {
    retour = null;
    listeMatch.forEach(function (element) {
        if (element[0] === sameId)
            retour = element[1];
    });
    return retour;
}


//a l'epoque
function generateFromBottom() {
    var NombrecolonneTest = 2;
    var numberPerColonneTest = [3, 2];
    var porteBool = [
        [true, "et"],
        [true, "ou"],
        [true, "inv"]
    ];
    var logiquesTest = [];

    for (let i = NombrecolonneTest; i > 0; i--) {
        for (let j = 0; j < numberPerColonneTest[i - 1]; j++) {
            let numberRandom = getRandomArbitrary(0, porteBool.length);
            logiquesTest.push([porteBool[numberRandom][1], i, j, (j + 1) * 10]);

        }
    }
    createLink(logiquesTest, numberPerColonneTest[numberPerColonneTest.length - 1]);
}

function createLinkTest(listeLogique, colonneMax) {
    listeLogique.forEach(function (element) {
        if (element[1] !== colonneMax) {
            console.log(element);
            listeLogique.forEach(function (item) {
                if (item[1] !== colonneMax) {
                    console.log(item);
                }
            });
        }
    });
}

function isValid(listeLogique, colonneMax) {
    listeLogique.forEach(function (element) {
        //derniere colonne donc fin
        if (element[1] == colonneMax) {
            console.log(element);
        }
    });
}