diff --git a/.drone.yml b/.drone.yml
index 89479ad..8379676 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -14,28 +14,28 @@ steps:
path: /docs
commands:
- cd src/EntityFramework_LoL/Sources/
- - dotnet restore LeagueOfLegends.sln
- - dotnet build LeagueOfLegends.sln -c Release --no-restore
- - dotnet publish LeagueOfLegends.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
+ - dotnet restore LeagueOfLegendsCI.sln
+ - dotnet build LeagueOfLegendsCI.sln -c Release --no-restore
+ - dotnet publish LeagueOfLegendsCI.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
- name: tests
image: mcr.microsoft.com/dotnet/sdk:6.0
commands:
- cd src/EntityFramework_LoL/Sources/
- - dotnet restore LeagueOfLegends.sln
- - dotnet test LeagueOfLegends.sln --no-restore
+ - dotnet restore LeagueOfLegendsCI.sln
+ - dotnet test LeagueOfLegendsCI.sln --no-restore
depends_on: [build]
- name: code-analysis
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dronesonarplugin-dotnet6
commands:
- cd src/EntityFramework_LoL/Sources/
- - dotnet restore LeagueOfLegends.sln
+ - dotnet restore LeagueOfLegendsCI.sln
- dotnet sonarscanner begin /k:LolProjectIUT /d:sonar.host.url=$${PLUGIN_SONAR_HOST} /d:sonar.coverageReportPaths="coveragereport/SonarQube.xml" /d:sonar.coverage.exclusions="Tests/**" /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
- - dotnet build LeagueOfLegends.sln -c Release --no-restore
- - dotnet test LeagueOfLegends.sln --logger trx --no-restore /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --collect "XPlat Code Coverage"
+ - dotnet build LeagueOfLegendsCI.sln -c Release --no-restore
+ - dotnet test LeagueOfLegendsCI.sln --logger trx --no-restore /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --collect "XPlat Code Coverage"
- reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport"
- - dotnet publish LeagueOfLegends.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
+ - dotnet publish LeagueOfLegendsCI.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release
- dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN}
secrets: [ SECRET_SONAR_LOGIN ]
settings:
diff --git a/.vs/LolProject/v17/.suo b/.vs/LolProject/v17/.suo
index fa82156..3708a4f 100644
Binary files a/.vs/LolProject/v17/.suo and b/.vs/LolProject/v17/.suo differ
diff --git a/.vs/LolProject/v17/.wsuo b/.vs/LolProject/v17/.wsuo
index 9ab157c..6a03c61 100644
Binary files a/.vs/LolProject/v17/.wsuo and b/.vs/LolProject/v17/.wsuo differ
diff --git a/README.md b/README.md
index 2ca56a5..652618a 100644
--- a/README.md
+++ b/README.md
@@ -21,12 +21,12 @@
-**Thème du projet** : Réalisation d'une API et d'un ORM (Entity Framework) qui seront reliés à une base de données dans le thème de League of Legends
+**Thème du projet** : Réalisation d'une API et d'un ORM (Entity Framework) qui seront reliés à une base de données (SQLite) dans le thème de League of Legends
-La racine de mon GitLab contient deux dossiers :open_file_folder: essentiels pour le projet :
+La racine de mon GitLab contient deux dossiers :open_file_folder: essentiels pour le projet :
[**src**](src) : **Toute la partie codage de l'application**
@@ -34,10 +34,12 @@ La racine de mon GitLab contient deux dossiers :open_file_folder: essentiels pou
👉 [**Solution de l'application**](src/EntityFramework_LoL/Sources/LeagueOfLegends.sln)
+👉 [**Solution de l'application pour la CI**](src/EntityFramework_LoL/Sources/LeagueOfLegendsCI.sln)
+
- ### Avancement du projet :construction_worker:
-Où en suis-je:grey_question::grey_exclamation: (:white_check_mark: réalisé, :warning: presque abouti, :x: non commencé )
+Où en suis-je :grey_question::grey_exclamation: (:white_check_mark: réalisé, :warning: presque abouti, :x: non commencé )
Côté API :
@@ -103,6 +105,8 @@ Grâce à l'injection de dépendances dans le projet, la Web API n'a pas besoin
La partie **bases de données** est gérée par le DbManager, qui utilise l'ORM Entity Framework (plus précisément le DbContext) pour récupérer les données dans la base de données. De plus, grâce à une factory :factory: (oui, comme celle de la web API), elle transforme les données en tables (appelées "Entities") en classes du modèle.
+Le client MAUI pourra effectuer des requêtes HTTP à l'API via l'API Manager, qui hérite de IDataManager et possède une liste de fonctions responsables d'exécuter les requêtes. De cette manière, le client n'aura pas besoin de connaître l'API pour interagir avec elle. :bulb:
+
- ### Comment récupérer le projet ?
@@ -187,6 +191,30 @@ réalisez à nouveau la migration (ou mettez à jour celle actuelle), puis suppr
+- ### Comment utiliser l'application MAUI ?
+
+Si vous préférez éviter la manipulation de l'API, vous pouvez également utiliser le **client MAUI**. Celui-ci contacte directement l'ApiManager, qui se charge des requêtes HTTP à l'API, et vous permet de visualiser et de modifier les données grâce à une interface graphique.
+
+Page **Home**:
+
+
+
+
+
+
+
+Page **Champions**:
+
+
+
+
+
+
+
+Vous pouvez vous amuser à filtrer les champions sur cette page, visualiser leurs skins, les modifier, et même en ajouter ! :grin:
+
+:information_source: *Pour utiliser cette application, vous devez avoir la dernière version de Visual Studio, avoir effectué la migration auparavant (comme indiqué ci-dessus), et avoir sélectionné la solution **LeagueOfLegends** plutôt que **LeagueOfLegendsCi**. Si vous avez besoin d'aide ou si vous souhaitez obtenir plus d'informations, vous pouvez contacter le technicien responsable de l'application (c'est-à-dire moi), en vous référant à mon mail ci-dessous. :email:*
+
Mon environnement de travail est basé sur un outil et un langage en particulier : 👇
@@ -206,7 +234,7 @@ Mon environnement de travail est basé sur un outil et un langage en particulier
-:mortar_board: Emre KARTAL
+:mortar_board: **Emre KARTAL** - *Emre.kartal@etu.uca.fr*
@@ -216,4 +244,9 @@ Mon environnement de travail est basé sur un outil et un langage en particulier
© PM2
-
\ No newline at end of file
+
+
+
+
+ Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International .
+
diff --git a/doc/Images/MauiClientChampions.gif b/doc/Images/MauiClientChampions.gif
new file mode 100644
index 0000000..819824e
Binary files /dev/null and b/doc/Images/MauiClientChampions.gif differ
diff --git a/doc/Images/MauiClientHome.png b/doc/Images/MauiClientHome.png
new file mode 100644
index 0000000..4812772
Binary files /dev/null and b/doc/Images/MauiClientHome.png differ
diff --git a/src/EntityFramework_LoL/Sources/ApiLol/ApiLol.csproj b/src/EntityFramework_LoL/Sources/ApiLol/ApiLol.csproj
index f765ca4..d01f0d6 100644
--- a/src/EntityFramework_LoL/Sources/ApiLol/ApiLol.csproj
+++ b/src/EntityFramework_LoL/Sources/ApiLol/ApiLol.csproj
@@ -17,6 +17,7 @@
+
diff --git a/src/EntityFramework_LoL/Sources/ApiLol/Controllers/v1/ChampionsController.cs b/src/EntityFramework_LoL/Sources/ApiLol/Controllers/v1/ChampionsController.cs
index f822be1..2125c70 100644
--- a/src/EntityFramework_LoL/Sources/ApiLol/Controllers/v1/ChampionsController.cs
+++ b/src/EntityFramework_LoL/Sources/ApiLol/Controllers/v1/ChampionsController.cs
@@ -61,9 +61,9 @@ namespace ApiLol.Controllers.v1
{
_logger.LogInformation("method {Action} - CHAMPION - V1.0 call with {name} and {item}", nameof(Put), name, champion);
- var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
+ var champs = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
- return Ok((await _manager.ChampionsMgr.UpdateItem(dtos.First(), champion.ToModel())).ToDto());
+ return Ok((await _manager.ChampionsMgr.UpdateItem(champs.First(), champion.ToModel())).ToDto());
}
@@ -87,9 +87,9 @@ namespace ApiLol.Controllers.v1
{
_logger.LogInformation("method {Action} - CHAMPION - V1.0 call with {name}", nameof(Delete), name);
- var dtos = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
+ var champs = (await _manager.ChampionsMgr.GetItemByName(name, 0, await _manager.ChampionsMgr.GetNbItems()));
- await _manager.ChampionsMgr.DeleteItem(dtos.First());
+ await _manager.ChampionsMgr.DeleteItem(champs.First());
return NoContent();
}
diff --git a/src/EntityFramework_LoL/Sources/ApiLol/Program.cs b/src/EntityFramework_LoL/Sources/ApiLol/Program.cs
index 98e6f6c..591bbb2 100644
--- a/src/EntityFramework_LoL/Sources/ApiLol/Program.cs
+++ b/src/EntityFramework_LoL/Sources/ApiLol/Program.cs
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Model;
-using StubLib;
var builder = WebApplication.CreateBuilder(args);
@@ -29,7 +28,7 @@ builder.Services.AddVersionedApiExplorer(setup =>
setup.SubstituteApiVersionInUrl = true;
});
-builder.Services.AddSingleton();
+builder.Services.AddSingleton();
var app = builder.Build();
diff --git a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Champions.cs b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Champions.cs
index 16a2328..005a45b 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Champions.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Champions.cs
@@ -1,6 +1,8 @@
-using Model;
+using DbManager.Mapper;
+using Microsoft.EntityFrameworkCore;
+using Model;
-namespace DbManager
+namespace DbLib
{
public partial class DbManager
{
@@ -11,94 +13,116 @@ namespace DbManager
public ChampionsManager(DbManager parent)
=> this.parent = parent;
- public Task AddItem(Champion? item)
+ public async Task AddItem(Champion? item)
{
- throw new NotImplementedException();
+ var champion = await parent.DbContext.Champions.AddAsync(item.ToEntity(parent.DbContext));
+ parent.DbContext.SaveChanges();
+ return champion.Entity.ToModel();
}
- public Task DeleteItem(Champion? item)
+ public async Task DeleteItem(Champion? item)
{
- throw new NotImplementedException();
+ var toDelete = parent.DbContext.Champions.Where(c => c.Name == item.Name).First();
+ if (toDelete != null)
+ {
+ parent.DbContext.Champions.Remove(toDelete);
+ parent.DbContext.SaveChanges();
+ return true;
+ }
+ return false;
}
- public Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
- public Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private Func filterByNameContains = (champ, substring) => champ.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByCharacteristic(string charName, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private Func filterByName = (champ, substring) => champ.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByClass(ChampionClass championClass, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(champ => filterByName(champ.ToModel(), substring), index, count, orderingPropertyName, descending)
+ .Select(c => c.ToModel());
- public Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
- public Task> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(
+ c => true,
+ index, count,
+ orderingPropertyName, descending).Select(c => c.ToModel());
- public Task> GetItemsBySkill(Skill? skill, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private Func filterByCharacteristic = (champ, charName) => champ.Characteristics.Keys.Any(k => k.Contains(charName, StringComparison.InvariantCultureIgnoreCase));
- public Task> GetItemsBySkill(string skill, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItemsByCharacteristic(string charName, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(
+ champ => filterByCharacteristic(champ.ToModel(), charName),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
- public Task GetNbItems()
- {
- throw new NotImplementedException();
- }
+ private Func filterByClass = (champ, championClass) => champ.Class == championClass;
+
+ public async Task> GetItemsByClass(ChampionClass championClass, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(
+ champ => filterByClass(champ.ToModel(), championClass),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(champ => filterByNameContains(champ.ToModel(), substring), index, count, orderingPropertyName, descending)
+ .Select(c => c.ToModel());
+
+ public async Task> GetItemsByRunePage(RunePage? runePage, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(
+ c => c.RunePages.Any(rp => rp.Equals(runePage.ToEntity(parent.DbContext))),
+ index, count,
+ orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsBySkill(Skill? skill, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(champ => filterBySkill(champ.ToModel(), skill), index, count, orderingPropertyName, descending)
+ .Select(c => c.ToModel());
+
+
+ public async Task> GetItemsBySkill(string skill, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Champions.Include(c => c.Skills).Include(c => c.Characteristics).Include(c => c.Skins).Include(c => c.Image).GetItemsWithFilterAndOrdering(champ => filterBySkillSubstring(champ.ToModel(), skill), index, count, orderingPropertyName, descending)
+ .Select(c => c.ToModel());
+
+ public async Task GetNbItems()
+ => parent.DbContext.Champions.Count();
public Task GetNbItemsByCharacteristic(string charName)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Champions.GetNbItemsWithFilter(champ => filterByCharacteristic(champ.ToModel(), charName));
- public Task GetNbItemsByClass(ChampionClass championClass)
- {
- throw new NotImplementedException();
- }
+ public async Task GetNbItemsByClass(ChampionClass championClass)
+ => parent.DbContext.Champions.Where(c => c.Class.Equals(championClass))
+ .Count();
- public Task GetNbItemsByName(string substring)
- {
- throw new NotImplementedException();
- }
+ public async Task GetNbItemsByName(string substring)
+ => parent.DbContext.Champions.Where(c => c.Name.Equals(substring))
+ .Count();
- public Task GetNbItemsByRunePage(RunePage? runePage)
- {
- throw new NotImplementedException();
- }
+ public async Task GetNbItemsByRunePage(RunePage? runePage)
+ => parent.DbContext.Champions.Where(c => c.RunePages.Any(rp => rp.Equals(runePage.ToEntity(parent.DbContext))))
+ .Count();
+
+
+ private Func filterBySkill = (champ, skill) => skill != null && champ.Skills.Contains(skill!);
public Task GetNbItemsBySkill(Skill? skill)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Champions.GetNbItemsWithFilter(champ => filterBySkill(champ.ToModel(), skill));
- public Task GetNbItemsBySkill(string skill)
- {
- throw new NotImplementedException();
- }
+ private static Func filterBySkillSubstring = (champ, skill) => champ.Skills.Any(s => s.Name.Contains(skill, StringComparison.InvariantCultureIgnoreCase));
- public Task UpdateItem(Champion? oldItem, Champion? newItem)
- {
- throw new NotImplementedException();
+ public Task GetNbItemsBySkill(string skill)
+ => parent.DbContext.Champions.GetNbItemsWithFilter(champ => filterBySkillSubstring(champ.ToModel(), skill));
+
+ public async Task UpdateItem(Champion? oldItem, Champion? newItem)
+ {
+ var toUpdate = parent.DbContext.Champions.FirstOrDefault(champ => champ.Name == oldItem.Name);
+ var newEntity = newItem.ToEntity(parent.DbContext);
+ toUpdate.Bio = newEntity.Bio;
+ toUpdate.Class = newEntity.Class;
+ toUpdate.Icon = newEntity.Icon;
+ toUpdate.Image = newEntity.Image;
+ toUpdate.Skins = newEntity.Skins;
+ toUpdate.Skills = newEntity.Skills;
+ toUpdate.Characteristics = newEntity.Characteristics;
+ parent.DbContext.SaveChanges();
+ return toUpdate?.ToModel();
}
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/DbManager.RunePages.cs b/src/EntityFramework_LoL/Sources/DbManager/DbManager.RunePages.cs
index d3b54d2..efdfc20 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/DbManager.RunePages.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/DbManager.RunePages.cs
@@ -1,11 +1,8 @@
-using Model;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DbManager
+using DbManager.Mapper;
+using Microsoft.EntityFrameworkCore;
+using Model;
+
+namespace DbLib
{
public partial class DbManager
{
@@ -16,64 +13,80 @@ namespace DbManager
public RunePagesManager(DbManager parent)
=> this.parent = parent;
- public Task AddItem(RunePage? item)
+ public async Task AddItem(RunePage? item)
{
- throw new NotImplementedException();
+ var RunePage = await parent.DbContext.RunePages.AddAsync(item.ToEntity(parent.DbContext));
+ parent.DbContext.SaveChanges();
+ return RunePage.Entity.ToModel(parent.DbContext);
}
- public Task DeleteItem(RunePage? item)
+ public async Task DeleteItem(RunePage? item)
{
- throw new NotImplementedException();
+ var toDelete = parent.DbContext.RunePages.Find(item.Name);
+ if (toDelete != null)
+ {
+ parent.DbContext.RunePages.Remove(toDelete);
+ parent.DbContext.SaveChanges();
+ return true;
+ }
+ return false;
}
- public Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByName
+ = (rp, substring) => rp.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByNameContains
+ = (rp, substring) => rp.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByChampion(Champion? champion, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByRune
+ = (rp, rune) => rune != null && rp.Runes.Values.Contains(rune!);
- public Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.RunePages.Include(rp => rp.Champions).Include(rp => rp.DictionaryCategoryRunes).GetItemsWithFilterAndOrdering(
+ rp => filterByName(rp.ToModel(parent.DbContext), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel(parent.DbContext));
- public Task> GetItemsByRune(Model.Rune? rune, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.RunePages.Include(rp => rp.Champions).Include(rp => rp.DictionaryCategoryRunes).GetItemsWithFilterAndOrdering(
+ rp => true,
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel(parent.DbContext));
+
+ public async Task> GetItemsByChampion(Champion? champion, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.RunePages.Include(rp => rp.Champions).Include(rp => rp.DictionaryCategoryRunes).GetItemsWithFilterAndOrdering(
+ rp => rp.Champions.Any(c => c.Name.Equals(champion.Name)),
+ index, count,
+ orderingPropertyName, descending).Select(rp => rp.ToModel(parent.DbContext));
+
+ public async Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.RunePages.Include(rp => rp.Champions).Include(rp => rp.DictionaryCategoryRunes).GetItemsWithFilterAndOrdering(
+ rp => filterByNameContains(rp.ToModel(parent.DbContext), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel(parent.DbContext));
+
+ public async Task> GetItemsByRune(Rune? rune, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.RunePages.Include(rp => rp.Champions).Include(rp => rp.DictionaryCategoryRunes).GetItemsWithFilterAndOrdering(
+ rp => filterByRune(rp.ToModel(parent.DbContext), rune),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel(parent.DbContext));
public Task GetNbItems()
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.RunePages.GetNbItemsWithFilter(
+ rp => true);
- public Task GetNbItemsByChampion(Champion? champion)
- {
- throw new NotImplementedException();
- }
+ public async Task GetNbItemsByChampion(Champion? champion)
+ => parent.DbContext.RunePages.Where(rp => rp.Champions.Any(c => c.Name.Equals(champion.Name))).Count();
- public Task GetNbItemsByName(string substring)
- {
- throw new NotImplementedException();
- }
- public Task GetNbItemsByRune(Model.Rune? rune)
- {
- throw new NotImplementedException();
- }
+ public async Task GetNbItemsByName(string substring)
+ => parent.DbContext.RunePages.Where(rp => rp.Name.Contains(substring)).Count();
+
+ public async Task GetNbItemsByRune(Rune? rune)
+ => parent.DbContext.RunePages.Where(rp => rp.DictionaryCategoryRunes.Any(r => r.RuneName.Equals(rune.Name))).Count();
- public Task UpdateItem(RunePage? oldItem, RunePage? newItem)
+ public async Task UpdateItem(RunePage? oldItem, RunePage? newItem)
{
- throw new NotImplementedException();
+ var toUpdate = parent.DbContext.RunePages.Find(oldItem.Name);
+ toUpdate.DictionaryCategoryRunes = newItem.ToEntity(parent.DbContext).DictionaryCategoryRunes;
+ parent.DbContext.SaveChanges();
+ return toUpdate.ToModel(parent.DbContext);
}
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Runes.cs b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Runes.cs
index ec2abfa..a40a901 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Runes.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Runes.cs
@@ -1,11 +1,7 @@
-using Model;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DbManager
+using DbManager.Mapper;
+using Model;
+
+namespace DbLib
{
public partial class DbManager
{
@@ -15,54 +11,77 @@ namespace DbManager
public RunesManager(DbManager parent)
=> this.parent = parent;
- public Task AddItem(Model.Rune? item)
+ public async Task AddItem(Rune? item)
{
- throw new NotImplementedException();
+ var rune = await parent.DbContext.Runes.AddAsync(item.ToEntity());
+ parent.DbContext.SaveChanges();
+ return rune.Entity.ToModel();
}
- public Task DeleteItem(Model.Rune? item)
+ public async Task DeleteItem(Rune? item)
{
- throw new NotImplementedException();
+ var toDelete = parent.DbContext.Runes.Find(item.Name);
+ if (toDelete != null)
+ {
+ parent.DbContext.Runes.Remove(toDelete);
+ parent.DbContext.SaveChanges();
+ return true;
+ }
+ return false;
}
- public Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByRuneFamily
+ = (rune, family) => rune.Family == family;
- public Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByName
+ = (rune, substring) => rune.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByFamily(RuneFamily family, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByNameContains
+ = (rune, substring) => rune.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Runes.GetItemsWithFilterAndOrdering(
+ rune => filterByName(rune.ToModel(), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Runes.GetItemsWithFilterAndOrdering(
+ r => true,
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsByFamily(RuneFamily family, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Runes.GetItemsWithFilterAndOrdering(
+ rune => filterByRuneFamily(rune.ToModel(), family),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Runes.GetItemsWithFilterAndOrdering(
+ rune => filterByNameContains(rune.ToModel(), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
public Task GetNbItems()
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Runes.GetNbItemsWithFilter(
+ rune => true);
public Task GetNbItemsByFamily(RuneFamily family)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Runes.GetNbItemsWithFilter(
+ rune => filterByRuneFamily(rune.ToModel(), family));
public Task GetNbItemsByName(string substring)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Runes.GetNbItemsWithFilter(
+ rune => filterByName(rune.ToModel(), substring));
- public Task UpdateItem(Model.Rune? oldItem, Model.Rune? newItem)
+ public async Task UpdateItem(Rune? oldItem, Rune? newItem)
{
- throw new NotImplementedException();
+ var toUpdate = parent.DbContext.Runes.Find(oldItem.Name);
+ var newEntity = newItem.ToEntity();
+ toUpdate.Description = newEntity.Description;
+ toUpdate.Icon = newEntity.Icon;
+ toUpdate.Family = newEntity.Family;
+ toUpdate.Image = newEntity.Image;
+
+ parent.DbContext.SaveChanges();
+ return toUpdate.ToModel();
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Skins.cs b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Skins.cs
index cb5ecc8..301a7e7 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/DbManager.Skins.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/DbManager.Skins.cs
@@ -1,11 +1,13 @@
-using Model;
+using DbManager.Mapper;
+using Microsoft.EntityFrameworkCore;
+using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace DbManager
+namespace DbLib
{
public partial class DbManager
{
@@ -16,54 +18,74 @@ namespace DbManager
public SkinsManager(DbManager parent)
=> this.parent = parent;
- public Task AddItem(Skin? item)
+ public async Task AddItem(Skin? item)
{
- throw new NotImplementedException();
+ var skin = await parent.DbContext.Skins.AddAsync(item.ToEntity(parent.DbContext));
+ parent.DbContext.SaveChanges();
+ return skin.Entity.ToModel();
}
- public Task DeleteItem(Skin? item)
+ public async Task DeleteItem(Skin? item)
{
- throw new NotImplementedException();
+ var toDelete = parent.DbContext.Skins.Find(item.Name);
+ if (toDelete != null)
+ {
+ parent.DbContext.Skins.Remove(toDelete);
+ parent.DbContext.SaveChanges();
+ return true;
+ }
+ return false;
}
- public Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByChampion = (skin, champion) => champion != null && skin.Champion.Equals(champion!);
- public Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByName = (skin, substring) => skin.Name.Equals(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByChampion(Champion? champion, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ private static Func filterByNameContains = (skin, substring) => skin.Name.Contains(substring, StringComparison.InvariantCultureIgnoreCase);
- public Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
- {
- throw new NotImplementedException();
- }
+ public async Task> GetItemByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Skins.Include(s => s.Champion).Include(s => s.Image).GetItemsWithFilterAndOrdering(
+ skin => filterByName(skin.ToModel(), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItems(int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Skins.Include(s => s.Champion).Include(s => s.Image).GetItemsWithFilterAndOrdering(
+ skin => true,
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsByChampion(Champion? champion, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Skins.Include(s => s.Champion).Include(s => s.Image).GetItemsWithFilterAndOrdering(
+ skin => filterByChampion(skin.ToModel(), champion),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
+
+ public async Task> GetItemsByName(string substring, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ => parent.DbContext.Skins.Include(s => s.Champion).Include(s => s.Image).GetItemsWithFilterAndOrdering(
+ skin => filterByNameContains(skin.ToModel(), substring),
+ index, count, orderingPropertyName, descending).Select(c => c.ToModel());
public Task GetNbItems()
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Skins.GetNbItemsWithFilter(
+ c => true);
public Task GetNbItemsByChampion(Champion? champion)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Skins.GetNbItemsWithFilter(
+ skin => filterByChampion(skin.ToModel(), champion));
public Task GetNbItemsByName(string substring)
- {
- throw new NotImplementedException();
- }
+ => parent.DbContext.Skins.GetNbItemsWithFilter(
+ skin => filterByName(skin.ToModel(), substring));
- public Task UpdateItem(Skin? oldItem, Skin? newItem)
+ public async Task UpdateItem(Skin? oldItem, Skin? newItem)
{
- throw new NotImplementedException();
+ var toUpdate = parent.DbContext.Skins.Find(oldItem.Name);
+ var newEntity = newItem.ToEntity(parent.DbContext);
+ toUpdate.Description = newEntity.Description;
+ toUpdate.Icon = newEntity.Icon;
+ toUpdate.Price = newEntity.Price;
+ toUpdate.Champion = newEntity.Champion;
+ toUpdate.Image = newEntity.Image;
+ parent.DbContext.SaveChanges();
+ return toUpdate.ToModel();
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/DbManager.cs b/src/EntityFramework_LoL/Sources/DbManager/DbManager.cs
index 33fae54..8ad6f6b 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/DbManager.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/DbManager.cs
@@ -1,12 +1,22 @@
-using Model;
+using Microsoft.EntityFrameworkCore;
+using Model;
using MyFlib;
-namespace DbManager
+namespace DbLib
{
public partial class DbManager : IDataManager
{
protected LolDbContext DbContext { get; set; }
+ public DbManager()
+ {
+ DbContext = new LolDbContext();
+ ChampionsMgr = new ChampionsManager(this);
+ SkinsMgr = new SkinsManager(this);
+ RunesMgr = new RunesManager(this);
+ RunePagesMgr = new RunePagesManager(this);
+ }
+
public DbManager(LolDbContext dbContext)
{
DbContext = dbContext;
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Extensions.cs b/src/EntityFramework_LoL/Sources/DbManager/Extensions.cs
new file mode 100644
index 0000000..239fae0
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/DbManager/Extensions.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DbLib
+{
+ static class Extensions
+ {
+ internal static IEnumerable GetItemsWithFilterAndOrdering(this IEnumerable collection,
+ Func filter, int index, int count, string? orderingPropertyName = null, bool descending = false)
+ {
+ IEnumerable temp = collection;
+ temp = temp.Where(item => filter(item));
+ if (orderingPropertyName != null)
+ {
+ var prop = typeof(T).GetProperty(orderingPropertyName!);
+ if (prop != null)
+ {
+ temp = descending ? temp.OrderByDescending(item => prop.GetValue(item))
+ : temp.OrderBy(item => prop.GetValue(item));
+ }
+ }
+ return temp.Skip(index * count).Take(count);
+ }
+
+ internal static Task GetNbItemsWithFilter(this IEnumerable collection, Func filter)
+ {
+ return Task.FromResult(collection.Count(item => filter(item)));
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/ChampionMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/ChampionMapper.cs
index 454bc54..71755f5 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/Mapper/ChampionMapper.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/ChampionMapper.cs
@@ -8,14 +8,21 @@ namespace DbManager.Mapper
{
public static Champion ToModel(this ChampionEntity championEntity)
{
- Champion champion = new (championEntity.Name, championEntity.Class.ToModel(), championEntity.Icon, championEntity.Image.Base64.ToString(), championEntity.Bio);
+ Champion champion = new (championEntity.Name, championEntity.Class.ToModel(), championEntity.Icon, championEntity.Image.Base64, championEntity.Bio);
foreach (var skill in championEntity.Skills)
{
champion.AddSkill(skill.ToModel());
}
foreach (var skin in championEntity.Skins)
{
- champion.AddSkin(skin.ToModel());
+ champion.AddSkin(new Skin(skin.Name, champion, skin.Price, skin.Icon, skin.Image.Base64, skin.Description));
+ }
+ if (championEntity.Characteristics != null)
+ {
+ foreach (var c in championEntity.Characteristics)
+ {
+ champion.AddCharacteristics(c.ToModel());
+ }
}
return champion;
}
@@ -31,12 +38,13 @@ namespace DbManager.Mapper
};
foreach (var skill in champion.Skills)
{
- champ.Skills.Add(skill.ToEntity(champ));
+ champ.Skills.Add(skill.ToEntity(champ, context));
}
foreach (var skin in champion.Skins)
{
champ.Skins.Add(skin.ToEntity(context));
}
+ champ.Characteristics = champion.Characteristics.Select(x => x.ToEntity(champ, context)).ToList();
return champ;
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/CharacteristicMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/CharacteristicMapper.cs
new file mode 100644
index 0000000..b99ee71
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/CharacteristicMapper.cs
@@ -0,0 +1,27 @@
+using MyFlib.Entities;
+using MyFlib;
+
+namespace DbManager.Mapper
+{
+ public static class CharacteristicMapper
+ {
+ public static CharacteristicEntity ToEntity(this KeyValuePair item, ChampionEntity champion, LolDbContext context)
+ {
+ var characteristicEntity = context.Characteristic.Find(item.Key, champion.Id);
+ if (characteristicEntity == null)
+ {
+ return new()
+ {
+ Name = item.Key,
+ Value = item.Value,
+ ChampionForeignKey = champion.Id
+ };
+ }
+ return characteristicEntity;
+ }
+
+
+ public static Tuple ToModel(this CharacteristicEntity entity)
+ => new(entity.Name, entity.Value);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/RuneMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/RuneMapper.cs
index 788ce1e..744c73f 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/Mapper/RuneMapper.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/RuneMapper.cs
@@ -6,7 +6,7 @@ namespace DbManager.Mapper
{
public static class RuneMapper
{
- public static Rune ToModel(this RuneEntity rune) => new(rune.Name, rune.Family.ToModel(), rune.Icon, rune.Image.Base64, rune.Description);
+ public static Rune ToModel(this RuneEntity rune) => new(rune.Name, rune.Family.ToModel(), rune.Icon, "", rune.Description);
public static RuneEntity ToEntity(this Rune rune)
=> new()
{
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/RunePageMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/RunePageMapper.cs
index 839ba0e..d485243 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/Mapper/RunePageMapper.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/RunePageMapper.cs
@@ -20,5 +20,29 @@ namespace DbManager.Mapper
}
return runePage;
}
+
+ public static RunePageEntity ToEntity(this RunePage runePage, LolDbContext context)
+ {
+ RunePageEntity? runePageEntity = context.RunePages.Find(runePage.Name);
+ if (runePageEntity == null)
+ {
+ runePageEntity = new()
+ {
+ Name = runePage.Name,
+ };
+
+ runePageEntity.DictionaryCategoryRunes = new List();
+ foreach (var r in runePage.Runes)
+ {
+ runePageEntity.DictionaryCategoryRunes.Add(new DictionaryCategoryRune()
+ {
+ category = r.Key.ToEntity(),
+ rune = r.Value.ToEntity(),
+ });
+ }
+
+ }
+ return runePageEntity;
+ }
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkillMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkillMapper.cs
index 9e8b636..f2c185c 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkillMapper.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkillMapper.cs
@@ -8,16 +8,20 @@ namespace DbManager.Mapper
{
public static Skill ToModel(this SkillEntity skillEntity) => new(skillEntity.Name, skillEntity.Type.ToModel(), skillEntity.Description);
-
- public static SkillEntity ToEntity(this Skill skill, ChampionEntity championEntity)
+ public static SkillEntity ToEntity(this Skill skill, ChampionEntity championEntity, LolDbContext context)
{
- return new()
+ var skillSearch = context.Skills.Find(skill.Name);
+ if (skillSearch == null)
{
- Name = skill.Name,
- Description = skill.Description,
- Type = skill.Type.ToEntity(),
- Champion = championEntity
- };
+ return new()
+ {
+ Name = skill.Name,
+ Description = skill.Description,
+ Type = skill.Type.ToEntity(),
+ Champion = championEntity
+ };
+ }
+ throw new Exception("Skill was already exist");
}
}
diff --git a/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkinMapper.cs b/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkinMapper.cs
index 391891f..5edde49 100644
--- a/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkinMapper.cs
+++ b/src/EntityFramework_LoL/Sources/DbManager/Mapper/SkinMapper.cs
@@ -9,14 +9,21 @@ namespace DbManager.Mapper
=> new(skinEntity.Name, skinEntity.Champion.ToModel(), skinEntity.Price, skinEntity.Icon, skinEntity.Image.Base64, skinEntity.Description);
public static SkinEntity ToEntity(this Skin skin, LolDbContext context)
- => new()
+ {
+ var skinSearch = context.Skins.Find(skin.Name);
+ if(skinSearch == null)
{
- Name = skin.Name,
- Description = skin.Description,
- Icon = skin.Icon,
- Price = skin.Price,
- Champion = context.Champions.Find(skin.Champion.Name),
- Image = skin.Image.ToEntity()
- };
+ return new()
+ {
+ Name = skin.Name,
+ Description = skin.Description,
+ Icon = skin.Icon,
+ Price = skin.Price,
+ Champion = context.Champions.FirstOrDefault(c => c.Name == skin.Champion.Name),
+ Image = skin.Image.ToEntity()
+ };
+ }
+ throw new Exception("Skin was already exist");
+ }
}
}
diff --git a/src/EntityFramework_LoL/Sources/LeagueOfLegends.sln b/src/EntityFramework_LoL/Sources/LeagueOfLegends.sln
index e0e137e..4256fc6 100644
--- a/src/EntityFramework_LoL/Sources/LeagueOfLegends.sln
+++ b/src/EntityFramework_LoL/Sources/LeagueOfLegends.sln
@@ -27,7 +27,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyFlib", "MyFlib\MyFlib.csp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UT_EF", "Tests\UT_EF\UT_EF.csproj", "{F896C30B-A6FE-42B2-BAC8-08360BC48DC6}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DbManager", "DbManager\DbManager.csproj", "{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbManager", "DbManager\DbManager.csproj", "{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LolApp", "LolApp\LolApp.csproj", "{0C898A04-092A-49AA-BE65-8AE818A2AF50}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ViewModels", "ViewModels\ViewModels.csproj", "{65135247-E1AB-4EE4-9473-DFDE6AFCC250}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -79,6 +83,16 @@ Global
{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {65135247-E1AB-4EE4-9473-DFDE6AFCC250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {65135247-E1AB-4EE4-9473-DFDE6AFCC250}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {65135247-E1AB-4EE4-9473-DFDE6AFCC250}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {65135247-E1AB-4EE4-9473-DFDE6AFCC250}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/EntityFramework_LoL/Sources/LeagueOfLegendsCI.sln b/src/EntityFramework_LoL/Sources/LeagueOfLegendsCI.sln
new file mode 100644
index 0000000..51c7876
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LeagueOfLegendsCI.sln
@@ -0,0 +1,95 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32616.157
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Model", "Model\Model.csproj", "{2960F9BA-49DE-494D-92E3-CE5A794BA1A9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C76D0C23-1FFA-4963-93CD-E12BD643F030}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleTests", "Tests\ConsoleTests\ConsoleTests.csproj", "{1889FA6E-B7C6-416E-8628-9449FB9070B9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{3B720C0C-53FE-4642-A2DB-87FD8634CD74}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stub", "Stub", "{2C607793-B163-4731-A4D1-AFE8A7C4C170}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StubLib", "StubLib\StubLib.csproj", "{B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiLol", "ApiLol\ApiLol.csproj", "{D59C9C7B-9BC2-4601-959D-BFA97E46D017}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DTO", "DTO\DTO.csproj", "{3919E408-EB12-4422-989B-C6ED4816D465}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTests", "Tests\ApiTests\ApiTests.csproj", "{1779D8A4-2E12-47F3-BDA2-2E7F04B758EB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{464DAB04-BE65-429D-9A39-3E1BB43C521A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyFlib", "MyFlib\MyFlib.csproj", "{2142AB69-B483-4B0A-96DC-CFA87DEB11A5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UT_EF", "Tests\UT_EF\UT_EF.csproj", "{F896C30B-A6FE-42B2-BAC8-08360BC48DC6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DbManager", "DbManager\DbManager.csproj", "{71DDCC06-D993-47B0-92E3-5DD6E295FB8B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2960F9BA-49DE-494D-92E3-CE5A794BA1A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1889FA6E-B7C6-416E-8628-9449FB9070B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B720C0C-53FE-4642-A2DB-87FD8634CD74}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D59C9C7B-9BC2-4601-959D-BFA97E46D017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D59C9C7B-9BC2-4601-959D-BFA97E46D017}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D59C9C7B-9BC2-4601-959D-BFA97E46D017}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D59C9C7B-9BC2-4601-959D-BFA97E46D017}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3919E408-EB12-4422-989B-C6ED4816D465}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3919E408-EB12-4422-989B-C6ED4816D465}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3919E408-EB12-4422-989B-C6ED4816D465}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3919E408-EB12-4422-989B-C6ED4816D465}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1779D8A4-2E12-47F3-BDA2-2E7F04B758EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1779D8A4-2E12-47F3-BDA2-2E7F04B758EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1779D8A4-2E12-47F3-BDA2-2E7F04B758EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1779D8A4-2E12-47F3-BDA2-2E7F04B758EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {464DAB04-BE65-429D-9A39-3E1BB43C521A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {464DAB04-BE65-429D-9A39-3E1BB43C521A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {464DAB04-BE65-429D-9A39-3E1BB43C521A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {464DAB04-BE65-429D-9A39-3E1BB43C521A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2142AB69-B483-4B0A-96DC-CFA87DEB11A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2142AB69-B483-4B0A-96DC-CFA87DEB11A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2142AB69-B483-4B0A-96DC-CFA87DEB11A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2142AB69-B483-4B0A-96DC-CFA87DEB11A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F896C30B-A6FE-42B2-BAC8-08360BC48DC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F896C30B-A6FE-42B2-BAC8-08360BC48DC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F896C30B-A6FE-42B2-BAC8-08360BC48DC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F896C30B-A6FE-42B2-BAC8-08360BC48DC6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71DDCC06-D993-47B0-92E3-5DD6E295FB8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {1889FA6E-B7C6-416E-8628-9449FB9070B9} = {C76D0C23-1FFA-4963-93CD-E12BD643F030}
+ {B01D7EF2-2D64-409A-A29A-61FB7BB7A9DB} = {2C607793-B163-4731-A4D1-AFE8A7C4C170}
+ {1779D8A4-2E12-47F3-BDA2-2E7F04B758EB} = {C76D0C23-1FFA-4963-93CD-E12BD643F030}
+ {F896C30B-A6FE-42B2-BAC8-08360BC48DC6} = {C76D0C23-1FFA-4963-93CD-E12BD643F030}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {92F3083D-793F-4552-8A9A-0AD6534159C9}
+ EndGlobalSection
+EndGlobal
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml
new file mode 100644
index 0000000..7f38acb
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml.cs
new file mode 100644
index 0000000..8388605
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddChampionPage.xaml.cs
@@ -0,0 +1,13 @@
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class AddChampionPage : ContentPage
+{
+ public AddChampionPage(ChampionsMgrVM championsMgrVM, ChampionVM champion = null)
+ {
+ InitializeComponent();
+ BindingContext = new AddChampionPageVM(championsMgrVM, champion);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml
new file mode 100644
index 0000000..20071b4
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml.cs
new file mode 100644
index 0000000..8c94ec0
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddOrEditSkinPage.xaml.cs
@@ -0,0 +1,24 @@
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class AddOrEditSkinPage : ContentPage
+{
+ AddOrEditSkinPage()
+ {
+ InitializeComponent();
+ }
+
+ public AddOrEditSkinPage(SkinsMgrVM skinsMgrVM, SkinVM skin)
+ :this()
+ {
+ BindingContext = new AddOrEditSkinPageVM(skinsMgrVM, skin);
+ }
+
+ public AddOrEditSkinPage(SkinsMgrVM skinsMgrVM, ChampionVM champion)
+ :this()
+ {
+ BindingContext = new AddOrEditSkinPageVM(skinsMgrVM, champion);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml b/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml
new file mode 100644
index 0000000..b6f9583
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml.cs
new file mode 100644
index 0000000..b164003
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AddSkill.xaml.cs
@@ -0,0 +1,13 @@
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class AddSkill : ContentPage
+{
+ public AddSkill(EditableChampionVM champion)
+ {
+ InitializeComponent();
+ BindingContext = new AddSkillVM(champion);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/App.xaml b/src/EntityFramework_LoL/Sources/LolApp/App.xaml
new file mode 100644
index 0000000..cdae088
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/App.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/App.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/App.xaml.cs
new file mode 100644
index 0000000..276b46e
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/App.xaml.cs
@@ -0,0 +1,12 @@
+namespace LolApp;
+
+public partial class App : Application
+{
+ public App()
+ {
+ InitializeComponent();
+
+ MainPage = new AppShell();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml b/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml
new file mode 100644
index 0000000..a71d8ca
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml.cs
new file mode 100644
index 0000000..bc552b6
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/AppShell.xaml.cs
@@ -0,0 +1,10 @@
+namespace LolApp;
+
+public partial class AppShell : Shell
+{
+ public AppShell()
+ {
+ InitializeComponent();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml
new file mode 100644
index 0000000..b0d85f5
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 120
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml.cs
new file mode 100644
index 0000000..411e629
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ChampionPage.xaml.cs
@@ -0,0 +1,31 @@
+using CommunityToolkit.Maui.Behaviors;
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class ChampionPage : ContentPage
+{
+ public ApplicationVM AppVM { get; set; }
+ public ChampionVM Champion { get; }
+
+ public ChampionPage(ChampionVM cvm, ApplicationVM appVM)
+ {
+ AppVM = appVM;
+ BindingContext = Champion = cvm;
+
+ InitializeComponent();
+ }
+
+ void imgClass_PropertyChanged(System.Object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ Image img = sender as Image;
+ if(e.PropertyName == "Source" && img != null && img.Behaviors.Any(b => b is IconTintColorBehavior))
+ {
+ var beh = (img.Behaviors.First(b => b is IconTintColorBehavior) as IconTintColorBehavior);
+ var color = beh.TintColor;
+ img.Behaviors.Remove(beh);
+ img.Behaviors.Add(new IconTintColorBehavior() { TintColor = color});
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml
new file mode 100644
index 0000000..4e8b2c9
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml.cs
new file mode 100644
index 0000000..6aa38a7
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ChampionsPage.xaml.cs
@@ -0,0 +1,17 @@
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class ChampionsPage : ContentPage
+{
+ public ApplicationVM AppVM { get; }
+ public ChampionsPageVM VM { get; }
+ public ChampionsPage(ApplicationVM appVM)
+ {
+ InitializeComponent();
+ AppVM = appVM;
+ VM = new ChampionsPageVM(AppVM.ChampionsMgrVM);
+ BindingContext = this;
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml
new file mode 100644
index 0000000..6dc66e4
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml
@@ -0,0 +1,131 @@
+
+
+
+
+ Assassin
+ Fighter
+ Mage
+ Marksman
+ Support
+ Tank
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs
new file mode 100644
index 0000000..74fb508
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/ChampionClassSelector.xaml.cs
@@ -0,0 +1,34 @@
+using Model;
+
+namespace LolApp.ContentViews;
+
+public partial class ChampionClassSelector : ContentView
+{
+ public ChampionClassSelector()
+ {
+ InitializeComponent();
+ }
+
+ public static readonly BindableProperty SelectedValueProperty = BindableProperty.Create(nameof(SelectedValue), typeof(ChampionClass), typeof(ChampionClassSelector), ChampionClass.Unknown, BindingMode.TwoWay);
+ public ChampionClass SelectedValue
+ {
+ get => (ChampionClass)GetValue(SelectedValueProperty);
+ set => SetValue(SelectedValueProperty, value);
+ }
+
+ public static readonly BindableProperty CheckedColorProperty = BindableProperty.Create(nameof(CheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon);
+
+ public Color CheckedColor
+ {
+ get => (Color)GetValue(CheckedColorProperty);
+ set => SetValue(CheckedColorProperty, value);
+ }
+
+ public static readonly BindableProperty UncheckedColorProperty = BindableProperty.Create(nameof(UncheckedColor), typeof(Color), typeof(ChampionClassSelector), Colors.DarkSalmon);
+
+ public Color UncheckedColor
+ {
+ get => (Color)GetValue(UncheckedColorProperty);
+ set => SetValue(UncheckedColorProperty, value);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ContentViews/SearchByStringView.cs b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/SearchByStringView.cs
new file mode 100644
index 0000000..308ce0d
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ContentViews/SearchByStringView.cs
@@ -0,0 +1,38 @@
+using System.Windows.Input;
+
+namespace LolApp.ContentViews;
+
+public class SearchByStringView : ContentView
+{
+ public static readonly BindableProperty PlaceHolderProperty = BindableProperty.Create(nameof(PlaceHolder), typeof(string), typeof(SearchByStringView), string.Empty);
+
+ public string PlaceHolder
+ {
+ get => (string)GetValue(PlaceHolderProperty);
+ set => SetValue(PlaceHolderProperty, value);
+ }
+
+ public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(SearchByStringView), string.Empty);
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+ set => SetValue(TextProperty, value);
+ }
+
+ public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(SearchByStringView), null);
+
+ public ICommand Command
+ {
+ get => (ICommand)GetValue(CommandProperty);
+ set => SetValue(CommandProperty, value);
+ }
+
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(SearchByStringView), null);
+
+ public object CommandParameter
+ {
+ get => GetValue(CommandParameterProperty);
+ set => SetValue(CommandParameterProperty, value);
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/LolApp.csproj b/src/EntityFramework_LoL/Sources/LolApp/LolApp.csproj
new file mode 100644
index 0000000..ab4fa0c
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/LolApp.csproj
@@ -0,0 +1,99 @@
+
+
+
+ net7.0-android;net7.0-ios;net7.0-maccatalyst
+ Exe
+ LolApp
+ true
+ true
+ enable
+
+
+ LolApp
+
+
+ fr.uca.iut.lolapp
+ d3cd18a9-c614-4933-bd36-3008e72004d5
+
+
+ 1.0
+ 1
+
+ 14.2
+ 14.0
+ 21.0
+ 10.0.17763.0
+ 10.0.17763.0
+ 6.5
+ {0C898A04-092A-49AA-BE65-8AE818A2AF50}
+
+
+
+ false
+ appleIUT_TP2022
+ iPhone Developer: Cedric BOUHOURS (M2E3ZQNZ3K)
+
+
+ false
+ Developer ID Application
+ 3rd Party Mac Developer Installer
+
+
+ false
+
+
+ $(TargetFrameworks);net7.0-windows10.0.22621.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml
new file mode 100644
index 0000000..9db8163
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml.cs
new file mode 100644
index 0000000..0750b67
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/MainPage.xaml.cs
@@ -0,0 +1,11 @@
+namespace LolApp;
+
+public partial class MainPage : ContentPage
+{
+ public MainPage()
+ {
+ InitializeComponent();
+ }
+}
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/MauiProgram.cs b/src/EntityFramework_LoL/Sources/LolApp/MauiProgram.cs
new file mode 100644
index 0000000..c12deff
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/MauiProgram.cs
@@ -0,0 +1,39 @@
+using CommunityToolkit.Maui;
+using LolApp.ViewModels;
+using Microsoft.Extensions.Logging;
+using Microsoft.Maui.Handlers;
+using Microsoft.Maui.Platform;
+using Model;
+using StubLib;
+using ViewModels;
+
+namespace LolApp;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .UseMauiCommunityToolkit()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ fonts.AddFont("Font Awesome 6 Free-Solid-900.otf", "FASolid");
+ });
+ builder.Services.AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton();
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/AndroidManifest.xml b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 0000000..e6c8a36
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainActivity.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainActivity.cs
new file mode 100644
index 0000000..016887c
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainActivity.cs
@@ -0,0 +1,11 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+
+namespace LolApp;
+
+[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
+public class MainActivity : MauiAppCompatActivity
+{
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainApplication.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainApplication.cs
new file mode 100644
index 0000000..95e1d92
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/MainApplication.cs
@@ -0,0 +1,16 @@
+using Android.App;
+using Android.Runtime;
+
+namespace LolApp;
+
+[Application]
+public class MainApplication : MauiApplication
+{
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/Resources/values/colors.xml b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 0000000..c2794f7
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,7 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 0000000..d5d15a5
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace LolApp;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Info.plist b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 0000000..ec44095
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,36 @@
+
+
+
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+ NSCameraUsageDescription
+ New Entry
+ NSPhotoLibraryUsageDescription
+ New Entry
+ NSPhotoLibraryAddUsageDescription
+ New Entry
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Program.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 0000000..f1b8f29
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace LolApp;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/Main.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/Main.cs
new file mode 100644
index 0000000..d58b3d9
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/Main.cs
@@ -0,0 +1,17 @@
+using System;
+using Microsoft.Maui;
+using Microsoft.Maui.Hosting;
+
+namespace LolApp;
+
+class Program : MauiApplication
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml
new file mode 100644
index 0000000..109d29f
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Tizen/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ maui-application-title-placeholder
+ maui-appicon-placeholder
+
+
+
+
+ http://tizen.org/privilege/internet
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml
new file mode 100644
index 0000000..23c64b9
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml.cs
new file mode 100644
index 0000000..c3b0669
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,25 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace LolApp.WinUI;
+
+///
+/// Provides application-specific behavior to supplement the default Application class.
+///
+public partial class App : MauiWinUIApplication
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/Package.appxmanifest b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 0000000..52b7801
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/app.manifest b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/app.manifest
new file mode 100644
index 0000000..91a1b32
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/Windows/app.manifest
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/AppDelegate.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 0000000..d5d15a5
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace LolApp;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Info.plist b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Info.plist
new file mode 100644
index 0000000..352a326
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Info.plist
@@ -0,0 +1,38 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+ NSCameraUsageDescription
+ New Entry
+ NSPhotoLibraryUsageDescription
+ Pour accéder aux images...
+ NSPhotoLibraryAddUsageDescription
+ Pour accéder aux images...
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Program.cs b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Program.cs
new file mode 100644
index 0000000..f1b8f29
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Platforms/iOS/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace LolApp;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Properties/launchSettings.json b/src/EntityFramework_LoL/Sources/LolApp/Properties/launchSettings.json
new file mode 100644
index 0000000..90f92d9
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "MsixPackage",
+ "nativeDebugging": false
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appicon.png b/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appicon.png
new file mode 100644
index 0000000..8263b46
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appicon.png differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appiconfg.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 0000000..e9b7139
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs
new file mode 100644
index 0000000..e258576
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/Base64ToImageSourceConverter.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using CommunityToolkit.Maui.Converters;
+
+namespace LolApp.Resources.Converters
+{
+ public class Base64ToImageSourceConverter : ByteArrayToImageSourceConverter, IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ string base64 = value as string;
+ if (string.IsNullOrWhiteSpace(base64)) return null;
+ try
+ {
+ byte[] bytes = System.Convert.FromBase64String(base64);
+ return base.ConvertFrom(bytes, culture);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ ImageSource source = value as ImageSource;
+ if (source == null) return null;
+ byte[] bytes = base.ConvertBackTo(source, culture) as byte[];
+ return System.Convert.ToBase64String(bytes);
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs
new file mode 100644
index 0000000..946b9a6
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ChampionClassToIconConverter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Globalization;
+using Model;
+
+namespace LolApp.Resources.Converters
+{
+ public class ChampionClassToIconConverter : IValueConverter
+ {
+ private static Dictionary icons = new()
+ {
+ [ChampionClass.Assassin] = "assassin.png",
+ [ChampionClass.Fighter] = "fighter.png",
+ [ChampionClass.Mage] = "mage.png",
+ [ChampionClass.Marksman] = "marksman.png",
+ [ChampionClass.Support] = "support.png",
+ [ChampionClass.Tank] = "tank.png"
+ };
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ ChampionClass champClass = (ChampionClass)value;
+ if(!icons.TryGetValue(champClass, out string icon))
+ {
+ return "";
+ }
+ return ImageSource.FromFile($"{icon}");
+ }
+ catch
+ {
+ return "";
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs
new file mode 100644
index 0000000..a3e0b7e
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/ImageRatioConverter.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Globalization;
+
+namespace LolApp.Resources.Converters
+{
+ public class ImageRatioConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ try
+ {
+ double parentWidth = (double)value;
+ double ratio = (double)parameter;
+ return parentWidth*ratio;
+ }
+ catch
+ {
+ return 0.0;
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/PlusOneConverter.cs b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/PlusOneConverter.cs
new file mode 100644
index 0000000..2d9eaec
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Converters/PlusOneConverter.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Globalization;
+
+namespace LolApp.Resources.Converters
+{
+ public class PlusOneConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ int i = -1;
+ try
+ {
+ i = (int)value;
+ }
+ catch (InvalidCastException e)
+ {
+ throw new InvalidCastException("PlusOneConverter : the value must be an int");
+ }
+ return i + 1;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf
new file mode 100644
index 0000000..f1d88fc
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/Font Awesome 6 Free-Solid-900.otf differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000..a49f11d
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Regular.ttf differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 0000000..23911e4
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Fonts/OpenSans-Semibold.ttf differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/assassin.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/assassin.svg
new file mode 100644
index 0000000..fb86680
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/assassin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/fighter.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/fighter.svg
new file mode 100644
index 0000000..42cb7df
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/fighter.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lol.png b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lol.png
new file mode 100644
index 0000000..10a552c
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lol.png differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lollogo.jpg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lollogo.jpg
new file mode 100644
index 0000000..a1b82b5
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/lollogo.jpg differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/mage.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/mage.svg
new file mode 100644
index 0000000..45d627b
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/mage.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/marksman.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/marksman.svg
new file mode 100644
index 0000000..f91066f
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/marksman.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/rp.png b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/rp.png
new file mode 100644
index 0000000..e025310
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/rp.png differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/support.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/support.svg
new file mode 100644
index 0000000..2d1f053
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/support.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/sword.png b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/sword.png
new file mode 100644
index 0000000..fb87c07
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/sword.png differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/tank.svg b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/tank.svg
new file mode 100644
index 0000000..2ec01a3
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Images/tank.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Raw/AboutAssets.txt b/src/EntityFramework_LoL/Sources/LolApp/Resources/Raw/AboutAssets.txt
new file mode 100644
index 0000000..808d6d3
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,17 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with you package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Splash/splash.png b/src/EntityFramework_LoL/Sources/LolApp/Resources/Splash/splash.png
new file mode 100644
index 0000000..e89e1c2
Binary files /dev/null and b/src/EntityFramework_LoL/Sources/LolApp/Resources/Splash/splash.png differ
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Colors.xaml b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Colors.xaml
new file mode 100644
index 0000000..286775e
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Colors.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+ #D2B977
+ #F0E7B7
+ #2B0B98
+ White
+ Black
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #F7B548
+ #FFD590
+ #FFE5B9
+ #28C2D1
+ #7BDDEF
+ #C3F2F4
+ #3E8EED
+ #72ACF1
+ #A7CBF6
+
+ Transparent
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml
new file mode 100644
index 0000000..a53b993
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/FontAwesomeGlyphs.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+ +
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/MyStyles.xaml b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/MyStyles.xaml
new file mode 100644
index 0000000..b988753
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/MyStyles.xaml
@@ -0,0 +1,102 @@
+
+
+
+
+ 0.59
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Styles.xaml b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Styles.xaml
new file mode 100644
index 0000000..d23a11d
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/Resources/Styles/Styles.xaml
@@ -0,0 +1,406 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml b/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml
new file mode 100644
index 0000000..0b082ab
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml.cs b/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml.cs
new file mode 100644
index 0000000..f4ac283
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/SkinPage.xaml.cs
@@ -0,0 +1,18 @@
+using LolApp.ViewModels;
+using ViewModels;
+
+namespace LolApp;
+
+public partial class SkinPage : ContentPage
+{
+ public ApplicationVM AppVM { get; set; }
+ public SkinVM SkinVM { get; }
+
+ public SkinPage(SkinVM svm, ApplicationVM appVM)
+ {
+ BindingContext = SkinVM = svm;
+ AppVM = appVM;
+
+ InitializeComponent();
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddChampionPageVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddChampionPageVM.cs
new file mode 100644
index 0000000..31fb1e3
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddChampionPageVM.cs
@@ -0,0 +1,80 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+//using Microsoft.Maui.Graphics.Platform;
+using ViewModels;
+
+namespace LolApp.ViewModels
+{
+ [ObservableObject]
+ public partial class AddChampionPageVM
+ {
+ ChampionsMgrVM ChampionsMgrVM { get; }
+
+ public AddChampionPageVM(ChampionsMgrVM championsMgrVM, ChampionVM champion = null)
+ {
+ ChampionsMgrVM = championsMgrVM;
+ if(champion == null) return;
+
+ oldChampion = champion;
+ IsNew = false;
+ this.champion = new EditableChampionVM(oldChampion);
+ }
+
+ private ChampionVM oldChampion;
+
+ [ObservableProperty]
+ bool isNew = true;
+
+ [ObservableProperty]
+ EditableChampionVM champion = new ();
+
+ [RelayCommand]
+ public async void PickIcon() => Champion.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42);
+
+ [RelayCommand]
+ public async void PickLargeImage() => Champion.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000);
+
+ [RelayCommand]
+ async Task Cancel()
+ => await App.Current.MainPage.Navigation.PopAsync();
+
+ [RelayCommand]
+ async Task AddChampion()
+ {
+ ChampionVM champVM = Champion.ToChampionVM();
+ await ChampionsMgrVM.AddChampion(champVM);
+ await App.Current.MainPage.Navigation.PopAsync();
+ }
+
+ [RelayCommand]
+ async Task EditChampion()
+ {
+ ChampionVM newChampion = Champion.ToChampionVM();
+ await ChampionsMgrVM.EditChampion(oldChampion, newChampion);
+ await App.Current.MainPage.Navigation.PopAsync();
+ }
+
+ [ObservableProperty]
+ string newCharacteristicDescription;
+
+ [ObservableProperty]
+ int newCharacteristicValue;
+
+ [RelayCommand]
+ void AddCharacteristic()
+ {
+ Champion?.AddCharacteristic(newCharacteristicDescription, newCharacteristicValue);
+ }
+
+ [RelayCommand]
+ void RemoveCharacteristic(KeyValuePair characteristic)
+ => Champion?.RemoveCharacteristic(characteristic);
+
+ [RelayCommand]
+ async Task AddSkill()
+ => await App.Current.MainPage.Navigation.PushModalAsync(new AddSkill(Champion));
+
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs
new file mode 100644
index 0000000..09a134c
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddOrEditSkinPageVM.cs
@@ -0,0 +1,64 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+using ViewModels;
+
+namespace LolApp.ViewModels
+{
+ [ObservableObject]
+ public partial class AddOrEditSkinPageVM
+ {
+ SkinsMgrVM SkinsMgrVM { get; }
+
+ private SkinVM oldSkin;
+
+ [ObservableProperty]
+ bool isNew = true;
+
+ [ObservableProperty]
+ EditableSkinVM skin;
+
+ public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, SkinVM oldSkin)
+ {
+ SkinsMgrVM = skinsMgrVM;
+
+ this.oldSkin = oldSkin;
+ IsNew = false;
+ this.skin = new EditableSkinVM(oldSkin);
+ }
+
+ public AddOrEditSkinPageVM(SkinsMgrVM skinsMgrVM, ChampionVM champion)
+ {
+ SkinsMgrVM = skinsMgrVM;
+ skin = new EditableSkinVM(champion);
+ }
+
+ [RelayCommand]
+ public async void PickIcon() => Skin.IconBase64 = await PickIconsAndImagesUtils.PickPhoto(42);
+
+ [RelayCommand]
+ public async void PickLargeImage() => Skin.LargeImageBase64 = await PickIconsAndImagesUtils.PickPhoto(1000);
+
+ [RelayCommand]
+ async Task Cancel()
+ => await App.Current.MainPage.Navigation.PopAsync();
+
+ [RelayCommand]
+ async Task AddSkin()
+ {
+ SkinVM skinVM = Skin.ToSkinVM();
+ await SkinsMgrVM.AddSkin(skinVM);
+ await App.Current.MainPage.Navigation.PopAsync();
+ }
+
+ [RelayCommand]
+ async Task EditSkin()
+ {
+ SkinVM newSkin = Skin.ToSkinVM();
+ await SkinsMgrVM.EditSkin(oldSkin, newSkin);
+ await App.Current.MainPage.Navigation.PopAsync();
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddSkillVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddSkillVM.cs
new file mode 100644
index 0000000..ef40e97
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/AddSkillVM.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+using ViewModels;
+
+namespace LolApp.ViewModels
+{
+ public partial class AddSkillVM : ObservableObject
+ {
+ public AddSkillVM(EditableChampionVM champion)
+ {
+ Champion = champion;
+ }
+
+ [ObservableProperty]
+ SkillType skillType;
+
+ [ObservableProperty]
+ string name;
+
+ [ObservableProperty]
+ string description;
+
+ [ObservableProperty]
+ EditableChampionVM champion;
+
+ [RelayCommand]
+ async void AddSkillToChampion()
+ {
+ champion.Skills.Add(new SkillVM(new Skill(name, skillType, description)));
+ await App.Current.MainPage.Navigation.PopModalAsync();
+ }
+
+ [RelayCommand]
+ async void Cancel()
+ {
+ await App.Current.MainPage.Navigation.PopModalAsync();
+ }
+
+ public IEnumerable AllSkills { get; }
+ = Enum.GetValues(typeof(SkillType)).Cast().Except(new SkillType[] {SkillType.Unknown}).ToList();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ApplicationVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ApplicationVM.cs
new file mode 100644
index 0000000..9f029f0
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ApplicationVM.cs
@@ -0,0 +1,58 @@
+using System;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+using ViewModels;
+
+namespace LolApp.ViewModels
+{
+ public partial class ApplicationVM
+ {
+ public ChampionsMgrVM ChampionsMgrVM { get; set; }
+
+ public SkinsMgrVM SkinsMgrVM { get; set; }
+
+ public ApplicationVM(ChampionsMgrVM championsMgrVM, SkinsMgrVM skinsMgrVM)
+ {
+ ChampionsMgrVM = championsMgrVM;
+ SkinsMgrVM = skinsMgrVM;
+ }
+
+ [RelayCommand]
+ async Task NavigateToChampionDetailsPage(ChampionVM cvm)
+ {
+ SkinsMgrVM.Champion = cvm;
+ SkinsMgrVM.Index = 0;
+ SkinsMgrVM.Count = 5;
+ await SkinsMgrVM.LoadSkinsCommand.ExecuteAsync(cvm);
+ await App.Current.MainPage.Navigation.PushAsync(new ChampionPage(cvm, this));
+ }
+
+ [RelayCommand]
+ async Task NavigateToAddNewChampionPage()
+ => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM));
+
+ [RelayCommand(CanExecute = nameof(CanNavigateToEditChampionPage))]
+ async Task NavigateToEditChampionPage(object champ)
+ => await App.Current.MainPage.Navigation.PushAsync(new AddChampionPage(ChampionsMgrVM, champ as ChampionVM));
+
+ bool CanNavigateToEditChampionPage(object champ) => champ != null && champ is ChampionVM;
+
+ [RelayCommand]
+ async Task NavigateToSkinDetailsPage(object svm)
+ {
+ if (svm == null || svm is not SkinVM) return;
+ await App.Current.MainPage.Navigation.PushAsync(new SkinPage(svm as SkinVM, this));
+ }
+
+ [RelayCommand]
+ async Task NavigateToAddNewSkinPage(ChampionVM champion)
+ => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, champion));
+
+ [RelayCommand(CanExecute = nameof(CanNavigateToEditSkinPage))]
+ async Task NavigateToEditSkinPage(object skin)
+ => await App.Current.MainPage.Navigation.PushAsync(new AddOrEditSkinPage(SkinsMgrVM, skin as SkinVM));
+
+ bool CanNavigateToEditSkinPage(object skin) => skin != null && skin is SkinVM;
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionClassVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionClassVM.cs
new file mode 100644
index 0000000..992f45f
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionClassVM.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Model;
+
+namespace LolApp.ViewModels
+{
+ [ObservableObject]
+ public partial class ChampionClassVM
+ {
+ [ObservableProperty]
+ private ChampionClass model;
+
+ [ObservableProperty]
+ private bool isSelected;
+
+ public ChampionClassVM(ChampionClass model)
+ {
+ Model = model;
+ }
+
+ public static IEnumerable Classes { get; }
+ = Enum.GetValues(typeof(ChampionClass)).Cast().Except(new ChampionClass[] {ChampionClass.Unknown})
+ .Select(cc => new ChampionClassVM(cc));
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionsPageVM.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionsPageVM.cs
new file mode 100644
index 0000000..906875a
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/ChampionsPageVM.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Reflection;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+using ViewModels;
+
+namespace LolApp.ViewModels
+{
+ [ObservableObject]
+ public partial class ChampionsPageVM
+ {
+ public ChampionsMgrVM ChampionsMgrVM { get; set; }
+
+ public ChampionsPageVM(ChampionsMgrVM championsMgrVM)
+ {
+ ChampionsMgrVM = championsMgrVM;
+ PropertyChanged += ChampionsMgrVM_PropertyChanged;
+
+ }
+
+ [ObservableProperty]
+ private ChampionClassVM selectedClass;
+
+
+ [RelayCommand]
+ public async Task SelectedChampionClassChanged(ChampionClassVM champClass)
+ {
+ if(SelectedClass != null) SelectedClass.IsSelected = false;
+ if(champClass.Model == ChampionClass.Unknown
+ || champClass.Model == SelectedClass?.Model)
+ {
+ SelectedClass = null;
+ return;
+ }
+ SelectedClass = champClass;
+ SelectedClass.IsSelected = true;
+ await ChampionsMgrVM.LoadChampionsByClass(SelectedClass.Model);//ChampionsMgrVM.SelectedClass);
+
+ }
+
+
+ [ObservableProperty]
+ private ChampionVM selectedChampion;
+
+ [ObservableProperty]
+ private string searchedName;
+
+
+
+ [ObservableProperty]
+ private string searchedSkill;
+
+ [ObservableProperty]
+ private string searchedCharacteristic;
+
+ private static string[] searchedStrings = { nameof(SearchedName), nameof(SearchedSkill), nameof(SearchedCharacteristic), nameof(SelectedClass) };
+
+ private async void ChampionsMgrVM_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if(searchedStrings.Any(s => e.PropertyName == s))
+ {
+ if(GetProperty(e.PropertyName).GetValue(this) != GetProperty(e.PropertyName).GetDefaultValue())
+ {
+ foreach(string s in searchedStrings.Except(new string[]{e.PropertyName }))
+ {
+ var prop = GetProperty(s);
+ prop.ResetPropertyValue(this);
+ }
+ return;
+ }
+ ChampionsMgrVM.Index=0;
+ if(searchedStrings.All(s => GetProperty(s).GetValue(this) == GetProperty(s).GetDefaultValue()))
+ {
+ await ChampionsMgrVM.LoadChampions();
+ }
+ }
+ }
+
+ private PropertyInfo? GetProperty(string propName)
+ => typeof(ChampionsPageVM).GetProperty(propName);
+
+ }
+
+ public static class Extensions
+ {
+ public static void ResetPropertyValue(this PropertyInfo pi, ChampionsPageVM instance)
+ {
+ if(pi.PropertyType == typeof(ChampionClassVM))
+ {
+ var temp = pi.GetValue(instance);
+ if(temp != null)
+ (temp as ChampionClassVM).IsSelected = false;
+ return;
+ }
+ pi.SetValue(instance, pi.GetDefaultValue());
+ }
+
+ public static object GetDefaultValue(this Type t)
+ {
+ if (t.IsValueType)
+ return Activator.CreateInstance(t);
+
+ return null;
+ }
+
+ public static object GetDefaultValue(this PropertyInfo pi)
+ => pi.PropertyType.GetDefaultValue();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs
new file mode 100644
index 0000000..6cef1d1
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/LolApp/ViewModels/PickIconsAndImagesUtils.cs
@@ -0,0 +1,32 @@
+using System;
+//using Microsoft.Maui.Graphics.Platform;
+using Microsoft.Maui.Graphics.Skia;
+
+namespace LolApp.ViewModels
+{
+ public static class PickIconsAndImagesUtils
+ {
+ public async static Task PickPhoto(float maxWidthAndHeight)
+ {
+ FileResult photo = await MediaPicker.Default.PickPhotoAsync();
+ return photo != null ? await ToBase64(photo, maxWidthAndHeight) : null;
+ }
+
+ public async static Task ToBase64(FileResult photo, float maxWidthAndHeight)
+ {
+ using (var stream = await photo.OpenReadAsync())
+ using (var memoryStream = new MemoryStream())
+ {
+ var image = SkiaImage.FromStream(memoryStream);
+ //var image = PlatformImage.FromStream(stream);
+ if(image != null)
+ {
+ var newImage = image.Downsize(maxWidthAndHeight, true);
+ return newImage.AsBase64();
+ }
+ }
+ return null;
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/DataBase.db b/src/EntityFramework_LoL/Sources/MyFlib/DataBase.db
index 298aaff..d3b2cb4 100644
Binary files a/src/EntityFramework_LoL/Sources/MyFlib/DataBase.db and b/src/EntityFramework_LoL/Sources/MyFlib/DataBase.db differ
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/LolDbContext.cs b/src/EntityFramework_LoL/Sources/MyFlib/LolDbContext.cs
index e680eb9..2a3ebb1 100644
--- a/src/EntityFramework_LoL/Sources/MyFlib/LolDbContext.cs
+++ b/src/EntityFramework_LoL/Sources/MyFlib/LolDbContext.cs
@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore;
using MyFlib.Entities;
using MyFlib.Entities.enums;
+using System.IO;
+using System.Reflection;
namespace MyFlib
{
@@ -24,7 +26,8 @@ namespace MyFlib
{
if (!optionsBuilder.IsConfigured)
{
- optionsBuilder.UseSqlite("Data Source=DataBase.db");
+ string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..\\..\\..\\..\\MyFlib\\DataBase.db");
+ optionsBuilder.UseSqlite($"Data Source={path}");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
@@ -93,6 +96,10 @@ namespace MyFlib
);
//CharacteristicEntity
+ modelBuilder.Entity()
+ .HasOne(m => m.Champion)
+ .WithMany(a => a.Characteristics)
+ .HasForeignKey("ChampionForeignKey");
modelBuilder.Entity().HasKey(c => new { c.Name, c.ChampionForeignKey });
modelBuilder.Entity().HasData(
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.Designer.cs b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.Designer.cs
new file mode 100644
index 0000000..3cd96b3
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.Designer.cs
@@ -0,0 +1,671 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using MyFlib;
+
+#nullable disable
+
+namespace MyFlib.Migrations
+{
+ [DbContext(typeof(LolDbContext))]
+ [Migration("20230325231552_myMigration")]
+ partial class myMigration
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
+
+ modelBuilder.Entity("ChampionEntityRunePageEntity", b =>
+ {
+ b.Property("ChampionsId")
+ .HasColumnType("TEXT");
+
+ b.Property("RunePagesName")
+ .HasColumnType("TEXT");
+
+ b.HasKey("ChampionsId", "RunePagesName");
+
+ b.HasIndex("RunePagesName");
+
+ b.ToTable("ChampionEntityRunePageEntity");
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Bio")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property("Class")
+ .HasColumnType("INTEGER");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Champions");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Bio = "",
+ Class = 1,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Akali"
+ },
+ new
+ {
+ Id = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Bio = "",
+ Class = 2,
+ Icon = "",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Name = "Aatrox"
+ },
+ new
+ {
+ Id = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Bio = "",
+ Class = 3,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Ahri"
+ },
+ new
+ {
+ Id = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Bio = "",
+ Class = 4,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Akshan"
+ },
+ new
+ {
+ Id = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Bio = "",
+ Class = 5,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Bard"
+ },
+ new
+ {
+ Id = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Bio = "",
+ Class = 6,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Alistar"
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.DictionaryCategoryRune", b =>
+ {
+ b.Property("RunePageName")
+ .HasColumnType("TEXT");
+
+ b.Property("RuneName")
+ .HasColumnType("TEXT");
+
+ b.Property("category")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("RunePageName", "RuneName");
+
+ b.HasIndex("RuneName");
+
+ b.ToTable("CategoryRunes");
+
+ b.HasData(
+ new
+ {
+ RunePageName = "Page 1",
+ RuneName = "Hextech Flashtraption ",
+ category = 0
+ },
+ new
+ {
+ RunePageName = "Page 1",
+ RuneName = "Manaflow Band ",
+ category = 1
+ },
+ new
+ {
+ RunePageName = "Page 2",
+ RuneName = "Manaflow Band ",
+ category = 4
+ },
+ new
+ {
+ RunePageName = "Page 2",
+ RuneName = "Hextech Flashtraption ",
+ category = 5
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.CharacteristicEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(254)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Name", "ChampionForeignKey");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.ToTable("Characteristic");
+
+ b.HasData(
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 58
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 92
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 6
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 526
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 418
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 68
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 570
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 350
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 70
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 580
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 56
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 575
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 200
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 63
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 2
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 573
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 278
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 30
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 535
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 350
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.RunePageEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Name");
+
+ b.ToTable("RunePages");
+
+ b.HasData(
+ new
+ {
+ Name = "Page 1"
+ },
+ new
+ {
+ Name = "Page 2"
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.LargeImageEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Base64")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("LargeImages");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Base64 = "empty"
+ },
+ new
+ {
+ Id = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Base64 = " "
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("TEXT");
+
+ b.Property("Family")
+ .HasColumnType("INTEGER");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Runes");
+
+ b.HasData(
+ new
+ {
+ Name = "Hextech Flashtraption ",
+ Description = "While Flash is on cooldown, it is replaced by Hexflash.",
+ Family = 0,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65")
+ },
+ new
+ {
+ Name = "Manaflow Band ",
+ Description = "Hitting enemy champions with a spell grants 25 maximum mana, up to 250 mana.",
+ Family = 2,
+ Icon = "",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c")
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.SkillEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.ToTable("Skills");
+
+ b.HasData(
+ new
+ {
+ Name = "Boule de feu",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Description = "Fire!",
+ Type = 1
+ },
+ new
+ {
+ Name = "White Star",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Description = "Random damage",
+ Type = 3
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.SkinEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(254)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("TEXT");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.Property("Price")
+ .HasColumnType("REAL");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Skins");
+
+ b.HasData(
+ new
+ {
+ Name = "Akali Infernale",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Description = "Djinn qu'on invoque en dessous du monde, l'Infernale connue sous le nom d'Akali réduira en cendres les ennemis de son maître… mais le prix de son service est toujours exorbitant.",
+ Icon = "empty",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Price = 520f
+ },
+ new
+ {
+ Name = "Akshan Cyberpop",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Description = "Les bas-fonds d'Audio City ont un nouveau héros : le Rebelle fluo. Cette position, Akshan la doit à son courage, sa sagesse et sa capacité à s'infiltrer dans des bâtiments d'affaires hautement sécurisés, et ce, sans être repéré. Son charme ravageur l'a aussi beaucoup aidé.",
+ Icon = "empty",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Price = 1350f
+ });
+ });
+
+ modelBuilder.Entity("ChampionEntityRunePageEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", null)
+ .WithMany()
+ .HasForeignKey("ChampionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.Entities.RunePageEntity", null)
+ .WithMany()
+ .HasForeignKey("RunePagesName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.DictionaryCategoryRune", b =>
+ {
+ b.HasOne("MyFlib.RuneEntity", "rune")
+ .WithMany("DictionaryCategoryRunes")
+ .HasForeignKey("RuneName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.Entities.RunePageEntity", "runePage")
+ .WithMany("DictionaryCategoryRunes")
+ .HasForeignKey("RunePageName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("rune");
+
+ b.Navigation("runePage");
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.CharacteristicEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Characteristics")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.SkillEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Skills")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+ });
+
+ modelBuilder.Entity("MyFlib.SkinEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Skins")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.Navigation("Characteristics");
+
+ b.Navigation("Skills");
+
+ b.Navigation("Skins");
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.RunePageEntity", b =>
+ {
+ b.Navigation("DictionaryCategoryRunes");
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.Navigation("DictionaryCategoryRunes");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.cs b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.cs
new file mode 100644
index 0000000..c5ed594
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/20230325231552_myMigration.cs
@@ -0,0 +1,375 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
+
+namespace MyFlib.Migrations
+{
+ ///
+ public partial class myMigration : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "LargeImages",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ Base64 = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_LargeImages", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "RunePages",
+ columns: table => new
+ {
+ Name = table.Column(type: "TEXT", maxLength: 64, nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_RunePages", x => x.Name);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Champions",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", maxLength: 64, nullable: false),
+ Bio = table.Column(type: "TEXT", maxLength: 255, nullable: false),
+ Icon = table.Column(type: "TEXT", nullable: false),
+ Class = table.Column(type: "INTEGER", nullable: false),
+ ImageId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Champions", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Champions_LargeImages_ImageId",
+ column: x => x.ImageId,
+ principalTable: "LargeImages",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Runes",
+ columns: table => new
+ {
+ Name = table.Column(type: "TEXT", maxLength: 64, nullable: false),
+ Description = table.Column(type: "TEXT", maxLength: 500, nullable: false),
+ Family = table.Column(type: "INTEGER", nullable: false),
+ Icon = table.Column(type: "TEXT", nullable: false),
+ ImageId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Runes", x => x.Name);
+ table.ForeignKey(
+ name: "FK_Runes_LargeImages_ImageId",
+ column: x => x.ImageId,
+ principalTable: "LargeImages",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ChampionEntityRunePageEntity",
+ columns: table => new
+ {
+ ChampionsId = table.Column(type: "TEXT", nullable: false),
+ RunePagesName = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ChampionEntityRunePageEntity", x => new { x.ChampionsId, x.RunePagesName });
+ table.ForeignKey(
+ name: "FK_ChampionEntityRunePageEntity_Champions_ChampionsId",
+ column: x => x.ChampionsId,
+ principalTable: "Champions",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_ChampionEntityRunePageEntity_RunePages_RunePagesName",
+ column: x => x.RunePagesName,
+ principalTable: "RunePages",
+ principalColumn: "Name",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Characteristic",
+ columns: table => new
+ {
+ Name = table.Column(type: "TEXT", maxLength: 254, nullable: false),
+ ChampionForeignKey = table.Column(type: "TEXT", nullable: false),
+ Value = table.Column(type: "INTEGER", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Characteristic", x => new { x.Name, x.ChampionForeignKey });
+ table.ForeignKey(
+ name: "FK_Characteristic_Champions_ChampionForeignKey",
+ column: x => x.ChampionForeignKey,
+ principalTable: "Champions",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Skills",
+ columns: table => new
+ {
+ Name = table.Column(type: "TEXT", maxLength: 64, nullable: false),
+ Description = table.Column(type: "TEXT", maxLength: 500, nullable: false),
+ Type = table.Column(type: "INTEGER", nullable: false),
+ ChampionForeignKey = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Skills", x => x.Name);
+ table.ForeignKey(
+ name: "FK_Skills_Champions_ChampionForeignKey",
+ column: x => x.ChampionForeignKey,
+ principalTable: "Champions",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Skins",
+ columns: table => new
+ {
+ Name = table.Column(type: "TEXT", maxLength: 254, nullable: false),
+ Description = table.Column(type: "TEXT", maxLength: 1000, nullable: false),
+ Icon = table.Column(type: "TEXT", nullable: false),
+ Price = table.Column(type: "REAL", nullable: false),
+ ChampionForeignKey = table.Column(type: "TEXT", nullable: false),
+ ImageId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Skins", x => x.Name);
+ table.ForeignKey(
+ name: "FK_Skins_Champions_ChampionForeignKey",
+ column: x => x.ChampionForeignKey,
+ principalTable: "Champions",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_Skins_LargeImages_ImageId",
+ column: x => x.ImageId,
+ principalTable: "LargeImages",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "CategoryRunes",
+ columns: table => new
+ {
+ RunePageName = table.Column(type: "TEXT", nullable: false),
+ RuneName = table.Column(type: "TEXT", nullable: false),
+ category = table.Column(type: "INTEGER", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_CategoryRunes", x => new { x.RunePageName, x.RuneName });
+ table.ForeignKey(
+ name: "FK_CategoryRunes_RunePages_RunePageName",
+ column: x => x.RunePageName,
+ principalTable: "RunePages",
+ principalColumn: "Name",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_CategoryRunes_Runes_RuneName",
+ column: x => x.RuneName,
+ principalTable: "Runes",
+ principalColumn: "Name",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.InsertData(
+ table: "LargeImages",
+ columns: new[] { "Id", "Base64" },
+ values: new object[,]
+ {
+ { new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "empty" },
+ { new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"), " " }
+ });
+
+ migrationBuilder.InsertData(
+ table: "RunePages",
+ column: "Name",
+ values: new object[]
+ {
+ "Page 1",
+ "Page 2"
+ });
+
+ migrationBuilder.InsertData(
+ table: "Champions",
+ columns: new[] { "Id", "Bio", "Class", "Icon", "ImageId", "Name" },
+ values: new object[,]
+ {
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "", 6, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "Alistar" },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "", 4, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "Akshan" },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "", 1, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "Akali" },
+ { new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"), "", 5, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "Bard" },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "", 2, "", new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"), "Aatrox" },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "", 3, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), "Ahri" }
+ });
+
+ migrationBuilder.InsertData(
+ table: "Runes",
+ columns: new[] { "Name", "Description", "Family", "Icon", "ImageId" },
+ values: new object[,]
+ {
+ { "Hextech Flashtraption ", "While Flash is on cooldown, it is replaced by Hexflash.", 0, "", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65") },
+ { "Manaflow Band ", "Hitting enemy champions with a spell grants 25 maximum mana, up to 250 mana.", 2, "", new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c") }
+ });
+
+ migrationBuilder.InsertData(
+ table: "CategoryRunes",
+ columns: new[] { "RuneName", "RunePageName", "category" },
+ values: new object[,]
+ {
+ { "Hextech Flashtraption ", "Page 1", 0 },
+ { "Manaflow Band ", "Page 1", 1 },
+ { "Hextech Flashtraption ", "Page 2", 5 },
+ { "Manaflow Band ", "Page 2", 4 }
+ });
+
+ migrationBuilder.InsertData(
+ table: "Characteristic",
+ columns: new[] { "ChampionForeignKey", "Name", "Value" },
+ values: new object[,]
+ {
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "Ability Power", 0 },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Ability Power", 0 },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Ability Power", 0 },
+ { new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"), "Ability Power", 30 },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "Ability Power", 0 },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "Ability Power", 92 },
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "Attack Damage", 63 },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Attack Damage", 68 },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Attack Damage", 56 },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "Attack Damage", 70 },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "Attack Damage", 58 },
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "Attack Speed", 2 },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Attack Speed", 1 },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Attack Speed", 1 },
+ { new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"), "Attack Speed", 1 },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "Attack Speed", 1 },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "Attack Speed", 6 },
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "Health", 573 },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Health", 570 },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Health", 575 },
+ { new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"), "Health", 535 },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "Health", 580 },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "Health", 526 },
+ { new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"), "Mana", 278 },
+ { new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Mana", 350 },
+ { new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Mana", 200 },
+ { new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"), "Mana", 350 },
+ { new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"), "Mana", 0 },
+ { new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"), "Mana", 418 }
+ });
+
+ migrationBuilder.InsertData(
+ table: "Skills",
+ columns: new[] { "Name", "ChampionForeignKey", "Description", "Type" },
+ values: new object[,]
+ {
+ { "Boule de feu", new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Fire!", 1 },
+ { "White Star", new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Random damage", 3 }
+ });
+
+ migrationBuilder.InsertData(
+ table: "Skins",
+ columns: new[] { "Name", "ChampionForeignKey", "Description", "Icon", "ImageId", "Price" },
+ values: new object[,]
+ {
+ { "Akali Infernale", new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"), "Djinn qu'on invoque en dessous du monde, l'Infernale connue sous le nom d'Akali réduira en cendres les ennemis de son maître… mais le prix de son service est toujours exorbitant.", "empty", new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"), 520f },
+ { "Akshan Cyberpop", new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"), "Les bas-fonds d'Audio City ont un nouveau héros : le Rebelle fluo. Cette position, Akshan la doit à son courage, sa sagesse et sa capacité à s'infiltrer dans des bâtiments d'affaires hautement sécurisés, et ce, sans être repéré. Son charme ravageur l'a aussi beaucoup aidé.", "empty", new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"), 1350f }
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_CategoryRunes_RuneName",
+ table: "CategoryRunes",
+ column: "RuneName");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_ChampionEntityRunePageEntity_RunePagesName",
+ table: "ChampionEntityRunePageEntity",
+ column: "RunePagesName");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Champions_ImageId",
+ table: "Champions",
+ column: "ImageId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Characteristic_ChampionForeignKey",
+ table: "Characteristic",
+ column: "ChampionForeignKey");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Runes_ImageId",
+ table: "Runes",
+ column: "ImageId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Skills_ChampionForeignKey",
+ table: "Skills",
+ column: "ChampionForeignKey");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Skins_ChampionForeignKey",
+ table: "Skins",
+ column: "ChampionForeignKey");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Skins_ImageId",
+ table: "Skins",
+ column: "ImageId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "CategoryRunes");
+
+ migrationBuilder.DropTable(
+ name: "ChampionEntityRunePageEntity");
+
+ migrationBuilder.DropTable(
+ name: "Characteristic");
+
+ migrationBuilder.DropTable(
+ name: "Skills");
+
+ migrationBuilder.DropTable(
+ name: "Skins");
+
+ migrationBuilder.DropTable(
+ name: "Runes");
+
+ migrationBuilder.DropTable(
+ name: "RunePages");
+
+ migrationBuilder.DropTable(
+ name: "Champions");
+
+ migrationBuilder.DropTable(
+ name: "LargeImages");
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/Migrations/LolDbContextModelSnapshot.cs b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/LolDbContextModelSnapshot.cs
new file mode 100644
index 0000000..3a1cbfe
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/MyFlib/Migrations/LolDbContextModelSnapshot.cs
@@ -0,0 +1,668 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using MyFlib;
+
+#nullable disable
+
+namespace MyFlib.Migrations
+{
+ [DbContext(typeof(LolDbContext))]
+ partial class LolDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
+
+ modelBuilder.Entity("ChampionEntityRunePageEntity", b =>
+ {
+ b.Property("ChampionsId")
+ .HasColumnType("TEXT");
+
+ b.Property("RunePagesName")
+ .HasColumnType("TEXT");
+
+ b.HasKey("ChampionsId", "RunePagesName");
+
+ b.HasIndex("RunePagesName");
+
+ b.ToTable("ChampionEntityRunePageEntity");
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Bio")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property("Class")
+ .HasColumnType("INTEGER");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Champions");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Bio = "",
+ Class = 1,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Akali"
+ },
+ new
+ {
+ Id = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Bio = "",
+ Class = 2,
+ Icon = "",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Name = "Aatrox"
+ },
+ new
+ {
+ Id = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Bio = "",
+ Class = 3,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Ahri"
+ },
+ new
+ {
+ Id = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Bio = "",
+ Class = 4,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Akshan"
+ },
+ new
+ {
+ Id = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Bio = "",
+ Class = 5,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Bard"
+ },
+ new
+ {
+ Id = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Bio = "",
+ Class = 6,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Name = "Alistar"
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.DictionaryCategoryRune", b =>
+ {
+ b.Property("RunePageName")
+ .HasColumnType("TEXT");
+
+ b.Property("RuneName")
+ .HasColumnType("TEXT");
+
+ b.Property("category")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("RunePageName", "RuneName");
+
+ b.HasIndex("RuneName");
+
+ b.ToTable("CategoryRunes");
+
+ b.HasData(
+ new
+ {
+ RunePageName = "Page 1",
+ RuneName = "Hextech Flashtraption ",
+ category = 0
+ },
+ new
+ {
+ RunePageName = "Page 1",
+ RuneName = "Manaflow Band ",
+ category = 1
+ },
+ new
+ {
+ RunePageName = "Page 2",
+ RuneName = "Manaflow Band ",
+ category = 4
+ },
+ new
+ {
+ RunePageName = "Page 2",
+ RuneName = "Hextech Flashtraption ",
+ category = 5
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.CharacteristicEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(254)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Name", "ChampionForeignKey");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.ToTable("Characteristic");
+
+ b.HasData(
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 58
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 92
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 6
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 526
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("ae5fe535-f041-445e-b570-28b75bc78cb9"),
+ Value = 418
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 68
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 570
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Value = 350
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 70
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 580
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("a4f84d92-c20f-4f2d-b3f9-ca00ef556e72"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 56
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 575
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Value = 200
+ },
+ new
+ {
+ Name = "Attack Damage",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 63
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 0
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 2
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 573
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("36ad2a82-d17b-47de-8a95-6e154a7df557"),
+ Value = 278
+ },
+ new
+ {
+ Name = "Ability Power",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 30
+ },
+ new
+ {
+ Name = "Attack Speed",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 1
+ },
+ new
+ {
+ Name = "Health",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 535
+ },
+ new
+ {
+ Name = "Mana",
+ ChampionForeignKey = new Guid("7f7746fa-b1cb-49da-9409-4b3e6910500e"),
+ Value = 350
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.RunePageEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Name");
+
+ b.ToTable("RunePages");
+
+ b.HasData(
+ new
+ {
+ Name = "Page 1"
+ },
+ new
+ {
+ Name = "Page 2"
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.LargeImageEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Base64")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("LargeImages");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Base64 = "empty"
+ },
+ new
+ {
+ Id = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Base64 = " "
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("TEXT");
+
+ b.Property("Family")
+ .HasColumnType("INTEGER");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Runes");
+
+ b.HasData(
+ new
+ {
+ Name = "Hextech Flashtraption ",
+ Description = "While Flash is on cooldown, it is replaced by Hexflash.",
+ Family = 0,
+ Icon = "",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65")
+ },
+ new
+ {
+ Name = "Manaflow Band ",
+ Description = "Hitting enemy champions with a spell grants 25 maximum mana, up to 250 mana.",
+ Family = 2,
+ Icon = "",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c")
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.SkillEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.ToTable("Skills");
+
+ b.HasData(
+ new
+ {
+ Name = "Boule de feu",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Description = "Fire!",
+ Type = 1
+ },
+ new
+ {
+ Name = "White Star",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Description = "Random damage",
+ Type = 3
+ });
+ });
+
+ modelBuilder.Entity("MyFlib.SkinEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(254)
+ .HasColumnType("TEXT");
+
+ b.Property("ChampionForeignKey")
+ .HasColumnType("TEXT");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("TEXT");
+
+ b.Property("Icon")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ImageId")
+ .HasColumnType("TEXT");
+
+ b.Property("Price")
+ .HasColumnType("REAL");
+
+ b.HasKey("Name");
+
+ b.HasIndex("ChampionForeignKey");
+
+ b.HasIndex("ImageId");
+
+ b.ToTable("Skins");
+
+ b.HasData(
+ new
+ {
+ Name = "Akali Infernale",
+ ChampionForeignKey = new Guid("4422c524-b2cb-43ef-8263-990c3cea7cae"),
+ Description = "Djinn qu'on invoque en dessous du monde, l'Infernale connue sous le nom d'Akali réduira en cendres les ennemis de son maître… mais le prix de son service est toujours exorbitant.",
+ Icon = "empty",
+ ImageId = new Guid("8d121cdc-6787-4738-8edd-9e026ac16b65"),
+ Price = 520f
+ },
+ new
+ {
+ Name = "Akshan Cyberpop",
+ ChampionForeignKey = new Guid("3708dcfd-02a1-491e-b4f7-e75bf274cf23"),
+ Description = "Les bas-fonds d'Audio City ont un nouveau héros : le Rebelle fluo. Cette position, Akshan la doit à son courage, sa sagesse et sa capacité à s'infiltrer dans des bâtiments d'affaires hautement sécurisés, et ce, sans être repéré. Son charme ravageur l'a aussi beaucoup aidé.",
+ Icon = "empty",
+ ImageId = new Guid("9f9086f5-5cc5-47b5-af9b-a935f4e9b89c"),
+ Price = 1350f
+ });
+ });
+
+ modelBuilder.Entity("ChampionEntityRunePageEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", null)
+ .WithMany()
+ .HasForeignKey("ChampionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.Entities.RunePageEntity", null)
+ .WithMany()
+ .HasForeignKey("RunePagesName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.DictionaryCategoryRune", b =>
+ {
+ b.HasOne("MyFlib.RuneEntity", "rune")
+ .WithMany("DictionaryCategoryRunes")
+ .HasForeignKey("RuneName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.Entities.RunePageEntity", "runePage")
+ .WithMany("DictionaryCategoryRunes")
+ .HasForeignKey("RunePageName")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("rune");
+
+ b.Navigation("runePage");
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.CharacteristicEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Characteristics")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.SkillEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Skills")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+ });
+
+ modelBuilder.Entity("MyFlib.SkinEntity", b =>
+ {
+ b.HasOne("MyFlib.ChampionEntity", "Champion")
+ .WithMany("Skins")
+ .HasForeignKey("ChampionForeignKey")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("MyFlib.LargeImageEntity", "Image")
+ .WithMany()
+ .HasForeignKey("ImageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Champion");
+
+ b.Navigation("Image");
+ });
+
+ modelBuilder.Entity("MyFlib.ChampionEntity", b =>
+ {
+ b.Navigation("Characteristics");
+
+ b.Navigation("Skills");
+
+ b.Navigation("Skins");
+ });
+
+ modelBuilder.Entity("MyFlib.Entities.RunePageEntity", b =>
+ {
+ b.Navigation("DictionaryCategoryRunes");
+ });
+
+ modelBuilder.Entity("MyFlib.RuneEntity", b =>
+ {
+ b.Navigation("DictionaryCategoryRunes");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/MyFlib.csproj b/src/EntityFramework_LoL/Sources/MyFlib/MyFlib.csproj
index effa3a7..d3c5f6a 100644
--- a/src/EntityFramework_LoL/Sources/MyFlib/MyFlib.csproj
+++ b/src/EntityFramework_LoL/Sources/MyFlib/MyFlib.csproj
@@ -1,7 +1,6 @@
- Exe
net6.0
enable
enable
diff --git a/src/EntityFramework_LoL/Sources/MyFlib/Program.cs b/src/EntityFramework_LoL/Sources/MyFlib/Program.cs
index a1a700c..4143966 100644
--- a/src/EntityFramework_LoL/Sources/MyFlib/Program.cs
+++ b/src/EntityFramework_LoL/Sources/MyFlib/Program.cs
@@ -1,5 +1,5 @@
// See https://aka.ms/new-console-template for more information
-using MyFlib;
+/*using MyFlib;
using static System.Console;
using (var context = new LolDbContext())
@@ -35,4 +35,4 @@ using (var context = new LolDbContext())
}
context.SaveChangesAsync(); // or context.SaveChangesAsync
-}
\ No newline at end of file
+}*/
\ No newline at end of file
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/ChampionVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/ChampionVM.cs
new file mode 100644
index 0000000..bdd1e7f
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/ChampionVM.cs
@@ -0,0 +1,101 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Model;
+using Microsoft.Maui.Controls;
+using System.Collections.ObjectModel;
+
+
+namespace ViewModels
+{
+ public partial class ChampionVM : ObservableObject
+ {
+ public Champion Model
+ {
+ get => model;
+ set
+ {
+ model = value;
+ OnPropertyChanged(nameof(Name));
+ OnPropertyChanged(nameof(Bio));
+ OnPropertyChanged(nameof(Class));
+ OnPropertyChanged(nameof(Icon));
+ OnPropertyChanged(nameof(Image));
+ OnPropertyChanged(nameof(Skills));
+ OnPropertyChanged(nameof(Characteristics));
+ }
+ }
+ private Champion model;
+
+ public ChampionVM(Champion model)
+ {
+ Model = model;
+ foreach(var skill in Model.Skills)
+ {
+ Skills.Add(new SkillVM(skill));
+ }
+ Skills.CollectionChanged += Skills_CollectionChanged;
+ }
+
+ private void Skills_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ SkillVM vm = e.NewItems?[0] as SkillVM;
+ switch(e.Action)
+ {
+ case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
+ Model.Skills.Add(new Skill(vm.Name, vm.Type, vm.Description));
+ break;
+ case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
+ Model.Skills.Remove(vm.Model);
+ break;
+ }
+ }
+
+ public string Name => Model.Name;
+
+ public ChampionClass Class
+ {
+ get => Model.Class;
+ set => SetProperty(Model.Class, value, newValue => Model.Class = newValue);
+ }
+
+ public string Bio
+ {
+ get => Model.Bio;
+ set => SetProperty(Model.Bio, value, newBio => Model.Bio = newBio);
+ }
+
+ public string Icon
+ {
+ get => Model.Icon;
+ set
+ {
+ SetProperty(Model.Icon, value, newIcon =>
+ {
+ Model.Icon = newIcon;
+ });
+ }
+ }
+
+ public string Image
+ {
+ get => Model.Image.Base64;
+ set
+ {
+ SetProperty(Model.Image.Base64, value, newImage =>
+ {
+ Model.Image.Base64 = newImage;
+ });
+ }
+ }
+
+ [ObservableProperty]
+ private ObservableCollection skills = new ObservableCollection();
+
+ public ReadOnlyDictionary Characteristics
+ => Model.Characteristics;
+
+ [ObservableProperty]
+ private ObservableCollection skins = new ObservableCollection();
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/ChampionsMgrVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/ChampionsMgrVM.cs
new file mode 100644
index 0000000..06e5d67
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/ChampionsMgrVM.cs
@@ -0,0 +1,227 @@
+using System.Threading.Tasks;
+using Model;
+using System.Windows.Input;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.Input;
+using System.Data.SqlTypes;
+using System.Reflection;
+
+namespace ViewModels;
+
+public partial class ChampionsMgrVM : ObservableObject
+{
+ internal IDataManager DataMgr { get; set; }
+
+ public ChampionsMgrVM(IDataManager dataManager)
+ {
+ DataMgr = dataManager;
+
+ loadingMethods = new Dictionary>()
+ {
+ [LoadingCriterium.None] = async (o) => await LoadChampions(),
+ [LoadingCriterium.ByName] = async (o) =>
+ {
+ string substring = o as string;
+ if(substring == null) return;
+ await LoadChampionsByName(substring);
+ },
+ [LoadingCriterium.BySkill] = async (o) =>
+ {
+ string skillString = o as string;
+ if(skillString == null) return;
+ await LoadChampionsBySkill(skillString);
+ },
+ [LoadingCriterium.ByCharacteristic] = async (o) =>
+ {
+ string characString = o as string;
+ if(characString == null) return;
+ await LoadChampionsByCharacteristic(characString);
+ },
+ [LoadingCriterium.ByClass] = async (o) =>
+ {
+ if(!Enum.IsDefined(typeof(ChampionClass), o)) return;
+ ChampionClass champClass = (ChampionClass)o;
+ await LoadChampionsByClass(champClass);
+ },
+ };
+ }
+
+ private async Task LoadChampionsFunc(Func>> loader,
+ Func> nbReader,
+ LoadingCriterium criterium,
+ object parameter = null)
+ {
+ Champions.Clear();
+ var someChampions = (await loader()).Select(c => new ChampionVM(c)).ToList();
+ foreach (var cvm in someChampions)
+ {
+ Champions.Add(cvm);
+ }
+ NbChampions = await nbReader();
+ currentLoadingCriterium = criterium;
+ currentLoadingParameter = parameter;
+ }
+
+ [RelayCommand]
+ public async Task LoadChampions()
+ {
+ await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItems(index, count, "Name"),
+ async () => await DataMgr.ChampionsMgr.GetNbItems(),
+ LoadingCriterium.None);
+ }
+
+ [RelayCommand(CanExecute =nameof(CanLoadChampionsByName))]
+ public async Task LoadChampionsByName(string substring)
+ {
+ await LoadChampionsFunc(async () => await DataMgr.ChampionsMgr.GetItemsByName(substring, index, count, "Name"),
+ async () => await DataMgr.ChampionsMgr.GetNbItemsByName(substring),
+ LoadingCriterium.ByName,
+ substring);
+ }
+ private bool CanLoadChampionsByName(string substring)
+ => !string.IsNullOrWhiteSpace(substring);
+
+ [RelayCommand(CanExecute =nameof(CanLoadChampionsBySkill))]
+ public async Task LoadChampionsBySkill(string skill)
+ {
+ await LoadChampionsFunc(
+ async () => await DataMgr.ChampionsMgr.GetItemsBySkill(skill, index, count, "Name"),
+ async () => await DataMgr.ChampionsMgr.GetNbItemsBySkill(skill),
+ LoadingCriterium.BySkill,
+ skill);
+ }
+ private bool CanLoadChampionsBySkill(string substring) => !string.IsNullOrWhiteSpace(substring);
+
+ [RelayCommand(CanExecute = nameof(CanLoadChampionsByCharacteristic))]
+ public async Task LoadChampionsByCharacteristic(string characteristic)
+ {
+ await LoadChampionsFunc(
+ async () => await DataMgr.ChampionsMgr.GetItemsByCharacteristic(characteristic, index, count, "Name"),
+ async () => await DataMgr.ChampionsMgr.GetNbItemsByCharacteristic(characteristic),
+ LoadingCriterium.ByCharacteristic,
+ characteristic);
+ }
+
+ private bool CanLoadChampionsByCharacteristic(string characteristic)
+ => !string.IsNullOrWhiteSpace(characteristic);
+
+ [RelayCommand]
+ public async Task LoadChampionsByClass(ChampionClass champClass)
+ {
+ if(champClass == ChampionClass.Unknown)
+ {
+ return;
+ }
+ await LoadChampionsFunc(
+ async () => await DataMgr.ChampionsMgr.GetItemsByClass(champClass, index, count, "Name"),
+ async () => await DataMgr.ChampionsMgr.GetNbItemsByClass(champClass),
+ LoadingCriterium.ByClass,
+ champClass);
+ }
+
+ [RelayCommand(CanExecute =nameof(CanDeleteChampion))]
+ public async Task DeleteChampion(object champVM)
+ {
+ ChampionVM cvm = champVM as ChampionVM;
+ if(cvm == null || !Champions.Contains(cvm)) return false;
+ bool result = await DataMgr.ChampionsMgr.DeleteItem(cvm.Model);
+ if(result)
+ {
+ Champions.Remove(cvm);
+ await LoadChampions();
+ }
+ return result;
+ }
+ bool CanDeleteChampion(object cvm)
+ => cvm!= null && cvm is ChampionVM && Champions.Contains(cvm);
+
+ [ObservableProperty]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int index = 0;
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(NbPages))]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int count = 5;
+
+ public int NbPages
+ {
+ get
+ {
+ if(Count == 0 || NbChampions == 0)
+ {
+ return 0;
+ }
+ return (NbChampions-1) / Count + 1;
+ }
+ }
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(NbPages))]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int nbChampions = 0;
+
+ [ObservableProperty]
+ private ObservableCollection champions = new ObservableCollection();
+
+ [RelayCommand(CanExecute =nameof(CanPreviousPage))]
+ async Task PreviousPage()
+ {
+ if(Index > 0)
+ {
+ Index--;
+ await loadingMethods[currentLoadingCriterium](currentLoadingParameter);
+ }
+ }
+ bool CanPreviousPage() => Index > 0;
+
+ [RelayCommand(CanExecute =nameof(CanNextPage))]
+ async Task NextPage()
+ {
+ if(Index < NbPages-1)
+ {
+ Index++;
+ await loadingMethods[currentLoadingCriterium](currentLoadingParameter);
+ }
+ }
+ bool CanNextPage() => Index < NbPages-1;
+
+
+ enum LoadingCriterium
+ {
+ None,
+ ByName,
+ BySkill,
+ ByCharacteristic,
+ ByClass
+ }
+
+ private LoadingCriterium currentLoadingCriterium = LoadingCriterium.None;
+ private object currentLoadingParameter = null;
+
+ private Dictionary> loadingMethods;
+
+ public async Task AddChampion(ChampionVM champVM)
+ {
+ var added = await DataMgr.ChampionsMgr.AddItem(champVM.Model);
+ if(added != null)
+ {
+ Champions.Add(champVM);
+ await LoadChampions();
+ }
+ }
+
+ public async Task EditChampion(ChampionVM oldChampion, ChampionVM newChampion)
+ {
+ var edited = await DataMgr.ChampionsMgr.UpdateItem(oldChampion.Model, newChampion.Model);
+ oldChampion.Model = newChampion.Model;
+ if(edited != null)
+ {
+ await LoadChampions();
+ }
+ }
+}
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/EditableChampionVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/EditableChampionVM.cs
new file mode 100644
index 0000000..2db038b
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/EditableChampionVM.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+
+namespace ViewModels
+{
+ [ObservableObject]
+ public partial class EditableChampionVM
+ {
+ public EditableChampionVM()
+ { }
+
+ public EditableChampionVM(ChampionVM championVM)
+ {
+ Name = championVM.Name;
+ IconBase64 = championVM.Icon;
+ LargeImageBase64 = championVM.Image;
+ Bio = championVM.Bio;
+ ChampionClass = championVM.Class;
+ foreach(var ch in championVM.Characteristics)
+ {
+ AddCharacteristic(ch.Key, ch.Value);
+ }
+ foreach(var skill in championVM.Skills)
+ {
+ Skills.Add(skill);
+ }
+ }
+
+ [ObservableProperty]
+ string name;
+
+ [ObservableProperty]
+ string iconBase64;
+
+ [ObservableProperty]
+ string largeImageBase64;
+
+ [ObservableProperty]
+ string bio;
+
+ [ObservableProperty]
+ ChampionClass championClass;
+
+ [ObservableProperty]
+ ObservableCollection> characteristics = new ();
+
+ public void AddCharacteristic(string description, int value)
+ => Characteristics.Add(new KeyValuePair(description, value));
+
+ public void RemoveCharacteristic(KeyValuePair characteristic)
+ => Characteristics.Remove(characteristic);
+
+ [ObservableProperty]
+ ObservableCollection skills = new ObservableCollection();
+
+
+
+ public ChampionVM ToChampionVM()
+ {
+ var champion = new Champion(name, championClass, iconBase64, largeImageBase64, bio);
+ champion.AddCharacteristics(characteristics.Select(kvp => Tuple.Create(kvp.Key, kvp.Value)).ToArray());
+ foreach(var skillVM in Skills)
+ {
+ champion.AddSkill(skillVM.Model);
+ }
+ return new ChampionVM(champion);
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/EditableSkinVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/EditableSkinVM.cs
new file mode 100644
index 0000000..b35ca24
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/EditableSkinVM.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Reflection.PortableExecutable;
+using System.Xml.Linq;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Model;
+
+namespace ViewModels
+{
+ [ObservableObject]
+ public partial class EditableSkinVM
+ {
+ public EditableSkinVM(ChampionVM championVM)
+ {
+ champion = championVM.Model;
+ }
+
+ public EditableSkinVM(SkinVM skinVM)
+ {
+ Name = skinVM.Name;
+ IconBase64 = skinVM.Icon;
+ LargeImageBase64 = skinVM.Image;
+ Description = skinVM.Description;
+ Price = skinVM.Price;
+ champion = skinVM.Champion;
+ }
+
+ [ObservableProperty]
+ private string name;
+
+ [ObservableProperty]
+ private string iconBase64;
+
+ [ObservableProperty]
+ private string largeImageBase64;
+
+ [ObservableProperty]
+ private string description;
+
+ [ObservableProperty]
+ private float price;
+
+ private Champion champion;
+
+ public SkinVM ToSkinVM()
+ {
+ var skin = new Skin(name, champion, price, iconBase64, largeImageBase64, description);
+ return new SkinVM(skin);
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/SkillVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/SkillVM.cs
new file mode 100644
index 0000000..c9c2ca1
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/SkillVM.cs
@@ -0,0 +1,32 @@
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Model;
+
+namespace ViewModels
+{
+ [ObservableObject]
+ public partial class SkillVM
+ {
+ [ObservableProperty]
+ private Skill model;
+
+ public SkillVM(Skill model)
+ {
+ Model = model;
+ }
+
+ public string Name => Model.Name;
+
+ public SkillType Type => Model.Type;
+
+ public string Description
+ {
+ get => Model.Description;
+ set
+ {
+ SetProperty(Model.Description, value, newValue => Model.Description = newValue);
+ }
+ }
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/SkinVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/SkinVM.cs
new file mode 100644
index 0000000..358ec97
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/SkinVM.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Reflection.PortableExecutable;
+using System.Security.Claims;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Model;
+
+namespace ViewModels
+{
+ [ObservableObject]
+ public partial class SkinVM
+ {
+ public Skin Model
+ {
+ get => model;
+ set
+ {
+ model = value;
+ OnPropertyChanged(nameof(Name));
+ OnPropertyChanged(nameof(Description));
+ OnPropertyChanged(nameof(Price));
+ OnPropertyChanged(nameof(Icon));
+ OnPropertyChanged(nameof(Image));
+ }
+ }
+ private Skin model;
+
+ public SkinVM(Skin model)
+ => Model = model;
+
+ public string Name => Model.Name;
+
+ public string Description
+ {
+ get => Model.Description;
+ set => SetProperty(Model.Description, value, newValue => Model.Description = newValue);
+ }
+
+ public float Price
+ {
+ get => Model.Price;
+ set => SetProperty(Model.Price, value, newValue => Model.Price = newValue);
+ }
+
+ public string Icon
+ {
+ get => Model.Icon;
+ set
+ {
+ SetProperty(Model.Icon, value, newIcon => Model.Icon = newIcon);
+ }
+ }
+
+ public string Image
+ {
+ get => Model.Image.Base64;
+ set
+ {
+ SetProperty(Model.Image.Base64, value, newImage => Model.Image.Base64 = newImage);
+ }
+ }
+
+ public Champion Champion => Model.Champion;
+ }
+}
+
diff --git a/src/EntityFramework_LoL/Sources/ViewModels/SkinsMgrVM.cs b/src/EntityFramework_LoL/Sources/ViewModels/SkinsMgrVM.cs
new file mode 100644
index 0000000..c51a6cf
--- /dev/null
+++ b/src/EntityFramework_LoL/Sources/ViewModels/SkinsMgrVM.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Model;
+
+namespace ViewModels
+{
+ [ObservableObject]
+ public partial class SkinsMgrVM
+ {
+ internal IDataManager DataMgr { get; set; }
+
+ [ObservableProperty]
+ private ChampionVM champion;
+
+ public SkinsMgrVM(IDataManager dataManager)
+ {
+ DataMgr = dataManager;
+ }
+
+ [ObservableProperty]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int index = 0;
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(NbPages))]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int count = 5;
+
+ public int NbPages
+ {
+ get
+ {
+ if(Count == 0 || NbSkins == 0)
+ {
+ return 0;
+ }
+ return (NbSkins-1) / Count + 1;
+ }
+ }
+
+ [ObservableProperty]
+ [NotifyPropertyChangedFor(nameof(NbPages))]
+ [NotifyCanExecuteChangedFor(nameof(NextPageCommand))]
+ [NotifyCanExecuteChangedFor(nameof(PreviousPageCommand))]
+ private int nbSkins = 0;
+
+ [ObservableProperty]
+ private ObservableCollection