diff --git a/.drone.yml b/.drone.yml index 5c6e8c0..d363876 100644 --- a/.drone.yml +++ b/.drone.yml @@ -26,25 +26,24 @@ steps: - dotnet test LeagueOfLegends.sln --no-restore depends_on: [build] - #- name: code-analysis - #image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dronesonarplugin-dotnet6 - #commands: - #- cd Sources/ - #- dotnet restore LeagueOfLegends.sln - #- dotnet sonarscanner begin /k:TEST /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" - #- reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport" - #- dotnet publish LeagueOfLegends.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: - # accessible en ligne de commande par ${PLUGIN_SONAR_HOST} - #sonar_host: https://codefirst.iut.uca.fr/sonar/ - # accessible en ligne de commande par ${PLUGIN_SONAR_TOKEN} - #sonar_token: - #from_secret: SECRET_SONAR_LOGIN - #depends_on: [tests] + - name: code-analysis + image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dronesonarplugin-dotnet6 + commands: + - cd Sources/ + - dotnet restore LeagueOfLegends.sln + - dotnet sonarscanner begin /k:LOLProject /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" + - reportgenerator -reports:"**/coverage.cobertura.xml" -reporttypes:SonarQube -targetdir:"coveragereport" + - dotnet publish LeagueOfLegends.sln -c Release --no-restore -o CI_PROJECT_DIR/build/release + - dotnet sonarscanner end /d:sonar.login=$${PLUGIN_SONAR_TOKEN} + secrets: [ SONAR_TOKEN ] + settings: + sonar_host: https://codefirst.iut.uca.fr/sonar/ + sonar_token: + from_secret: SONAR_TOKEN + depends_on: [tests] + - name: generate-and-deploy-docs image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-docdeployer @@ -77,7 +76,7 @@ steps: image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest environment: IMAGENAME: hub.codefirst.iut.uca.fr/lucas.delanier/lolproject:latest - CONTAINERNAME: container_lol + CONTAINERNAME: containerlol COMMAND: create OVERWRITE: true volumes: diff --git a/Documentations/Capture d'écran 2023-03-26 111526.png b/Documentations/Capture d'écran 2023-03-26 111526.png new file mode 100644 index 0000000..e3f92dd Binary files /dev/null and b/Documentations/Capture d'écran 2023-03-26 111526.png differ diff --git a/Documentations/Capture d'écran 2023-03-26 113439.png b/Documentations/Capture d'écran 2023-03-26 113439.png new file mode 100644 index 0000000..afbf638 Binary files /dev/null and b/Documentations/Capture d'écran 2023-03-26 113439.png differ diff --git a/Documentations/Capture d'écran 2023-03-26 113710.png b/Documentations/Capture d'écran 2023-03-26 113710.png new file mode 100644 index 0000000..c50c6b9 Binary files /dev/null and b/Documentations/Capture d'écran 2023-03-26 113710.png differ diff --git a/Documentations/Capture d'écran 2023-03-26 114811.png b/Documentations/Capture d'écran 2023-03-26 114811.png new file mode 100644 index 0000000..383ae59 Binary files /dev/null and b/Documentations/Capture d'écran 2023-03-26 114811.png differ diff --git a/Documentations/Mask group.png b/Documentations/Mask group.png new file mode 100644 index 0000000..fac0dc8 Binary files /dev/null and b/Documentations/Mask group.png differ diff --git a/Documentations/Schema_architecture.png b/Documentations/Schema_architecture.png new file mode 100644 index 0000000..22039d4 Binary files /dev/null and b/Documentations/Schema_architecture.png differ diff --git a/README.md b/README.md index 3228583..0841a09 100644 --- a/README.md +++ b/README.md @@ -1,168 +1,93 @@ -# prepaLoL - -## Diagramme de classes du modèle -```mermaid -classDiagram -class LargeImage{ - +/Base64 : string -} -class Champion{ - +/Name : string - +/Bio : string - +/Icon : string - +/Characteristics : Dictionary~string, int~ - ~ AddSkin(skin : Skin) bool - ~ RemoveSkin(skin: Skin) bool - + AddSkill(skill: Skill) bool - + RemoveSkill(skill: Skill) bool - + AddCharacteristics(someCharacteristics : params Tuple~string, int~[]) - + RemoveCharacteristics(label : string) bool - + this~label : string~ : int? -} -Champion --> "1" LargeImage : Image -class ChampionClass{ - <> - Unknown, - Assassin, - Fighter, - Mage, - Marksman, - Support, - Tank, -} -Champion --> "1" ChampionClass : Class -class Skin{ - +/Name : string - +/Description : string - +/Icon : string - +/Price : float -} -Skin --> "1" LargeImage : Image -Champion "1" -- "*" Skin -class Skill{ - +/Name : string - +/Description : string -} -class SkillType{ - <> - Unknown, - Basic, - Passive, - Ultimate, -} -Skill --> "1" SkillType : Type -Champion --> "*" Skill -class Rune{ - +/Name : string - +/Description : string -} -Rune --> "1" LargeImage : Image -class RuneFamily{ - <> - Unknown, - Precision, - Domination -} -Rune --> "1" RuneFamily : Family -class Category{ - <> - Major, - Minor1, - Minor2, - Minor3, - OtherMinor1, - OtherMinor2 -} -class RunePage{ - +/Name : string - +/this[category : Category] : Rune? - - CheckRunes(newRuneCategory : Category) - - CheckFamilies(cat1 : Category, cat2 : Category) bool? - - UpdateMajorFamily(minor : Category, expectedValue : bool) -} -RunePage --> "*" Rune : Dictionary~Category,Rune~ -``` - -## Diagramme de classes des interfaces de gestion de l'accès aux données -```mermaid -classDiagram -direction LR; -class IGenericDataManager~T~{ - <> - GetNbItems() Task~int~ - GetItems(index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~T~~ - GetNbItemsByName(substring : string) - GetItemsByName(substring : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~T~~ - UpdateItem(oldItem : T, newItem : T) Task~T~~ - AddItem(item : T) Task~T~ - DeleteItem(item : T) Task~bool~ -} -class IChampionsManager{ - <> - GetNbItemsByCharacteristic(charName : string) - GetItemsByCharacteristic(charName : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~ - GetNbItemsByClass(championClass : ChampionClass) - GetItemsByClass(championClass : ChampionClass, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~ - GetNbItemsBySkill(skill : Skill?) - GetItemsBySkill(skill : Skill?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~ - GetNbItemsBySkill(skill : string) - GetItemsBySkill(skill : string, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~ - GetNbItemsByRunePage(runePage : RunePage?) - GetItemsByRunePage(runePage : RunePage?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Champion?~~ -} -class ISkinsManager{ - <> - GetNbItemsByChampion(champion : Champion?) - GetItemsByChampion(champion : Champion?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Skin?~~ -} -class IRunesManager{ - <> - GetNbItemsByFamily(family : RuneFamily) - GetItemsByFamily(family : RuneFamily, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~Rune?~~ -} -class IRunePagesManager{ - <> - GetNbItemsByRune(rune : Rune?) - GetItemsByRune(rune : Rune?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~RunePage?~~ - GetNbItemsByChampion(champion : Champion?) - GetItemsByChampion(champion : Champion?, index : int, count : int, orderingPropertyName : string?, descending : bool) Task~IEnumerable~RunePage?~~ -} - -IGenericDataManager~Champion?~ <|.. IChampionsManager : T--Champion? -IGenericDataManager~Skin?~ <|.. ISkinsManager : T--Skin? -IGenericDataManager~Rune?~ <|.. IRunesManager : T--Rune? -IGenericDataManager~RunePage?~ <|.. IRunePagesManager : T--RunePage? -class IDataManager{ - <> -} -IChampionsManager <-- IDataManager : ChampionsMgr -ISkinsManager <-- IDataManager : SkinsMgr -IRunesManager <-- IDataManager : RunesMgr -IRunePagesManager <-- IDataManager : RunePagesMgr -``` - -## Diagramme de classes simplifié du Stub -```mermaid -classDiagram -direction TB; - -IDataManager <|.. StubData - -ChampionsManager ..|> IChampionsManager -StubData --> ChampionsManager - -RunesManager ..|> IRunesManager -StubData --> RunesManager - -RunePagesManager ..|> IRunePagesManager -StubData --> RunePagesManager - -SkinsManager ..|> ISkinsManager -StubData --> SkinsManager - -StubData --> RunesManager -StubData --> "*" Champion -StubData --> "*" Rune -StubData --> "*" RunePages -StubData --> "*" Skins -``` \ No newline at end of file + + ## LOLProject + + + + +**LOLProject** est un projet reliant une API C# et EntityFramework afin de produire une API qui renvoie les informations d'une base de données SQLite sur un client MAUI + +Merci de noter la v1 de l'api qui est tenu a jour la v2 sert uniquement a montrer que nous pouvons versionner. + +## :floppy_disk: FEATURES + +- L'API dispose des principales requêtes CRUD sur les champions, skills, skins, runes, runepages aussi consultables sur le swagger UI. +- L'ORM réalisé avec EntityFramework afin d'enregistrer dans une base de données SQLite +- L'application MAUI pour faire des requêtes depuis un client et les afficher. + + +![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png) + +## :dizzy: Getting Started + +Une fois le dépot cloné, vous pouvez lancer le code sur votre téléphone Android grâce à l'outil Android Studio ou grâce à un émulateur Android. + + +## Archutecture + +![](https://codefirst.iut.uca.fr/git/lucas.delanier/LOLProject/raw/branch/master/Documentations/Schema_architecture.png) +Ce schéma d'architecure globale permet de comprendre la composition interne de la solution. + +Sur la partie gauche on peut voir la partie client qui fait appel a l'api via des requetes http en utilisant les routes de l'api Rest Full. +Pour tout a fait comprendre, comment communiquent et fonctionnent les différentes briques de la solution nous allons vous détailler brique par brique, relation par relation les différentes point rouge du schéma. + +## 1 - La déserialization +Le client est une solution qui va intérragir avec notre api grace des requetes sur internet. Il nécessite donc impérativement d'une connexion internet afin de pouvoir communiquer grace a des requetes http(s). Une fois qu'il a récupéré les données demandé. Il doit transoformer ce document json en classe métier de son model. Cela s'appel la déserialization. Ce processus ce traduit ar le code suivant en C#. + +![](https://codefirst.iut.uca.fr/git/lucas.delanier/LOLProject/raw/branch/master/Documentations/Capture%20d%27%C3%A9cran%202023-03-26%20111526.png) + + +## 2 - La communication Client - Api + Maintenant que vous savez comment le client traite les données renvoyées par l'API, nous allons a présent voir comment ils communiquent entre eux. Cette communication se fait par des requetes http(s) sous la forme suivante. + +"codefirst.iut.uca.fr/containers/lucasdelanier-containerlol/api/v{version}/{controller}" + +Lors de l'appel de l'API, le client peut choisir la version ( v1, v2, etc) mais aussi indiquer le controlleur qu'il souhaite intérroger. Par exemple Champion lui permettra de récuperer des informations sur les champions que connait l'API. Il est aussi possible de rajouter de précisions en ajoutant par exemple un nom apres le controller pour demander les informations spécifique a un champion en particulié. Lors des communications, les objects sons traduit sous la forme DTO. Cela permet de controller l'envoie de certaines données au client comme pr exemple un id unique ou des données sensibles qui ne doivent pas etre connu par l'utilisateur. Voici un exemple. + +![](https://codefirst.iut.uca.fr/git/lucas.delanier/LOLProject/raw/branch/master/Documentations/Capture%20d%27%C3%A9cran%202023-03-26%20113439.png) + +Ci dessus on voit que l'object champion a une nouvelle "forme" ChampionDTO que l'on construit a partir des attributs d'un champion. Dans l'exemple, il reprend les memes informations qu'un champion mais on aurait put imaginer qu'il en perde certains que l'on ne veut pas renvoyer a l'utilisateur. Pour permettre le passage d'un DTO en object et d'un object en DTO il faut ce qu'on appel des Mappers. Voici l'exemple des méthodes ToModel() et ToDTO() + +![](https://codefirst.iut.uca.fr/git/lucas.delanier/LOLProject/raw/branch/master/Documentations/Capture%20d%27%C3%A9cran%202023-03-26%20113710.png) + +## 3 - L'utilisation du stub dans l'API + Avant de faire la relation avec une base de données. Il était impotant de pouvoir tester l'application avec un Stub qui est une classe contenant des listes d'object. Une sorte de base de données fictive. Pour permettre a l'api d'intéroger ce stub, il a fallut faire un manager spécialement destiné à l'utilisation du stub (StubData) qui hérite d'un manager commun qui est une interface composé des méthodes nécessaire a l'interrogation des données (IDataManager). + + ![](https://codefirst.iut.uca.fr/git/lucas.delanier/LOLProject/raw/branch/master/Documentations/Capture%20d%27%C3%A9cran%202023-03-26%20114811.png) + + + ## 4 - Lien entre API et Entityframework +... + + + ## 5 - Mappage des classes métier en tables +... + + ## 6 - Lien avec base de données SQLlite +... + + +## :wrench: SUPPORT +En cas de problème lors de l'utilisation de l'application, vous pouvez nous contacter aux adresses suivantes : + + +Lucas Delanier : **Lucas.DELANIER@etu.uca.fr**
+Louison Parant : **Louison.PARANT@etu.uca.fr** +![](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png) + + + +## ✨ Contributors + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/APILOL/Controllers/v2/ChampionsController.cs b/Sources/APILOL/Controllers/v2/ChampionsController.cs index 6e48806..279f98a 100644 --- a/Sources/APILOL/Controllers/v2/ChampionsController.cs +++ b/Sources/APILOL/Controllers/v2/ChampionsController.cs @@ -12,7 +12,7 @@ namespace APILOL.Controllers.v2 { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] - [ApiVersion("2")] + [ApiVersion("2.0")] public class ChampionsController : ControllerBase { @@ -24,18 +24,17 @@ namespace APILOL.Controllers.v2 { this.dataManager = dataManager.ChampionsMgr; this._logger = logger; - + } // GET: api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet] - public async Task Get([FromQuery] PageRequest request) { - _logger.LogInformation("API call - [GET] - CHAMPION"); + _logger.LogInformation("API call - [GET] - CHAMPION "); try { @@ -44,48 +43,50 @@ namespace APILOL.Controllers.v2 IEnumerable items = champions.Select(c => c.ToDto()); if (items.Count() == 0) { - _logger.LogInformation("No champion found."); + _logger.LogError("No champion found."); return NotFound("No champion found."); } return Ok(new { data = items, count = await dataManager.GetNbItems(), offset = request.Offset, limit = request.Limit }); } - catch(Exception error) + catch (Exception error) { + _logger.LogInformation("Error in the request"); return BadRequest(error.Message); } - + } // GET api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet("{name}")] - public async Task Get([FromQuery] PageRequest request,string name) + public async Task Get([FromQuery] PageRequest request, string name) { - _logger.LogInformation("API call - [GET / NAME] - CHAMPION"); + _logger.LogInformation("API call - [GET / NAME] - CHAMPION {name}", name); try { if (dataManager.GetNbItemsByName(name) != null) { var champions = await dataManager.GetItemsByName(name, request.Offset, request.Limit, request.OrderingPropertyName, request.IsDesc); - IEnumerable items = champions.Select(c => c.ToDto()); + IEnumerable items = champions.Select(c => c.ToDto()); if (items.Count() == 0) { - _logger.LogInformation("No champion found."); + _logger.LogError("No champion found."); return NotFound("No champion found."); } - return Ok(items); + return Ok(new { data = items, count = dataManager.GetNbItems() }); } return NotFound("No champion matching with this name."); } catch (Exception error) { + _logger.LogInformation("Error in the request"); return BadRequest(error.Message); } } // POST api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPost] public async Task Post([FromBody] ChampionDTO championDTO) { @@ -93,12 +94,12 @@ namespace APILOL.Controllers.v2 try { - if(await dataManager.GetNbItemsByName(championDTO.Name) == 0) + if (await dataManager.GetNbItemsByName(championDTO.Name) == 0) { await dataManager.AddItem(championDTO.ToModel()); return CreatedAtAction(nameof(Get), championDTO); } - _logger.LogInformation("A champion already exist with this Name. ( Unique Name )"); + _logger.LogError("A champion already exist with this Name. ( Unique Name )"); return BadRequest("A champion already exist with this Name. ( Unique Name )"); } catch (Exception error) @@ -109,7 +110,7 @@ namespace APILOL.Controllers.v2 } // PUT api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] ChampionDTO championDTO) { @@ -118,24 +119,24 @@ namespace APILOL.Controllers.v2 { var champion = await dataManager .GetItemsByName(name, 0, await dataManager.GetNbItems()); - Console.WriteLine(champion.First().Name) ; + Console.WriteLine(champion.First().Name); var champion2 = await dataManager .GetItemsByName(championDTO.Name, 0, await dataManager.GetNbItems()); if (champion != null) { - if(champion2.Count() == 0) + if (champion2.Count() == 0) { await dataManager.UpdateItem(champion.First(), championDTO.ToModel()); return Ok(); } - _logger.LogInformation("champion already exist with this unique name."); + _logger.LogError("champion already exist with this unique name."); return BadRequest("champion already exist with this unique name."); } else { - _logger.LogInformation("champion not found."); + _logger.LogError("champion not found."); return NotFound("champion not found."); } await dataManager.UpdateItem(champion.First(), championDTO.ToModel()); @@ -144,13 +145,14 @@ namespace APILOL.Controllers.v2 } catch (Exception e) { + _logger.LogInformation("Error in the request"); return BadRequest(e.Message); } } // DELETE api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpDelete("{name}")] public async Task Delete(string name) { @@ -158,7 +160,7 @@ namespace APILOL.Controllers.v2 try { var champion = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); - + if (champion.Count() != 0) { var championDto = champion.First().ToDto(); @@ -167,13 +169,14 @@ namespace APILOL.Controllers.v2 } else { - _logger.LogInformation("No matching Champion with this name"); + _logger.LogError("No matching Champion with this name"); return NotFound("No matching Champion with this name"); } - + } - catch(Exception error) + catch (Exception error) { + _logger.LogInformation("Error in the request"); return BadRequest(error); } } diff --git a/Sources/APILOL/Controllers/v2/RuneController.cs b/Sources/APILOL/Controllers/v2/RuneController.cs index f76b628..cdbde5c 100644 --- a/Sources/APILOL/Controllers/v2/RuneController.cs +++ b/Sources/APILOL/Controllers/v2/RuneController.cs @@ -11,7 +11,7 @@ namespace APILOL.Controllers.v2 { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] - [ApiVersion("2")] + [ApiVersion("2.0")] public class RuneController : ControllerBase { IRunesManager dataManager; @@ -28,7 +28,7 @@ namespace APILOL.Controllers.v2 // GET: api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -54,7 +54,7 @@ namespace APILOL.Controllers.v2 } // GET api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { @@ -82,7 +82,7 @@ namespace APILOL.Controllers.v2 } // POST api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPost] public async Task Post([FromBody] RuneDTO runeDTO) { @@ -106,7 +106,7 @@ namespace APILOL.Controllers.v2 } // PUT api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] RuneDTO runeDTO) { @@ -147,7 +147,7 @@ namespace APILOL.Controllers.v2 } // DELETE api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Controllers/v2/RunePageController.cs b/Sources/APILOL/Controllers/v2/RunePageController.cs index 2c1e278..64ae8dd 100644 --- a/Sources/APILOL/Controllers/v2/RunePageController.cs +++ b/Sources/APILOL/Controllers/v2/RunePageController.cs @@ -11,7 +11,7 @@ namespace APILOL.Controllers.v2 { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] - [ApiVersion("2")] + [ApiVersion("2.0")] public class RunePageController : ControllerBase { IRunePagesManager dataManager; @@ -28,7 +28,7 @@ namespace APILOL.Controllers.v2 // GET: api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -54,11 +54,11 @@ namespace APILOL.Controllers.v2 } // GET api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { - _logger.LogInformation("API call - [GET / NAME] - RUNEPAGE {name}",name); + _logger.LogInformation("API call - [GET / NAME] - RUNEPAGE"); try { if (dataManager.GetNbItemsByName(name) != null) @@ -82,7 +82,7 @@ namespace APILOL.Controllers.v2 } // POST api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPost] public async Task Post([FromBody] RunePageDTO runePageDTO) { @@ -106,11 +106,11 @@ namespace APILOL.Controllers.v2 } // PUT api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] RunePageDTO runePageDTO) { - _logger.LogInformation("API call - [PUT / NAME] - RUNEPAGE {name}", name); + _logger.LogInformation("API call - [PUT / NAME] - RUNEPAGE"); try { var runePage = await dataManager @@ -147,11 +147,11 @@ namespace APILOL.Controllers.v2 } // DELETE api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpDelete("{name}")] public async Task Delete(string name) { - _logger.LogInformation("API call - [DELETE / NAME] - RUNEPAGE {name}", name); + _logger.LogInformation("API call - [DELETE / NAME] - RUNEPAGE"); try { var runePage = await (dataManager.GetItemsByName(name, 0, await dataManager.GetNbItems())); diff --git a/Sources/APILOL/Controllers/v2/SkinController.cs b/Sources/APILOL/Controllers/v2/SkinController.cs index 9ac47c0..4199383 100644 --- a/Sources/APILOL/Controllers/v2/SkinController.cs +++ b/Sources/APILOL/Controllers/v2/SkinController.cs @@ -8,7 +8,7 @@ namespace APILOL.Controllers.v2 { [ApiController] [Route("api/v{version:apiVersion}/[controller]")] - [ApiVersion("2")] + [ApiVersion("2.0")] public class SkinController : ControllerBase { @@ -26,7 +26,7 @@ namespace APILOL.Controllers.v2 // GET: api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet] public async Task Get([FromQuery] PageRequest request) { @@ -52,11 +52,11 @@ namespace APILOL.Controllers.v2 } // GET api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpGet("{name}")] public async Task Get([FromQuery] PageRequest request, string name) { - _logger.LogInformation("API call - [GET / NAME] - SKIN {name}", name); + _logger.LogInformation("API call - [GET / NAME] - SKIN"); try { if (dataManager.GetNbItemsByName(name) != null) @@ -80,11 +80,11 @@ namespace APILOL.Controllers.v2 } // POST api/ - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPost] public async Task Post([FromBody] SkinDTO skinDTO) { - _logger.LogInformation("API call - [POST] - SKIN "); + _logger.LogInformation("API call - [POST] - SKIN"); try { @@ -104,7 +104,7 @@ namespace APILOL.Controllers.v2 } // PUT api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpPut("{name}")] public async Task PutAsync(string name, [FromBody] SkinDTO skinDTO) { @@ -145,7 +145,7 @@ namespace APILOL.Controllers.v2 } // DELETE api//5 - [MapToApiVersion("2")] + [MapToApiVersion("2.0")] [HttpDelete("{name}")] public async Task Delete(string name) { diff --git a/Sources/APILOL/Mapper/ChampionMapper.cs b/Sources/APILOL/Mapper/ChampionMapper.cs index d8c0bd5..4e276ba 100644 --- a/Sources/APILOL/Mapper/ChampionMapper.cs +++ b/Sources/APILOL/Mapper/ChampionMapper.cs @@ -15,8 +15,7 @@ namespace APILOL.Mapper Class = champion.Class, Icon = champion.Icon, Image = champion.Image, - Characteristics = champion.Characteristics, - Skills = champion.Skills, + Skills = champion.Skills.Select(skill => skill.ToDto()), }; } diff --git a/Sources/APILOL/Mapper/SkillMapper.cs b/Sources/APILOL/Mapper/SkillMapper.cs new file mode 100644 index 0000000..f8c0364 --- /dev/null +++ b/Sources/APILOL/Mapper/SkillMapper.cs @@ -0,0 +1,23 @@ +using DTO; +using Model; + +namespace APILOL.Mapper +{ + public static class SkillMapper + { + public static SkillDTO ToDto(this Skill skill) + { + return new SkillDTO() + { + Type = skill.Type, + Name = skill.Name, + Description = skill.Description + }; + } + + public static Skill ToModel(this SkillDTO skill) + { + return new Skill(skill.Name, skill.Type, skill.Description); + } + } +} diff --git a/Sources/DTO/ChampionDTO.cs b/Sources/DTO/ChampionDTO.cs index 12eb51f..82b6030 100644 --- a/Sources/DTO/ChampionDTO.cs +++ b/Sources/DTO/ChampionDTO.cs @@ -16,8 +16,7 @@ namespace DTO public LargeImage Image { get; set; } - public ReadOnlyDictionary Characteristics { get; set; } - public ImmutableHashSet Skills { get; set; } + public IEnumerable Skills { get; set; } } } \ No newline at end of file diff --git a/Sources/DTO/SkillDTO.cs b/Sources/DTO/SkillDTO.cs index 0f53f56..2b66a28 100644 --- a/Sources/DTO/SkillDTO.cs +++ b/Sources/DTO/SkillDTO.cs @@ -15,4 +15,6 @@ namespace DTO public string Description { get; set; } } + + } diff --git a/Sources/EntityFrameworkLOL/Program.cs b/Sources/EntityFrameworkLOL/Program.cs index 07c35d6..4fbb5ba 100644 --- a/Sources/EntityFrameworkLOL/Program.cs +++ b/Sources/EntityFrameworkLOL/Program.cs @@ -8,169 +8,5 @@ class Program { static void Main(string[] args) { - using (var context = new SQLiteContext()) { - if (context.Champion.Count() > 0) - { - foreach (var c in context.Champion.ToArray()) - { - context.Champion.Remove(c); - } - } - if (context.Rune.Count() > 0) - { - foreach (var r in context.Rune.ToArray()) - { - context.Rune.Remove(r); - } - } - if (context.Skin.Count() > 0) - { - foreach (var s in context.Skin.ToArray()) - { - context.Skin.Remove(s); - } - } - if (context.Skill.Count() > 0) - { - foreach (var s in context.Skill.ToArray()) - { - context.Skill.Remove(s); - } - } - if (context.RunePage.Count() > 0) - { - foreach (var rp in context.RunePage.ToArray()) - { - context.RunePage.Remove(rp); - } - } - if (context.ChampionClass.Count() > 0) - { - foreach (var cc in context.ChampionClass.ToArray()) - { - context.ChampionClass.Remove(cc); - } - } - if (context.RuneFamily.Count() > 0) - { - foreach (var rf in context.RuneFamily.ToArray()) - { - context.RuneFamily.Remove(rf); - } - } - if (context.SkillType.Count() > 0) - { - foreach (var st in context.SkillType.ToArray()) - { - context.SkillType.Remove(st); - } - } - if (context.Image.Count() > 0) - { - foreach (var i in context.Image.ToArray()) - { - context.Image.Remove(i); - } - } - context.SaveChanges(); - } - ChampionEntity akali = new ChampionEntity { Name = "Akali", Bio = "" }; - ChampionEntity aatrox = new ChampionEntity { Name = "Aatrox", Bio = "" }; - ChampionEntity ahri = new ChampionEntity { Name = "Ahri", Bio = "" }; - ChampionEntity bard = new ChampionEntity { Name = "Bard", Bio = "" }; - ChampionEntity alistar = new ChampionEntity { Name = "Alistar", Bio = "" }; - ChampionEntity akshan = new ChampionEntity { Name = "Akshan", Bio = "" }; - - using (var context = new SQLiteContext()) - { - // Crée des champions et les insère dans la base - Console.WriteLine("Creates and inserts new Champions"); - context.AddRange(new ChampionEntity[] { akali, aatrox, ahri, bard, alistar, akshan }); - /*context.Add(akali); - context.Add(aatrox); - context.Add(ahri); - context.Add(bard); - context.Add(alistar); - context.Add(akshan);*/ - context.SaveChanges(); - Console.WriteLine("Creates and executes a query retrieving the first Champion of the database whose name starts with an \"A\":"); - var aChampion = context.Champion - .Where(c => c.Name.StartsWith("A")) - .First(); - Console.WriteLine($"{aChampion.Name} (with bio : \"{aChampion.Bio}\")"); - } - - RuneEntity conqueror = new RuneEntity { Name = "Conqueror", Description = "" }; - RuneEntity thriumph = new RuneEntity { Name = "Thriumph", Description = "" }; - RuneEntity alacrity = new RuneEntity { Name = "Legend : Alacrity", Description = "" }; - RuneEntity tenacity = new RuneEntity { Name = "Legend : Tenacity", Description = "" }; - RuneEntity laststand = new RuneEntity { Name = "Last Stand", Description = "" }; - RuneEntity laststand2 = new RuneEntity { Name = "Last Stand 2", Description = "" }; - - using (var context = new SQLiteContext()) - { - // Crée des Runes et les insère dans la base - Console.WriteLine("Creates and inserts new Runes"); - context.AddRange(new RuneEntity[] { conqueror, thriumph, alacrity, tenacity, laststand, laststand2 }); - /*context.Add(conqueror); - context.Add(thriumph); - context.Add(alacrity); - context.Add(tenacity); - context.Add(laststand); - context.Add(laststand2);*/ - context.SaveChanges(); - Console.WriteLine("Creates and executes a query retrieving the first Runes of the database whose name starts with an \"L\":"); - var lRune = context.Rune - .Where(r => r.Name.StartsWith("L")) - .First(); - Console.WriteLine($"{lRune.Name} (with Description : \"{lRune.Description}\")"); - } - - SkinEntity stinger = new SkinEntity { Name = "Stinger", Description = "" }; - SkinEntity infernal = new SkinEntity { Name = "Infernal", Description = "" }; - SkinEntity allStar = new SkinEntity { Name = "All-Star", Description = "" }; - SkinEntity justicar = new SkinEntity { Name = "Justicar", Description = "" }; - SkinEntity mecha = new SkinEntity { Name = "Mecha", Description = "" }; - SkinEntity seaHunter = new SkinEntity { Name = "Sea Hunter", Description = "" }; - - using (var context = new SQLiteContext()) - { - // Crée des Skins et les insère dans la base - Console.WriteLine("Creates and inserts new Skins"); - context.AddRange(new SkinEntity[] { stinger, infernal, allStar, justicar, mecha, seaHunter }); - /*context.Add(stinger); - context.Add(infernal); - context.Add(allStar); - context.Add(justicar); - context.Add(mecha); - context.Add(seaHunter);*/ - context.SaveChanges(); - Console.WriteLine("Creates and executes a query retrieving the first Skins of the database whose name starts with an \"I\":"); - var iSkin = context.Skin - .Where(s => s.Name.StartsWith("I")) - .First(); - Console.WriteLine($"{iSkin.Name} (with Description : \"{iSkin.Description}\")"); - - Console.WriteLine("Updates the name of the Infernal Skin"); - iSkin.Description = "Hella Infernal (Wallah)"; - context.SaveChanges(); - Console.WriteLine($"{iSkin.Name} (with Description : \"{iSkin.Description}\")"); - - Console.WriteLine("Deletes one item from the database"); - var droid = context.Skin - .SingleOrDefault(s => s.Name.Equals("Infernal")); - context.Remove(droid); - context.SaveChanges(); - } - - using (var context = new SQLiteContext()) - { - foreach (var c in context.Champion) - { - c.Bio = $"{c.Name}"; - Console.WriteLine($"{c.Name} - {c.Bio}"); - } - context.SaveChanges(); - } } } \ No newline at end of file diff --git a/Sources/TestUnitaire/UnitTestChampion.cs b/Sources/TestUnitaire/UnitTestChampion.cs index f6c318b..bf9dff6 100644 --- a/Sources/TestUnitaire/UnitTestChampion.cs +++ b/Sources/TestUnitaire/UnitTestChampion.cs @@ -27,7 +27,6 @@ namespace TestUnitaire [TestMethod] public async Task TestGet() { - //Act var champions = await controller.Get(new PageRequest()); //Assert