using CoreLibrary.Exceptions;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
namespace CoreLibrary.Core
{
///
/// Classe représentant un code composé de jetons et ses différentes méthodes.
///
[DataContract]
public class Code
{
///
/// Collection observable de jetons.
///
[DataMember]
public ObservableCollection Jetons { get; private init; } = new ObservableCollection();
///
/// Obtient le nombre actuel de jetons dans le code.
///
public int Taille => Jetons.Count;
///
/// Taille maximale de jetons autorisée pour le code.
///
[DataMember]
public int TailleMax { get; private init; }
///
/// Indique si le code est complet.
///
public bool Complet => Taille == TailleMax;
///
/// Indique si le code est vide.
///
public bool Vide => Taille == 0;
///
/// Constructeur de code avec une taille maximale spécifiée.
///
/// La taille maximale de jetons autorisée pour le code.
/// Exception lancée si la taille spécifiée est négative ou nulle.
public Code(int taille)
{
if (taille < 0)
throw new TailleCodeException(taille);
TailleMax = taille;
}
///
/// Ajoute un jeton au code.
///
/// Le jeton à ajouter.
/// Lancée si le code est déjà complet.
public void AjouterJeton(Jeton jeton)
{
if (Complet)
throw new CodeCompletException();
Jetons.Add(jeton);
}
///
/// Récupère le jeton à l'indice spécifié.
///
/// L'indice du jeton à récupérer.
/// Renvoie le jeton à l'indice spécifié.
/// Lancée si l'indice est en dehors des limites de la collection de jetons.
public Jeton RecupererJeton(int indice)
{
if (indice < 0 || indice >= Taille)
throw new IndiceCodeException(indice, Taille - 1);
return Jetons.ElementAt(indice);
}
///
/// Supprime le dernier jeton du code.
///
/// Lancée si le code est vide.
public void SupprimerDernierJeton()
{
if (Vide)
throw new CodeVideException();
Jetons.RemoveAt(Taille - 1);
}
///
/// Compare le code avec le code secret et retourne une liste d'indicateurs.
///
/// Le code à comparer.
/// Renvoie une liste d'indicateurs représentant les résultats de la comparaison.
/// Lancée si le code n'est pas complet.
/// Lancée si le code est invalide.
public IReadOnlyList Comparer(Code code)
{
// Je suis le bon code
List indicateurs = new List();
if (!code.Complet)
throw new CodeIncompletException();
if (code.TailleMax != TailleMax)
throw new CodeInvalideException();
List mesJetons = Jetons.Select(jeton => (Jeton?)jeton).ToList();
List sesJetons = code.Jetons.Select(jeton => (Jeton?)jeton).ToList();
for (int i = 0; i < mesJetons.Count; ++i)
{
if (mesJetons[i] == sesJetons[i])
{
mesJetons[i] = null;
sesJetons[i] = null;
indicateurs.Add(Indicateur.BonnePlace);
}
}
for (int i = 0; i < sesJetons.Count; ++i)
{
if (sesJetons[i].HasValue && mesJetons.Contains(sesJetons[i]))
{
mesJetons[mesJetons.IndexOf(sesJetons[i])] = null;
sesJetons[i] = null;
indicateurs.Add(Indicateur.BonneCouleur);
}
}
return indicateurs;
}
///
/// Retourne la taille du code sous forme de chaîne de caractères.
///
/// Renvoie une chaîne de caractères représentant la taille du code.
public override string ToString() => $"Code({Taille})";
}
}