v0.9 - Ajouts: Système de commentaire ; Affichage des genres et plateformes ; Ajout de la persistence avec JSON ; Modification de la solution en projets ; Bouton déconnexion fonctionnel ; Documentation du Code (Models) ; Ajout de Tests Unitaires
continuous-integration/drone/push Build is failing Details

pull/71/head
Rémi LAVERGNE 2 years ago
parent 90f7273e67
commit 910b3c69fc

@ -0,0 +1,68 @@
using Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
using System.Text.Json;
namespace DataContractPersistance
{
public class DataContractJSON : IPersistanceManager
{
public string FileName { get; set; } = "data.json";
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
public (ObservableCollection<Jeu>, List<Admin>, List<Utilisateur>) ChargeDonnees()
{
DataContractJsonSerializer JsonSerializer = new DataContractJsonSerializer(typeof(DataToPersist));
DataToPersist? data = new DataToPersist();
using (Stream s = File.OpenRead(Path.Combine(FilePath, FileName)))
{
data = JsonSerializer.ReadObject(s) as DataToPersist;
}
return (data!.Jeux, data.Admins, data.Utilisateurs);
}
public void SauvegardeDonnees(ObservableCollection<Jeu> jeux, List<Admin> admins, List<Utilisateur> users)
{
DataContractJsonSerializer JsonSerializer = new DataContractJsonSerializer(typeof(DataToPersist));
if(!Directory.Exists(FilePath))
{
Debug.WriteLine("Directory créé");
Debug.WriteLine(Directory.GetDirectoryRoot(FilePath));
Debug.WriteLine(FilePath);
Directory.CreateDirectory(FilePath);
}
DataToPersist data = new DataToPersist();
data.Jeux = jeux;
data.Admins = admins;
data.Utilisateurs = users;
var settings = new XmlWriterSettings() { Indent = true };
using (FileStream stream = File.Create(Path.Combine(FilePath, FileName)))
{
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(
stream,
Encoding.UTF8,
false,
true)) // Indentation
{
JsonSerializer.WriteObject(writer, data);
writer.Flush();
}
}
}
}
}

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,61 @@
using Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
namespace DataContractPersistance
{
public class DataContractXML : IPersistanceManager
{
public string FileName { get; set; } = "data.xml";
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
public (ObservableCollection<Jeu>, List<Admin>, List<Utilisateur>) ChargeDonnees()
{
var serializer = new DataContractSerializer(typeof(DataToPersist));
DataToPersist? data = new DataToPersist();
using (Stream s = File.OpenRead(Path.Combine(FilePath, FileName)))
{
data = serializer.ReadObject(s) as DataToPersist;
}
return (data!.Jeux, data.Admins, data.Utilisateurs);
}
public void SauvegardeDonnees(ObservableCollection<Jeu> jeux, List<Admin> admins, List<Utilisateur> users)
{
var serializer = new DataContractSerializer(typeof(DataToPersist));
if(!Directory.Exists(FilePath))
{
Debug.WriteLine("Directory créé");
Debug.WriteLine(Directory.GetDirectoryRoot(FilePath));
Debug.WriteLine(FilePath);
Directory.CreateDirectory(FilePath);
}
DataToPersist data = new DataToPersist();
data.Jeux = jeux;
data.Admins = admins;
data.Utilisateurs = users;
var settings = new XmlWriterSettings() { Indent = true };
using (TextWriter tw = File.CreateText(Path.Combine(FilePath, FileName)))
{
using (XmlWriter writer = XmlWriter.Create(tw, settings))
{
serializer.WriteObject(writer, data);
}
}
}
}
}

@ -6,12 +6,12 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameAtlas.DataContractPersistance
namespace DataContractPersistance
{
public class DataToPersist
{
public ObservableCollection<Jeu> jeux { get; set; } = new ObservableCollection<Jeu>();
public List<Admin> admins { get; set; } = new List<Admin>();
public List<Utilisateur> utilisateurs { get; set; } = new List<Utilisateur>();
public ObservableCollection<Jeu> Jeux { get; set; } = new ObservableCollection<Jeu>();
public List<Admin> Admins { get; set; } = new List<Admin>();
public List<Utilisateur> Utilisateurs { get; set; } = new List<Utilisateur>();
}
}

