using CoreLibrary.Exceptions;
using CoreLibrary.Evenements;
using System.Runtime.Serialization;
using System.Security.Cryptography;
namespace CoreLibrary.Core
{
///
/// Classe représentant le plateau de jeu contenant les codes et les indicateurs.
///
[DataContract]
public class Plateau
{
///
/// Événement déclenché lorsqu'un code est ajouté au plateau.
///
public event EventHandler? PlateauAjouterCode;
private void QuandPlateauAjouterCode() => PlateauAjouterCode?.Invoke(this, new PlateauAjouterCodeEventArgs(this));
///
/// Le code secret à deviner.
///
[DataMember]
private readonly Code codeSecret;
///
/// Liste des codes ajoutés au plateau.
///
[DataMember]
private readonly List codes = new List();
///
/// Liste des listes d'indicateurs pour chaque code ajouté.
///
[DataMember]
private readonly List> indicateurs = new List>();
///
/// Obtient le nombre de codes sur le plateau.
///
public int Taille => codes.Count;
///
/// Obtient la taille maximale de codes autorisée sur le plateau.
///
[DataMember]
public int TailleMax { get; private init; }
///
/// Obtient la taille maximale d'un code.
///
[DataMember]
public int TailleMaxCode { get; private init; }
///
/// Indique si le plateau à atteint sa taille maximale.
///
public bool Complet => Taille == TailleMax;
///
/// Indique si la victoire est atteinte.
///
[DataMember]
public bool Victoire { get; private set; } = false;
///
/// Obtient la grille des codes et des indicateurs.
///
public (IEnumerable>, IEnumerable>) Grille => (
codes.Select(code => code.Jetons),
indicateurs
);
///
/// Constructeur de plateau avec une taille de code et une taille de plateau spécifiées.
///
/// La taille maximale d'un code.
/// La taille maximale du plateau.
/// Lancée si la taille du code est négative ou nulle.
/// Lancée si la taille du plateau spécifiée est négative ou nulle.
public Plateau(int tailleCode, int taillePlateau)
{
if (tailleCode < 0)
throw new TailleCodeException(tailleCode);
if (taillePlateau < 0)
throw new TailleGrilleException(taillePlateau);
TailleMax = taillePlateau;
TailleMaxCode = tailleCode;
codeSecret = GenererCodeSecret();
}
///
/// Génère un code secret aléatoire.
///
/// Renvoie le code secret généré.
private Code GenererCodeSecret()
{
Code code = new Code(TailleMaxCode);
Couleur[] couleurs = Enum.GetValues();
while (!code.Complet)
{
code.AjouterJeton(
new Jeton(couleurs[RandomNumberGenerator.GetInt32(0, couleurs.Length)])
);
}
return code;
}
///
/// Ajoute un code au plateau et compare avec le code secret.
///
/// Le code à ajouter.
/// Lancée si le code à ajouter n'est pas complet.
/// Lancée si le plateau est déjà complet.
public void AjouterCode(Code code)
{
if (!code.Complet)
throw new CodeIncompletException();
if (Complet)
throw new GrilleCompleteException();
codes.Add(code);
IReadOnlyList indicateursCode = codeSecret.Comparer(code);
indicateurs.Add(indicateursCode.ToList());
if (!Victoire && indicateursCode.Count(indicateur => indicateur == Indicateur.BonnePlace) == TailleMaxCode)
Victoire = true;
QuandPlateauAjouterCode();
}
}
}