#! /usr/bin/python3
# vim: set fileencoding=utf-8 :
#
# --
# Copyright (C) (2024) (Mathieu Bergeron) (mathieu.bergeron@cmontmorency.qc.ca)
# --
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU AFFERO General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
# or see http://www.gnu.org/licenses/agpl.txt.
# --

import argparse
import random

parser = argparse.ArgumentParser(description='Simulation de Monty Hall')
parser.add_argument('-i', metavar='ITERATIONS', default='10000', nargs='?', type=int, help="Nombre d'itérations (10000 par défaut)")
parser.add_argument('-p', metavar='NOMBRE_DE_PORTES', default='3', nargs='?', type=int, help="Nombre de portes (3 par défaut)")

args = parser.parse_args()

ITERATIONS = args.i
NOMBRE_DE_PORTES = args.p

if not (NOMBRE_DE_PORTES >= 3):
    print()
    parser.print_usage()
    print()
    print()
    print("-p NOMBRE_DE_PORTES doit être >= 3")
    print()
    exit(0)

if not (ITERATIONS >= 1):
    print()
    parser.print_usage()
    print()
    print()
    print("-i ITERATIONS doit être >= 1")
    print()
    exit(0)


def indice_au_hasard(liste):
    return random.randint(0, len(liste) -1)

def choix_initial(portes):
    return indice_au_hasard(portes)

def eliminer_une_porte(portes, indice_choix_initial):
    indice_a_eliminer = indice_au_hasard(portes)

    while indice_a_eliminer == indice_choix_initial or portes[indice_a_eliminer] == True:
        indice_a_eliminer = indice_au_hasard(portes)

    portes[indice_a_eliminer] = None

    return portes

def choix_final(portes, indice_choix_initial):
    if random.randint(0,1) == 0:

        return choix_final_si_reste(indice_choix_initial)

    else:

        return choix_final_si_change(portes, indice_choix_initial)

def choix_final_si_reste(indice_choix_initial):
    return indice_choix_initial

def choix_final_si_change(portes, indice_choix_initial):
    indice_choix_final = indice_au_hasard(portes)

    while indice_choix_final == indice_choix_initial or portes[indice_choix_final] == None:
        indice_choix_final = indice_au_hasard(portes)

    return indice_choix_final

def creer_portes(nombre_de_portes):
    portes = [False] * nombre_de_portes
    indice_du_prix = indice_au_hasard(portes)

    portes[indice_du_prix] = True

    return portes

def creer_cas(resultats, nom_cas):
    resultats[nom_cas] = {'reussites':0,'echecs':0,'total':0,'taux_succes':0}

def ajouter_reussite(cas):
    cas['reussites'] = cas['reussites'] + 1

def ajouter_echec(cas):
    cas['echecs'] = cas['echecs'] + 1

def finaliser_cas(cas):
    cas['total'] = cas['reussites'] + cas['echecs']

    if cas['total'] > 0:
        cas['taux_succes'] = cas['reussites'] / cas['total']

def afficher_cas(cas, nom_cas):
    print(f"{nom_cas}")
    print(f"\tnombre essais: {cas['total']}")
    print(f"\tnombre réussites: {cas['reussites']}")
    print(f"\tnombre échecs: {cas['echecs']}")
    print("\ttaux de succès: {0:.2f}%".format(cas['taux_succes'] * 100))


if __name__ == '__main__':

    resultats = {}
    creer_cas(resultats, 'reste')
    creer_cas(resultats, 'change')

    print(f"nombre d'itération: {ITERATIONS}")
    print()
    print()

    for i in range(ITERATIONS):
        print(f"itération {i}")

        portes = creer_portes(NOMBRE_DE_PORTES)

        print(f"portes: {portes}")

        indice_choix_initial = choix_initial(portes)

        print(f"choix initial: {indice_choix_initial}")

        portes = eliminer_une_porte(portes, indice_choix_initial)

        print(f"après porte éliminée: {portes}")

        indice_choix_final = choix_final(portes, indice_choix_initial)

        print(f"choix final: {indice_choix_final}")

        si_change = indice_choix_initial != indice_choix_final
        si_reussite = portes[indice_choix_final] == True

        if si_change and si_reussite:
            print("CHANGE: réussite")
            ajouter_reussite(resultats['change'])

        elif si_change and not si_reussite:
            print("CHANGE: échec")
            ajouter_echec(resultats['change'])

        elif not si_change and si_reussite:
            print("RESTE: réussite")
            ajouter_reussite(resultats['reste'])

        elif not si_change and not si_reussite:
            print("RESTE: échec")
            ajouter_echec(resultats['reste'])

        print()

    print()

    finaliser_cas(resultats['change'])
    finaliser_cas(resultats['reste'])
    
    print()
    afficher_cas(resultats['reste'], 'stratégie RESTE')

    print()
    afficher_cas(resultats['change'], 'stratégie CHANGE')

    print()