@ -5,9 +5,13 @@ VisualStudioVersion = 17.0.31611.283
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameAtlas", "GameAtlas\GameAtlas.csproj", "{D3C0D86A-FF1B-4C1B-AA60-537889127607}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{0B50E976-EC7C-4A88-96DA-632162084160}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Models", "Models\Models.csproj", "{0B50E976-EC7C-4A88-96DA-632162084160}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{6DD3E0DA-035C-411E-ABB4-794181D25A72}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{6DD3E0DA-035C-411E-ABB4-794181D25A72}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataContractPersistance", "DataContractPersistance\DataContractPersistance.csproj", "{B8902707-9F3B-41D0-8D5C-72ABED9323C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stub", "Stub\Stub.csproj", "{A6BAE3C5-B7EB-4090-9050-65721F861DD4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -29,6 +33,14 @@ Global
{6DD3E0DA-035C-411E-ABB4-794181D25A72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DD3E0DA-035C-411E-ABB4-794181D25A72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DD3E0DA-035C-411E-ABB4-794181D25A72}.Release|Any CPU.Build.0 = Release|Any CPU
{B8902707-9F3B-41D0-8D5C-72ABED9323C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8902707-9F3B-41D0-8D5C-72ABED9323C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8902707-9F3B-41D0-8D5C-72ABED9323C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8902707-9F3B-41D0-8D5C-72ABED9323C2}.Release|Any CPU.Build.0 = Release|Any CPU
{A6BAE3C5-B7EB-4090-9050-65721F861DD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6BAE3C5-B7EB-4090-9050-65721F861DD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6BAE3C5-B7EB-4090-9050-65721F861DD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6BAE3C5-B7EB-4090-9050-65721F861DD4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -1,13 +1,14 @@
using Models;
using Stub;
using DataContractPersistance;
using GameAtlas.Views;
using GameAtlas.Stub;
namespace GameAtlas;
public partial class App : Application
{
public string FileName { get; set; } = "data.xml";
public string FileName { get; set; } = "data.json"; // data.xml
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
@ -18,7 +19,8 @@ public partial class App : Application
if (File.Exists(Path.Combine(FilePath, FileName)))
{
MyManager = new Manager(new DataContractPersistance.DataContractPers());
//MyManager = new Manager(new DataContractPersistance.DataContractXML());
MyManager = new Manager(new DataContractPersistance.DataContractJSON());
}
@ -29,7 +31,8 @@ public partial class App : Application
if (!File.Exists(Path.Combine(FilePath, FileName)))
{
MyManager.Persistance = new DataContractPersistance.DataContractPers();
//MyManager.Persistance = new DataContractPersistance.DataContractXML();
MyManager.Persistance = new DataContractPersistance.DataContractJSON();
}

@ -1,104 +0,0 @@
using Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Collections.ObjectModel;
namespace GameAtlas.DataContractPersistance
{
public class DataContractPers : IPersistanceManager
{
public string FileName { get; set; } = "data.xml";
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory); //Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/data";
public (ObservableCollection<Jeu>, List<Admin>, List<Utilisateur>) ChargeDonnees()
{
var serializer = new DataContractSerializer(typeof(DataToPersist));
DataToPersist data = new DataToPersist();
using (Stream s = File.OpenRead(Path.Combine(FilePath, FileName)))
{
data = serializer.ReadObject(s) as DataToPersist;
}
return (data.jeux, data.admins, data.utilisateurs);
}
public void SauvegardeDonnees(ObservableCollection<Jeu> jeux, List<Admin> admins, List<Utilisateur> users)
{
var serializer = new DataContractSerializer(typeof(DataToPersist));
if(!Directory.Exists(FilePath))
{
Debug.WriteLine("Directory créé");
Debug.WriteLine(Directory.GetDirectoryRoot(FilePath));
Debug.WriteLine(FilePath);
Directory.CreateDirectory(FilePath);
}
DataToPersist data = new DataToPersist();
data.jeux = jeux;
data.admins = admins;
data.utilisateurs = users;
var settings = new XmlWriterSettings() { Indent = true };
using (TextWriter tw = File.CreateText(Path.Combine(FilePath, FileName)))
{
using (XmlWriter writer = XmlWriter.Create(tw, settings))
{
serializer.WriteObject(writer, data);
}
}
/*using (Stream s = File.Create(Path.Combine(FilePath, FileName)))
{
serializer.WriteObject(s, users);
}*/
}
public void SauvegardeUser(Utilisateur user)
{
var serializer = new DataContractSerializer(typeof(List<Utilisateur>));
if (!Directory.Exists(FilePath))
{
Debug.WriteLine("Directory créé");
Debug.WriteLine(FilePath);
Directory.CreateDirectory(FilePath);
}
var settings = new XmlWriterSettings() { Indent = true };
using (TextWriter tw = File.CreateText(Path.Combine(FilePath, FileName)))
{
using (XmlWriter writer = XmlWriter.Create(tw, settings))
{
serializer.WriteObject(writer, new List<Utilisateur> { user });
}
}
Debug.WriteLine("Un utilisateur a été sauvegardé !");
}
/*public (List<Jeu>, List<Utilisateur>) ChargeDonnees2()
{
var serializer = new DataContractSerializer(typeof(List<Utilisateur>));
DataToPersist data;
using (Stream s = File.OpenRead(Path.Combine(FilePath, FileName)))
{
data = serializer.ReadObject(s) as DataToPersist;
}
return (data.jeux, data.users);
}*/
}
}

@ -135,6 +135,8 @@
<ItemGroup>
<ProjectReference Include="..\Models\Models.csproj" />
<ProjectReference Include="..\Stub\Stub.csproj" />
<ProjectReference Include ="..\DataContractPersistance\DataContractPersistance.csproj" />
</ItemGroup>
</Project>

@ -5,9 +5,6 @@
xmlns:views="clr-namespace:GameAtlas.Views.Composants"
x:Class="GameAtlas.Views.PageAcceuil"
Title="ACCUEIL">
<!-- WidthRequest="390" HeightRequest="844"> -->
<Grid>

@ -4,7 +4,7 @@
x:Class="GameAtlas.Views.PageAdmin"
Title="Page Admin">
<Grid x:Name="outerGrid" RowDefinitions="50,50,30,30,30" ColumnDefinitions="50,*,50" RowSpacing="60" Padding="10,20,10,0">
<Grid RowDefinitions="50,50,30,30,30" ColumnDefinitions="50,*,50" RowSpacing="60" Padding="10,20,10,0">
<Grid.Background>
<LinearGradientBrush EndPoint="1,0">

@ -54,7 +54,8 @@ public partial class PageConnexion : ContentPage
*/
private async void OnInscrire_Tapped(object sender, EventArgs e)
{
await Navigation.PushAsync(new PageInscription());
await Navigation.PushModalAsync(new PageInscription());
}
/**

@ -1,15 +1,18 @@
namespace GameAtlas.Views;
using Models;
using GameAtlas.DataContractPersistance;
using DataContractPersistance;
using System.Diagnostics;
using System.Text.RegularExpressions;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Alerts;
using Font = Microsoft.Maui.Font;
public partial class PageInscription : ContentPage
{
DataContractPers PersistanceManager = new DataContractPers();
public Manager InscriptionManager => (App.Current as App).MyManager;
public PageInscription()
{
InitializeComponent();
@ -45,10 +48,9 @@ public partial class PageInscription : ContentPage
Utilisateur utilisateur = new Utilisateur(mail, username, password);
InscriptionManager.AddUtilisateur(utilisateur);
InscriptionManager.SauvegardeDonnees();
//PersistanceManager.SauvegardeUser(utilisateur);
Debug.WriteLine(InscriptionManager.Utilisateurs.Count);
//await Navigation.PushAsync(new PageAcceuil());
await DisplayAlert("Compte créer avec succès !","Vous pouvez maintenant vous connecter.", cancel: "Ok");
await Shell.Current.GoToAsync("//page/PageAccueil");
@ -86,4 +88,5 @@ public partial class PageInscription : ContentPage
}
}

@ -4,7 +4,7 @@
x:Class="GameAtlas.Views.PageJeu"
Title="PageJeu">
<Grid x:Name="outerGrid">
<Grid>
<Grid.Background>
<LinearGradientBrush EndPoint="1,0">
@ -39,15 +39,7 @@
<Label Text="{Binding JeuModel.Sortie}" FontFamily="RobotoRegular" FontSize="11" TextColor="{StaticResource Gray500}"/>
<FlexLayout Direction="Row" JustifyContent="Start" AlignItems="Start" Wrap="Wrap" >
<BindableLayout.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>XONE</x:String>
<x:String>PS5</x:String>
<x:String>PC</x:String>
<x:String>SWITCH</x:String>
</x:Array>
</BindableLayout.ItemsSource>
<FlexLayout BindableLayout.ItemsSource="{Binding JeuModel.ListPlateformes}" Direction="Row" JustifyContent="Start" AlignItems="Start" Wrap="Wrap">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="18" ColumnDefinitions="auto">
@ -111,7 +103,7 @@
<Frame Grid.Column="6" BorderColor="{StaticResource Black}" CornerRadius="5" Padding="15,15,30,15" BackgroundColor="Transparent">
<Grid RowDefinitions="auto,auto" ColumnDefinitions="*" ColumnSpacing="15" VerticalOptions="Center">
<Label Grid.Column="0" Text="{Binding JeuModel.ListeAvis.Count}" FontFamily="RobotoRegular" FontSize="16" TextColor="{StaticResource Black}" VerticalOptions="Center"/>
<Label Grid.Column="0" Text="{Binding JeuModel.ListAvis.Count}" FontFamily="RobotoRegular" FontSize="16" TextColor="{StaticResource Black}" VerticalOptions="Center"/>
<Label Grid.Row="1" Grid.Column="0" Text="Avis" FontFamily="RobotoRegular" FontSize="12" TextColor="{StaticResource Gray500}" VerticalOptions="Center"/>
</Grid>
</Frame>
@ -127,13 +119,7 @@
<Label Text="Genres" FontFamily="PTSansCBold" FontSize="14" TextColor="{StaticResource Black}" Margin="0,10,0,0"/>
<FlexLayout Direction="Row" JustifyContent="Start" AlignItems="Start" Wrap="Wrap" >
<BindableLayout.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>🧙🏻 Jeu de rôle</x:String>
<x:String>🏹 Aventure</x:String>
</x:Array>
</BindableLayout.ItemsSource>
<FlexLayout BindableLayout.ItemsSource="{Binding JeuModel.ListGenres}" Direction="Row" JustifyContent="Start" AlignItems="Start" Wrap="Wrap">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid RowDefinitions="20" ColumnDefinitions="auto">
@ -149,9 +135,10 @@
<Label Text="{Binding JeuModel.Resume}" FontFamily="PTSansNRegular" FontSize="10" TextColor="{StaticResource Gray500}" VerticalOptions="Center"/>
<Button Text="+ Ajouter un commentaire" FontFamily="PTSansCBold" FontSize="13" TextColor="{StaticResource Black}" Clicked="OnAddCommentClicked"/>
<VerticalStackLayout Spacing="10" Margin="0,15,0,0">
<BindableLayout.ItemTemplate ItemsSource="{Binding JeuModel.ListeAvis}">
<Button Text="+ Ajouter un commentaire" CornerRadius="5" FontFamily="PTSansCBold" FontSize="13" Margin="20,10,20,10" HeightRequest="40" BackgroundColor="{StaticResource Primary}" TextColor="{StaticResource Black}" Clicked="OnAddCommentClicked"/>
<VerticalStackLayout BindableLayout.ItemsSource="{Binding JeuModel.ListAvis}" Spacing="10" Margin="0,15,0,0">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Frame CornerRadius="5" BackgroundColor="{StaticResource Tertiary}" Padding="15">
<Grid ColumnDefinitions="30,*" RowDefinitions="30,auto" ColumnSpacing="10" RowSpacing="10">
@ -170,14 +157,14 @@
</Frame>
<VerticalStackLayout Grid.Column="1" VerticalOptions="Center" Spacing="3">
<Label Text="{Binding Item1}" FontSize="14" FontFamily="AladinRegular" TextColor="{StaticResource Black}"/>
<Label Text="{Binding [0]}" FontSize="14" FontFamily="AladinRegular" TextColor="{StaticResource Black}"/>
<HorizontalStackLayout Spacing="3">
<Image Source="starrating" HeightRequest="10" VerticalOptions="Center" Margin="0,-2,0,0"/>
<Label Text="{Binding Item2}" FontSize="10" FontFamily="RobotoRegular" TextColor="{StaticResource Gray600}" VerticalOptions="Center"/>
<Label Text="{Binding [1]}" FontSize="10" FontFamily="RobotoRegular" TextColor="{StaticResource Gray600}" VerticalOptions="Center"/>
</HorizontalStackLayout>
</VerticalStackLayout>
<Label Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding Item3}" FontFamily="PTSansNRegular" FontSize="10" TextColor="{StaticResource Gray500}" VerticalOptions="Center"/>
<Label Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding [2]}" FontFamily="PTSansNRegular" FontSize="10" TextColor="{StaticResource Gray500}" VerticalOptions="Center"/>
</Grid>
</Frame>

@ -24,7 +24,9 @@ public partial class PageJeu : ContentPage
{
JeuModel = jeu;
Debug.WriteLine($"Nombre d'avis sur ce jeu: {JeuModel.ListAvis.Count()}");
Debug.WriteLineIf(JeuModel.ListAvis.Count() >= 1, $"Contenu du 1er avis:\nAuteur: {JeuModel.ListAvis[0].Item1}\nAvis: {JeuModel.ListAvis[0].Item2}\nMessage: {JeuModel.ListAvis[0].Item3}");
InitializeComponent();
BindingContext = this;
@ -103,7 +105,18 @@ public partial class PageJeu : ContentPage
string commentaire = await DisplayPromptAsync("⭐ Votre Avis", "Ecrivez votre commentaire:\n(250 caractères maximum)", maxLength: 250, accept: "Suivant", cancel: "Annuler");
string note = await DisplayPromptAsync("✒️ La Note", "De 0 à 10", maxLength: 3, accept: "Envoyer", cancel: "Annuler");
JeuModel.AjouterAvis(JeuManager.ConnectedUser.Pseudo, Convert.ToDouble(note), commentaire);
if (JeuModel != null && JeuModel.ListAvis != null)
{
string pseudo = JeuManager.ConnectedUser.Pseudo;
double notation = Convert.ToDouble(note);
JeuManager.ConnectedUser.NbAvis += 1;
JeuModel.AjouterAvis(pseudo, notation, commentaire);
JeuManager.OnPropertyChanged(nameof(JeuModel.ListAvis));
JeuManager.SauvegardeDonnees();
Debug.WriteLine("Un commentaire a été ajouté.");
}
}
else
{
@ -116,7 +129,7 @@ public partial class PageJeu : ContentPage
await Navigation.PopAsync();
}
async void Alert()
private async void Alert()
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

@ -6,7 +6,7 @@
Title="ECRAN DE CONNEXION" WidthRequest="390" HeightRequest="844">
<Grid x:Name="outerGrid">
<Grid>
<Grid.Background>
<LinearGradientBrush EndPoint="1,0">

@ -4,7 +4,7 @@
x:Class="GameAtlas.Views.PageProfil"
Title="PageProfil">
<Grid x:Name="outerGrid" RowDefinitions="50,35,*" ColumnDefinitions="70,*,70" ColumnSpacing="15" RowSpacing="30" Padding="10,20,10,0">
<Grid RowDefinitions="50,35,*" ColumnDefinitions="70,*,70" ColumnSpacing="15" RowSpacing="30" Padding="10,20,10,0">
<Grid.Background>
<LinearGradientBrush EndPoint="1,0">
@ -43,15 +43,16 @@
</Label>
</VerticalStackLayout>
<Image Source="logout.png" Grid.Column="2">
<Image Source="logout.png" Grid.Column="2"
HeightRequest="30" HorizontalOptions="Center">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnDisconnect_Tapped"/>
</Image.GestureRecognizers>
</Image>
<Grid Grid.Row="0" Grid.Column="2" RowDefinitions="50" ColumnDefinitions="50" HorizontalOptions="Start">
<Frame IsVisible="{Binding ConnectedUser.EstAdmin}" WidthRequest="50" HeightRequest="50" CornerRadius="25" VerticalOptions="Start" IsClippedToBounds="True" BackgroundColor="{StaticResource Tertiary}">
<Image Source="shieldperson" HeightRequest="40"/>
<Grid Grid.Row="0" Grid.Column="2" Padding="0,0,100,0" HorizontalOptions="Center">
<Frame IsVisible="{Binding ConnectedUser.EstAdmin}" WidthRequest="40" HeightRequest="40" CornerRadius="25" VerticalOptions="Center" IsClippedToBounds="True" BackgroundColor="{StaticResource Tertiary}">
<Image Source="shieldperson" HeightRequest="30"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="OnAdmin_Tapped"/>
@ -83,8 +84,14 @@
<BoxView Grid.Column="3" Color="{StaticResource Black}" WidthRequest="1"/>
<Label Grid.Column="4" Text="0&#x0a;Avis" FontSize="12" FontFamily="RobotoRegular" TextColor="{StaticResource Black}" VerticalOptions="Center" HorizontalOptions="Center" HorizontalTextAlignment="Start" LineHeight="1.15"/>
<Label Grid.Column="4" FontSize="12" FontFamily="RobotoRegular" TextColor="{StaticResource Black}" VerticalOptions="Center" HorizontalOptions="Center" HorizontalTextAlignment="Start" LineHeight="1.2">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding ConnectedUser.NbAvis}" />
<Span Text="&#x0a;Avis" />
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>
<Border Grid.Row="2" Grid.ColumnSpan="3" StrokeShape="RoundRectangle 20,20,0,0" StrokeThickness="0" Margin="-10,0" BackgroundColor="{StaticResource Secondary}">

@ -9,6 +9,11 @@ public partial class PageProfil : ContentPage
{
InitializeComponent();
BindingContext = ProfilManager;
}
protected override void OnAppearing()
{
base.OnAppearing();
SwitchPage();
}

@ -11,13 +11,22 @@ using System.Threading.Tasks;
namespace Models
{
/// <summary>
/// Représente un administrateur qui hérite d'Utilisateur.
/// </summary>
[DataContract]
public class Admin : Utilisateur
{
/// <summary>
/// Constructeur qui initialise une nouvelle instance de la classe <see cref="Admin"/> qui hérite de <see cref="Utilisateur"/>.
/// </summary>
/// <param name="mail">L'adresse e-mail de l'administrateur.</param>
/// <param name="pseudo">Le pseudo de l'administrateur.</param>
/// <param name="mdp">Le mot de passe de l'administrateur.</param>
public Admin(string mail, string pseudo, string mdp) : base(mail, pseudo, mdp)
{
EstAdmin = true;
}
}
}

@ -7,10 +7,24 @@ using System.Threading.Tasks;
namespace Models
{
/// <summary>
/// Interface pour la gestion de la persistance des données.
/// </summary>
public interface IPersistanceManager
{
(ObservableCollection<Jeu>,List<Admin>,List<Utilisateur>) ChargeDonnees();
/// <summary>
/// Charge les données persistantes.
/// </summary>
/// <returns>Un tuple contenant les collections de jeux, d'administrateurs et d'utilisateurs chargées.</returns>
(ObservableCollection<Jeu>, List<Admin>, List<Utilisateur>) ChargeDonnees();
/// <summary>
/// Sauvegarde les données persistantes.
/// </summary>
/// <param name="jeux">La collection de jeux à sauvegarder.</param>
/// <param name="admins">La liste des administrateurs à sauvegarder.</param>
/// <param name="utilisateurs">La liste des utilisateurs à sauvegarder.</param>
void SauvegardeDonnees(ObservableCollection<Jeu> jeux, List<Admin> admins, List<Utilisateur> utilisateurs);
}
}

@ -12,62 +12,150 @@ using System.Threading.Tasks;
namespace Models
{
/// <summary>
/// Représente un jeu-vidéo dans sa totalité, avec ses paramètres.
/// </summary>
[DataContract]
public class Jeu
{
/// <summary>
/// Obtient ou définit le nom du jeu.
/// </summary>
/// <value>Nom du jeu.</value>
[DataMember]
public string Nom { get; private set; }
/// <summary>
/// Obtient ou définit le résumé du jeu.
/// </summary>
/// <value>Description résumée du jeu.</value>
[DataMember]
public string Resume { get; private set; }
/// <summary>
/// Obtient ou définit la date de sortie du jeu.
/// </summary>
/// <value>La date de sortie du jeu (sans format préalable).</value>
[DataMember]
public string Sortie { get; private set; }
/// <summary>
/// Obtient ou définit la liste des plateformes du jeu.
/// </summary>
/// <value>La liste des plateformes du jeu.</value>
[DataMember]
public string Plateformes { get; private set; }
public List<string> ListPlateformes { get; private set; }
/// <summary>
/// Obtient ou définit le développeur du jeu.
/// </summary>
/// <value>Studio-développeur du jeu.</value>
[DataMember]
public string Developpeur { get; private set; }
/// <summary>
/// Obtient ou définit l'éditeur du jeu.
/// </summary>
/// <value>Studio-éditeur du jeu.</value>
[DataMember]
public string Editeur { get; private set; }
/// <summary>
/// Obtient ou définit la note du jeu.
/// </summary>
/// <value>La note du jeu (sur 10).</value>
[DataMember]
public double Note { get; private set; }
/// <summary>
/// Obtient ou définit le nombre de téléchargements du jeu.
/// </summary>
/// <value>Le nombre de téléchargements du jeu (en milliers).</value>
[DataMember]
public int NbTelechargement { get; private set; }
//[DataMember]
//public List<(string,string)> Revendeurs { get; private set; }
/// <summary>
/// Obtient ou définit la liste des genres du jeu.
/// </summary>
/// <value>La liste des genres du jeu.</value>
[DataMember]
public string Genres { get; private set; }
public List<string> ListGenres { get; private set; }
/// <summary>
/// Obtient ou définit l'image du jeu.
/// </summary>
/// <value>L'image du jeu.</value>
[DataMember]
public string Image { get; private set; }
[DataMember]
public ObservableCollection<(string,double,string)> ListeAvis { get; private set; }
/// <summary>
/// Obtient ou définit le nombre de favoris du jeu.
/// </summary>
/// <value>Le nombre d'utilisateur qui aiment le jeu.</value>
[DataMember]
public int NbFavoris { get; private set; }
/// <summary>
/// Obtient ou définit le nombre de copies possédées du jeu.
/// </summary>
/// <value>Le nombre d'utilisateur qui possèdent le jeu.</value>
[DataMember]
public int NbPossedes { get; private set; }
/// <summary>
/// Obtient ou définit la liste des avis du jeu.
/// </summary>
/// <value>La liste des avis du jeu.</value>
[DataMember]
public ObservableCollection<(string, double, string)> ListAvis { get; private set; }
/// <summary>
/// Constructeur qui initialise une nouvelle instance de la classe <see cref="Jeu"/>.
/// </summary>
/// <param name="nom">Le nom du jeu.</param>
/// <param name="resume">Le résumé du jeu.</param>
/// <param name="sortie">La date de sortie du jeu.</param>
/// <param name="plateformes">La liste des plateformes du jeu (séparées par des espaces).</param>
/// <param name="developpeur">Le développeur du jeu.</param>
/// <param name="editeur">L'éditeur du jeu.</param>
/// <param name="note">La note du jeu.</param>
/// <param name="nbTelechargement">Le nombre de téléchargements du jeu.</param>
/// <param name="genres">La liste des genres du jeu (séparés par des espaces).</param>
/// <param name="image">L'image du jeu.</param>
public Jeu(string nom, string resume, string sortie, string plateformes, string developpeur, string editeur, double note, int nbTelechargement, string genres, string image)
{
Nom = nom;
Resume = resume;
Sortie = sortie;
Plateformes = plateformes;
ListPlateformes = plateformes.Split(' ').ToList();
Developpeur = developpeur;
Editeur = editeur;
Note = note;
NbTelechargement = nbTelechargement;
//Revendeurs = revendeurs;
Genres = genres;
ListGenres = genres.Split(' ').ToList();
Image = image;
ListeAvis = new ObservableCollection<(string, double, string)>();
ListAvis = new ObservableCollection<(string, double, string)>();
NbFavoris = 0;
NbPossedes = 0;
}
/// <summary>
/// Ajoute un avis au jeu.
/// </summary>
/// <param name="pseudo">Le pseudo de l'utilisateur donnant l'avis.</param>
/// <param name="note">La note donnée par l'utilisateur (sur 10).</param>
/// <param name="commentaire">Le commentaire de l'utilisateur.</param>
public void AjouterAvis(string pseudo, double note, string commentaire)
{
this.ListeAvis.Add((pseudo, note, commentaire));
this.ListAvis.Add((pseudo, note, commentaire));
}
public override bool Equals(object obj)
/// <summary>
/// Détermine si l'objet spécifié est égal à l'objet actuel.
/// </summary>
/// <param name="obj">L'objet à comparer avec l'objet actuel (via le Nom et la Date de Sortie).</param>
/// <returns><see langword="true"/> si les objets sont égaux, sinon <see langword="false"/>.</returns>
public override bool Equals(object? obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
@ -76,6 +164,10 @@ namespace Models
return Nom == otherJeu.Nom && Sortie == otherJeu.Sortie;
}
/// <summary>
/// Retourne le code de hachage de l'objet actuel.
/// </summary>
/// <returns>Le code de hachage de l'objet actuel.</returns>
public override int GetHashCode()
{
return HashCode.Combine(Nom, Sortie);

@ -9,13 +9,26 @@ using System.Threading.Tasks;
namespace Models
{
/// <summary>
/// Classe qui gère la liaison entre Views et Models (View-Model-ViewModel).
/// </summary>
public class Manager : INotifyPropertyChanged
{
/// <summary>
/// Liste des administrateurs de l'application.
/// </summary>
public List<Admin> Admins { get; private set; }
/// <summary>
/// Liste des utilisateurs de l'application.
/// </summary>
public List<Utilisateur> Utilisateurs { get; private set; }
private ObservableCollection<Jeu> topRatedGames;
/// <summary>
/// Les jeux les mieux notés.
/// </summary>
public ObservableCollection<Jeu> TopRatedGames
{
get
@ -29,7 +42,11 @@ namespace Models
}
}
private ObservableCollection<Jeu> listJeuxAffiches;
/// <summary>
/// Les jeux affichés sur la page d'accueil.
/// </summary>
public ObservableCollection<Jeu> ListJeuxAffiches
{
get
@ -45,8 +62,11 @@ namespace Models
}
private ObservableCollection<Jeu> listJeux;
/// <summary>
/// Liste complète des jeux.
/// </summary>
public ObservableCollection<Jeu> ListJeux
{
{
get
{
return listJeux;
@ -58,10 +78,16 @@ namespace Models
}
}
/// <summary>
/// Gestionnaire de persistance utilisé pour charger et sauvegarder les données.
/// </summary>
public IPersistanceManager Persistance { get; set; }
private Utilisateur connectedUser;
public Utilisateur ConnectedUser
/// <summary>
/// Utilisateur actuellement connecté.
/// </summary>
public Utilisateur? ConnectedUser
{
get => connectedUser;
set
@ -73,9 +99,17 @@ namespace Models
public event PropertyChangedEventHandler? PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
/// <summary>
/// Déclenche l'événement PropertyChanged pour une propriété spécifiée.
/// </summary>
/// <param name="propertyName">Le nom de la propriété modifiée.</param>
public void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
/// <summary>
/// Constructeur de la classe Manager avec un gestionnaire de persistance spécifique.
/// </summary>
/// <param name="persistance">Le gestionnaire de persistance utilisé pour charger et sauvegarder les données.</param>
public Manager(IPersistanceManager persistance)
{
Utilisateurs = new List<Utilisateur>();
@ -85,28 +119,47 @@ namespace Models
ConnectedUser = null;
}
public Manager() {
/// <summary>
/// Constructeur par défaut de la classe Manager.
/// </summary>
public Manager()
{
ListJeux = new ObservableCollection<Jeu>();
Admins = new List<Admin>();
Utilisateurs = new List<Utilisateur>();
ConnectedUser = null;
}
/// <summary>
/// Ajoute un jeu à la liste des jeux.
/// </summary>
/// <param name="jeux">Le jeu à ajouter.</param>
public void AddJeux(Jeu jeux)
{
ListJeux.Add(jeux);
}
/// <summary>
/// Ajoute un administrateur à la liste des administrateurs.
/// </summary>
/// <param name="admin">L'administrateur à ajouter.</param>
public void AddAdmin(Admin admin)
{
Admins.Add(admin);
}
/// <summary>
/// Ajoute un utilisateur à la liste des utilisateurs.
/// </summary>
/// <param name="utilisateur">L'utilisateur à ajouter.</param>
public void AddUtilisateur(Utilisateur utilisateur)
{
Utilisateurs.Add(utilisateur);
}
/// <summary>
/// Charge les données persistantes à partir du gestionnaire de persistance.
/// </summary>
public void ChargerDonnees()
{
var donnees = Persistance.ChargeDonnees();
@ -117,21 +170,22 @@ namespace Models
}
foreach (var admin in donnees.Item2)
{
AddAdmin(admin);
{
AddAdmin(admin);
}
foreach (var jeu in donnees.Item1)
{
AddJeux(jeu);
}
}
/// <summary>
/// Sauvegarde les données persistantes en utilisant le gestionnaire de persistance.
/// </summary>
public void SauvegardeDonnees()
{
Persistance.SauvegardeDonnees(ListJeux, Admins, Utilisateurs);
}
}
}

@ -30,6 +30,8 @@ namespace Models
public ObservableCollection<Jeu> ListePossedes { get; private set; }
[DataMember]
public ObservableCollection<Jeu> ListeFavoris { get; private set; }
[DataMember]
public int NbAvis { get; set; }
public Utilisateur(string mail, string pseudo, string mdp)
{
@ -40,7 +42,7 @@ namespace Models
ListePossedes = new ObservableCollection<Jeu>();
ListeFavoris = new ObservableCollection<Jeu>();
EstAdmin = false;
NbAvis = 0;
}
}
}

@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameAtlas.Stub
namespace Stub
{
public class Stub : IPersistanceManager
{

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,32 @@
using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tests
{
public class AdminSimulation
{
[Fact]
public void Admin_Creation_Et_Verification()
{
string mail = "admin@example.com";
string pseudo = "admin";
string mdp = "password";
Admin admin = new Admin(mail, pseudo, mdp);
// Assert
Assert.Equal(mail, admin.Mail);
Assert.Equal(pseudo, admin.Pseudo);
Assert.Equal(mdp, admin.Mdp);
Assert.True(admin.EstAdmin);
Assert.Empty(admin.ListePossedes);
Assert.Empty(admin.ListeFavoris);
}
}
}

@ -0,0 +1,94 @@
using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tests
{
public class JeuCreation
{
[Fact]
public void Jeu_Creation_Et_Verification()
{
string nom = "Street Fighter 6";
string resume = "Un jeu de combat";
string sortie = "2 Juin 2023";
string plateformes = "PC Xbox PlayStation";
string developpeur = "CAPCOM Co., Ltd.";
string editeur = "Capcom";
double note = 4.5;
int nbTelechargement = 1200;
string genres = "Action Aventure";
string image = "test_image.png";
Jeu jeu = new Jeu(nom, resume, sortie, plateformes, developpeur, editeur, note, nbTelechargement, genres, image);
// Assert
Assert.Equal(nom, jeu.Nom);
Assert.Equal(resume, jeu.Resume);
Assert.Equal(sortie, jeu.Sortie);
Assert.Equal(plateformes, jeu.Plateformes);
Assert.Equal(developpeur, jeu.Developpeur);
Assert.Equal(editeur, jeu.Editeur);
Assert.Equal(note, jeu.Note);
Assert.Equal(nbTelechargement, jeu.NbTelechargement);
Assert.Equal(genres, jeu.Genres);
Assert.Equal(image, jeu.Image);
Assert.Empty(jeu.ListeAvis);
Assert.Equal(0, jeu.NbFavoris);
Assert.Equal(0, jeu.NbPossedes);
}
[Fact]
public void Jeu_AjouterAvis()
{
string nom = "Street Fighter 6";
string resume = "Un jeu de combat";
string sortie = "2 Juin 2023";
string plateformes = "PC Xbox PlayStation";
string developpeur = "CAPCOM Co., Ltd.";
string editeur = "Capcom";
double note = 4.5;
int nbTelechargement = 1200;
string genres = "Action Aventure";
string image = "test_image.png";
Jeu jeu = new Jeu(nom, resume, sortie, plateformes, developpeur, editeur, note, nbTelechargement, genres, image);
string pseudo = "John";
double notation = 8.6;
string commentaire = "Jeu mangifique !";
jeu.AjouterAvis(pseudo, notation, commentaire);
// Assert
Assert.Single(jeu.ListAvis);
var avis = jeu.ListAvis[0];
Assert.Equal(pseudo, avis.Item1);
Assert.Equal(notation, avis.Item2);
Assert.Equal(commentaire, avis.Item3);
}
[Fact]
public void Jeu_Comparer()
{
Jeu jeu1 = new Jeu("Un Jeu", "Description", "1 Janvier 2023", "PC", "Studio", "Editeur", 4.5, 1000, "Action", "test_image.png");
Jeu jeu2 = new Jeu("Un Jeu", "Description", "1 Janvier 2023", "PC", "Studio", "Editeur", 4.5, 1000, "Action", "test_image.png");
Jeu jeu3 = new Jeu("Un autre Jeu", "Une autre description", "12 Janvier 2023", "PS5", "Studio", "Autre Editeur", 3.8, 500, "Aventure", "test_image.png");
Jeu jeu4 = new Jeu("Un autre Jeu", "Une autre description", "1 Janvier 2023", "PS5", "Studio", "Autre Editeur", 3.8, 500, "Aventure", "test_image.png");
// Assert
Assert.Equal(jeu1, jeu2);
Assert.NotEqual(jeu1, jeu3);
Assert.NotEqual(jeu2, jeu3);
Assert.NotEqual(jeu1, jeu4);
}
}
}

@ -0,0 +1,139 @@
using Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tests
{
public class ManagerTest
{
[Fact]
public void Manager_Creation_Et_Verification()
{
var manager = new Manager();
// Assert
Assert.Empty(manager.Admins);
Assert.Empty(manager.Utilisateurs);
Assert.Empty(manager.TopRatedGames);
Assert.Empty(manager.ListJeuxAffiches);
Assert.Empty(manager.ListJeux);
Assert.Null(manager.ConnectedUser);
}
[Fact]
public void Manager_AddJeux()
{
var manager = new Manager();
var jeu = new Jeu("Un Jeu", "Description", "1 Janvier 2023", "PC", "Studio", "Editeur", 4.5, 1000, "Action", "test_image.png");
manager.AddJeux(jeu);
// Assert
Assert.Single(manager.ListJeux);
Assert.Contains(jeu, manager.ListJeux);
}
[Fact]
public void Manager_AddAdmin()
{
var manager = new Manager();
var admin = new Admin("admin@example.com", "admin", "password");
manager.AddAdmin(admin);
// Assert
Assert.Single(manager.Admins);
Assert.Contains(admin, manager.Admins);
}
[Fact]
public void Manager_AddUtilisateur()
{
var manager = new Manager();
var utilisateur = new Utilisateur("test@example.com", "test", "password");
manager.AddUtilisateur(utilisateur);
// Assert
Assert.Single(manager.Utilisateurs);
Assert.Contains(utilisateur, manager.Utilisateurs);
}
[Fact]
public void Manager_ChargerDonnees()
{
// Arrange
var manager = new Manager();
var jeux = new ObservableCollection<Jeu>()
{
new Jeu("Un Jeu", "Description", "1 Janvier 2023", "PC", "Studio", "Editeur", 4.5, 1000, "Action", "test_image.png"),
new Jeu("Un autre Jeu", "Une autre description", "12 Janvier 2023", "PS5", "Studio", "Autre Editeur", 3.8, 500, "Aventure", "test_image.png")
};
var admins = new List<Admin>()
{
new Admin("admin1@example.com", "admin1", "password1"),
new Admin("admin2@example.com", "admin2", "password2")
};
var utilisateurs = new List<Utilisateur>()
{
new Utilisateur("user1@example.com", "user1", "password1"),
new Utilisateur("user2@example.com", "user2", "password2")
};
manager.ListJeux = jeux;
manager.Admins = admins;
manager.Utilisateurs = utilisateurs;
manager.ChargerDonnees();
// Assert
Assert.Equal(jeux, manager.ListJeux);
Assert.Equal(admins, manager.Admins);
Assert.Equal(utilisateurs, manager.Utilisateurs);
}
[Fact]
public void Manager_SauvegardeDonnees()
{
var manager = new Manager();
var jeux = new ObservableCollection<Jeu>()
{
new Jeu("Un Jeu", "Description", "1 Janvier 2023", "PC", "Studio", "Editeur", 4.5, 1000, "Action", "test_image.png"),
new Jeu("Un autre Jeu", "Une autre description", "12 Janvier 2023", "PS5", "Studio", "Autre Editeur", 3.8, 500, "Aventure", "test_image.png")
};
var admins = new List<Admin>()
{
new Admin("admin1@example.com", "adminuser1", "password1"),
new Admin("admin2@example.com", "adminuser2", "password2")
};
var utilisateurs = new List<Utilisateur>()
{
new Utilisateur("user1@example.com", "user1", "password1"),
new Utilisateur("user2@example.com", "user2", "password2")
};
manager.ListJeux = jeux;
manager.Admins = admins;
manager.Utilisateurs = utilisateurs;
manager.SauvegardeDonnees();
// Assert
Assert.True(true); // Vérifie qu'il n'y a aucune exception de levée
}
}
}

@ -1,17 +0,0 @@
using Models;
using System.Diagnostics;
namespace Tests
{
public class UnitTest1
{
[Fact]
public void Test1()
{
Utilisateur Georges = new Utilisateur("georges.gio@gmail.com", "GeoStorm", "Storm7!");
Debug.WriteLine(Georges.Mail);
Debug.WriteLine(Georges.Pseudo);
Debug.WriteLine(Georges.EstAdmin);
}
}
}

@ -1,22 +0,0 @@
using Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tests
{
public class UnitTest2
{
[Fact]
public void Test2()
{
Admin Antoine = new Admin("antoine@gameatlas.com", "Antoine", "adminAntoine01");
Debug.WriteLine(Antoine.Mail);
Debug.WriteLine(Antoine.Pseudo);
Debug.WriteLine(Antoine.EstAdmin);
}
}
}

@ -15,7 +15,7 @@ namespace Tests
{
string mail = "test@example.com";
string pseudo = "testuser";
string pseudo = "test";
string mdp = "password";

Loading…
Cancel
Save