Merge pull request ' Navigation, Persistance, Binding et Actualisation' (#97) from navigation into dev
continuous-integration/drone/push Build is failing Details

Reviewed-on: #97
Reviewed-by: Remi NEVEU <remi.neveu@etu.uca.fr>
pull/99/head
Remi NEVEU 11 months ago
commit da44204a0f

@ -26,13 +26,13 @@ namespace DataContractPersistence
/// <summary>
/// Path (relative to the project)
/// </summary>
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
public string FilePath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Trek_12");
/// <summary>
/// Load all the data from JSON file
/// </summary>
/// <returns>A tuple with the lists of players, games, maps and best scores</returns>
public (List<Player>, List<Game>, List<Map>, List<BestScore>) LoadData()
public (ObservableCollection<Player>, ObservableCollection<Game>, ObservableCollection<Map>, ObservableCollection<BestScore>) LoadData()
{
var JsonSerializer = new DataContractJsonSerializer(typeof(DataToPersist));
DataToPersist? data = new DataToPersist();
@ -52,8 +52,9 @@ namespace DataContractPersistence
/// <param name="games"></param>
/// <param name="maps"></param>
/// <param name="bestScores"></param>
public void SaveData(List<Player> players, List<Game> games, List<Map> maps, List<BestScore> bestScores)
public void SaveData(ObservableCollection<Player> players, ObservableCollection<Game> games, ObservableCollection<Map> maps, ObservableCollection<BestScore> bestScores)
{
Debug.WriteLine("Saving data at " + Path.Combine(FilePath, FileName));
if (!Directory.Exists(FilePath))
{
Debug.WriteLine("Directory created");

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
@ -23,13 +24,13 @@ namespace DataContractPersistence
/// <summary>
/// Path (relative to the project)
/// </summary>
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
public string FilePath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Trek_12");
/// <summary>
/// Load all the data from XML file
/// </summary>
/// <returns>A tuple with the lists of players, games, maps and best scores</returns>
public (List<Player>, List<Game>, List<Map>, List<BestScore>) LoadData()
public (ObservableCollection<Player>, ObservableCollection<Game>, ObservableCollection<Map>, ObservableCollection<BestScore>) LoadData()
{
var serializer = new DataContractSerializer(typeof(DataToPersist));
DataToPersist? data = new DataToPersist();
@ -49,7 +50,7 @@ namespace DataContractPersistence
/// <param name="games"></param>
/// <param name="maps"></param>
/// <param name="bestScores"></param>
public void SaveData(List<Player> players, List<Game> games, List<Map> maps, List<BestScore> bestScores)
public void SaveData(ObservableCollection<Player> players, ObservableCollection<Game> games, ObservableCollection<Map> maps, ObservableCollection<BestScore> bestScores)
{
if(!Directory.Exists(FilePath))
{

@ -8,21 +8,21 @@ namespace DataContractPersistence
/// <summary>
/// List of players
/// </summary>
public List<Player> Players { get; set; }
public ObservableCollection<Player> Players { get; set; }
/// <summary>
/// List of games (with all the data in it to be able to recreate the game)
/// </summary>
public List<Game> Games { get; set; }
public ObservableCollection<Game> Games { get; set; }
/// <summary>
/// List of maps with their boards
/// </summary>
public List<Map> Maps { get; set; }
public ObservableCollection<Map> Maps { get; set; }
/// <summary>
/// List of best scores
/// </summary>
public List<BestScore> BestScores { get; set; }
public ObservableCollection<BestScore> BestScores { get; set; }
}
}

@ -1,4 +1,5 @@
using System;
using Microsoft.Maui.Controls;
using Models.Interfaces;
namespace Models.Game
@ -25,5 +26,16 @@ namespace Models.Game
byte[] imageBytes = File.ReadAllBytes(imagePath);
return Convert.ToBase64String(imageBytes);
}
/// <summary>
/// Retrieve an image from a string encoded in base64
/// </summary>
/// <param name="imageString"></param>
/// <returns></returns>
public ImageSource RetrieveImage(string imageString)
{
byte[] imageBytes = Convert.FromBase64String(imageString);
return ImageSource.FromStream(() => new MemoryStream(imageBytes));
}
}
}

@ -1,7 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
@ -16,16 +19,59 @@ namespace Models.Game
/// The Game class represents a game session in the application.
/// It contains all the necessary properties and methods to manage a game, including the game loop, dice rolling, and use of the game rules.
/// </summary>
public class Game
public class Game : INotifyPropertyChanged
{
/* Persistence */
public IPersistence PersistenceManager { get; set; }
/* List for the game and persistence */
public List<Player> Players { get; set; }
public List<Game> Games { get; set; }
public List<Map> Maps { get; set; }
public List<BestScore> BestScores { get; set; }
private ObservableCollection<Player> _players;
public ObservableCollection<Player> Players
{
get => _players;
set
{
_players = value;
OnPropertyChanged(nameof(Players));
}
}
private ObservableCollection<Game> _games;
public ObservableCollection<Game> Games
{
get => _games;
set
{
_games = value;
OnPropertyChanged(nameof(Games));
}
}
private ObservableCollection<Map> _maps;
public ObservableCollection<Map> Maps
{
get => _maps;
set
{
_maps = value;
OnPropertyChanged(nameof(Maps));
}
}
private ObservableCollection<BestScore> _bestScores;
public ObservableCollection<BestScore> BestScores
{
get => _bestScores;
set
{
_bestScores = value;
OnPropertyChanged(nameof(BestScores));
}
}
private bool _isRunning;
public bool IsRunning
@ -74,6 +120,17 @@ namespace Models.Game
BestScores.Add(bestScore);
}
public bool RemovePlayer(string playerName)
{
Player player = Players.FirstOrDefault(p => p.Pseudo == playerName);
if (player == null)
{
return false;
}
Players.Remove(player);
return true;
}
public void LoadData()
{
var data = PersistenceManager.LoadData();
@ -101,10 +158,10 @@ namespace Models.Game
{
PersistenceManager = persistenceManager;
Players = new List<Player>();
Games = new List<Game>();
Maps = new List<Map>();
BestScores = new List<BestScore>();
Players = new ObservableCollection<Player>();
Games = new ObservableCollection<Game>();
Maps = new ObservableCollection<Map>();
BestScores = new ObservableCollection<BestScore>();
GameRules = new Rules.Rules();
@ -113,8 +170,10 @@ namespace Models.Game
public Game()
{
UsedMap = new Map("Map1");
BestScores = new List<BestScore>();
Players = new ObservableCollection<Player>();
Games = new ObservableCollection<Game>();
Maps = new ObservableCollection<Map>();
BestScores = new ObservableCollection<BestScore>();
GameRules = new Rules.Rules();
@ -351,5 +410,19 @@ namespace Models.Game
return true;
//BoardUpdated?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Event raised when a property is changed to notify the view.
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// Trigger the PropertyChanged event for a specific property.
/// </summary>
/// <param name="propertyName">Name of the property that changed.</param>
public virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

@ -7,20 +7,10 @@ namespace Models.Game
/// </summary>
public class OperationCell : Position
{
private bool isChecked;
/// <summary>
/// It tells if the operation is checked or not in the operation grid of the game.
/// </summary>
public bool IsChecked
{
get => isChecked;
private set
{
isChecked = value;
OnPropertyChanged(nameof(IsChecked));
}
}
public bool IsChecked { get; private set; }
/// <summary>
/// Constructor of the OperationCell class.

File diff suppressed because one or more lines are too long

@ -7,7 +7,7 @@ namespace Models.Game
/// <summary>
/// The Position (x,y) of a cell in the game.
/// </summary>
public class Position : INotifyPropertyChanged
public class Position
{
/// <summary>
/// The X coordinate.
@ -29,19 +29,5 @@ namespace Models.Game
X = x;
Y = y;
}
/// <summary>
/// Event raised when a property is changed to notify the view.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Trigger the PropertyChanged event for a specific property.
/// </summary>
/// <param name="propertyName">Name of the property that changed.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

@ -1,4 +1,6 @@
namespace Models.Interfaces
using Microsoft.Maui.Controls;
namespace Models.Interfaces
{
/// <summary>
/// Interface for image converters
@ -11,5 +13,12 @@
/// <param name="imagePath"></param>
/// <returns></returns>
string ConvertImage(string imagePath);
/// <summary>
/// Retrieve an image from a string encoded
/// </summary>
/// <param name="imageString"></param>
/// <returns></returns>
ImageSource RetrieveImage(string imageString);
}
}

@ -1,11 +1,12 @@
using Models.Game;
using System.Collections.ObjectModel;
namespace Models.Interfaces
{
public interface IPersistence
{
(List<Player>, List<Game.Game>, List<Map>, List<BestScore>) LoadData();
(ObservableCollection<Player>, ObservableCollection<Game.Game>, ObservableCollection<Map>, ObservableCollection<BestScore>) LoadData();
void SaveData(List<Player> players, List<Game.Game> games, List<Map> maps, List<BestScore> bestScores);
void SaveData(ObservableCollection<Player> players, ObservableCollection<Game.Game> games, ObservableCollection<Map> maps, ObservableCollection<BestScore> bestScores);
}
}

@ -8,6 +8,13 @@
<ItemGroup>
<Folder Include="Rules\" />
<Folder Include="Game\" />
<Folder Include="Events\" />
<Folder Include="Interfaces\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls.Core" Version="8.0.3" />
</ItemGroup>
</Project>

@ -1,28 +1,58 @@
using DataContractPersistence;
using System.Diagnostics;
using System.Runtime.Serialization.DataContracts;
using DataContractPersistence;
using Models.Game;
using Models.Interfaces;
namespace Trek_12
{
public partial class App : Application
{
public string FileName { get; set; } = "data.json";
public string FilePath { get; set; } = Path.Combine(AppDomain.CurrentDomain.BaseDirectory);
public string FilePath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Trek_12");
public Game Manager { get; private set; }
public App()
{
InitializeComponent();
if(File.Exists(Path.Combine(FilePath, FileName)))
Manager = new Game(new DataContractJson());
if (!Directory.Exists(FilePath))
{
Directory.CreateDirectory(FilePath);
}
//File.Delete(Path.Combine(FilePath, FileName));
string fullPath = Path.Combine(FilePath, FileName);
if (File.Exists(fullPath))
{
Manager = new Game(new DataContractJson());
Debug.WriteLine("Data loaded from " + fullPath);
Manager.LoadData();
}
Manager.LoadData();
MainPage = new AppShell();
// If the MainPage is closed, we save the data
MainPage.Disappearing += (sender, e) =>
{
Debug.WriteLine("Saving data...");
Manager.SaveData();
};
}
/// <summary>
/// Save the data when the app is in background
/// </summary>
protected override void OnSleep()
{
Debug.WriteLine("Zzz Secure save...");
Manager.SaveData();
}
}
}

@ -1,10 +1,21 @@
namespace Trek_12
using Trek_12.Views;
namespace Trek_12
{
/// <summary>
/// Class for the route of the views and the navigation of the app.
/// </summary>
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(PageMenuPrincipal), typeof(PageMenuPrincipal));
Routing.RegisterRoute(nameof(PageProfils), typeof(PageProfils));
Routing.RegisterRoute(nameof(PageSelectMap), typeof(PageSelectMap));
Routing.RegisterRoute(nameof(PageRegles), typeof(PageRegles));
Routing.RegisterRoute(nameof(PageLeaderBoard), typeof(PageLeaderBoard));
}
}
}

File diff suppressed because one or more lines are too long

@ -3,8 +3,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Trek_12.Views.PageProfils"
xmlns:views="clr-namespace:Trek_12.Views.Components"
xmlns:game="clr-namespace:Models.Game;assembly=Models"
Title="pageProfils">
<ContentPage.Resources>
<ResourceDictionary>
<game:Base64Converter x:Key="Base64Converter"/>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
@ -14,7 +21,7 @@
<Label Text="Profils" TextColor="black" HorizontalTextAlignment="Center" FontSize="Header" Margin="30"/>
<CollectionView Grid.Row="1" ItemsSource="{Binding ListPlayer}"
<CollectionView Grid.Row="1" ItemsSource="{Binding Players}"
ItemsLayout="VerticalList"
VerticalOptions="Center">
<CollectionView.ItemTemplate>

@ -1,46 +1,68 @@
namespace Trek_12.Views;
using Models.Game;
using Stub;
using System.Diagnostics;
using CommunityToolkit.Maui.Alerts;
using CommunityToolkit.Maui.Core;
using Models.Interfaces;
namespace Trek_12.Views;
public partial class PageProfils : ContentPage
{
public Stub MyStub { get; set; } = new Stub();
public Game ProfileManager => (App.Current as App).Manager;
public PageProfils()
{
InitializeComponent();
BindingContext = MyStub;
BindingContext = ProfileManager;
}
async void Button_ClickedAdd(System.Object sender, System.EventArgs e)
{
string result = await DisplayPromptAsync("Info", $"Choose a name : ", "Ok");
Debug.WriteLine("Answer: " + result);
if (result != null)
{
Debug.WriteLine("bam, added");
MyStub.Add(result, "profile.jpg");
}
}
string pseudo = await DisplayPromptAsync("Info", $"Choose a name : ", "Ok");
if (pseudo == null) return;
var profilePicture = await MediaPicker.PickPhotoAsync();
if (profilePicture == null) return;
IImageConverter converter = new Base64Converter();
string convertedProfilePicture = converter.ConvertImage(profilePicture.FullPath);
Player player = new Player(pseudo, convertedProfilePicture);
ProfileManager.AddPlayer(player);
Debug.WriteLine("Player " + pseudo + " added with profile picture " + convertedProfilePicture);
Debug.WriteLine("It's the number" + ProfileManager.Players.Count + " player");
ProfileManager.OnPropertyChanged(nameof(ProfileManager.Players));
ProfileManager.SaveData();
}
async void Button_ClickedPop(System.Object sender, System.EventArgs e)
{
string result = await DisplayPromptAsync("Info", $"Choose a name to delete : ", "Ok");
if (ProfileManager.Players.Count == 0)
{
await DisplayAlert("Info", "There is no player actually\nPlease add one", "Ok");
return;
}
string result = await DisplayPromptAsync("Info", $"Choose a pseudo to delete : ", "Ok");
if (result == null) return;
Debug.WriteLine("Answer: " + result);
if (result != null)
if (ProfileManager.RemovePlayer(result))
{
Debug.WriteLine("bam, deleted");
MyStub.Pop(result, "profile.jpg");
OnPropertyChanged(nameof(ProfileManager));
}
else Debug.WriteLine("Pseudo not found");
else Debug.WriteLine("Player not found");
}
async void Button_ClickedModify(System.Object sender, System.EventArgs e)
{
throw new NotImplementedException();
/*
string result = await DisplayPromptAsync("Info", $"Choose a name to modify : ", "Ok");
Debug.WriteLine("Answer: " + result);
if (result != null)
@ -60,7 +82,7 @@ public partial class PageProfils : ContentPage
}
}
else Debug.WriteLine("Did not found");
*/
}
}

Loading…
Cancel
Save