exciting-aftermath/Portfolio.WebUI.Server/Components/Pages/PokemonRate.razor

438 lines
16 KiB
Plaintext

@page "/pokemonsleep/rate-pokemon"
@inject IPokemonService PokemonService
@inject IPokemonNatureService PokemonNatureService
@inject IPokemonSubskillService PokemonSubskillService
@inject NavigationManager Navigation
@attribute [StreamRendering]
@rendermode InteractiveServer
<PageTitle>Rate Pokémon</PageTitle>
<style>
.flip-container {
perspective: 1000px;
display: inline-block;
width: 250px;
height: 250px;
cursor: pointer;
}
.flipper {
transition: transform 0.6s;
transform-style: preserve-3d;
width: 100%;
height: 100%;
position: relative;
}
.flipped {
transform: rotateY(180deg);
}
.front, .back {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
}
.back {
transform: rotateY(180deg);
}
.badge {
width: 100px;
height: 30px;
color: white;
padding: 4px 8px;
border-radius: 30px;
}
.statText {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 13px;
}
.dozing {
background-color: #fcdc5e;
}
.snoozing {
background-color: #4ce8ed;
}
.slumbering {
background-color: #4588fb;
}
.berries {
background-color: #24d86b;
}
.ingredients {
background-color: #fdbe4d;
}
.skills {
background-color: #47a0fc;
}
.finalScore {
width: 30px;
height: 30px;
color: white;
padding: 4px 8px;
text-align: center;
vertical-align: middle;
border-radius: 3px;
}
</style>
<div class="card-header bg-secondary bg-gradient ml-0 py-3">
<div class="row">
<div class="col-12 text-center">
<h1 class="text-primary">Pokémon Sleep</h1>
</div>
</div>
</div>
@if (PokemonList == null || NatureList == null || SubskillList == null)
{
<p>Loading...</p>
}
else
{
<div class="w-75 mt-3 m-auto " style="box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);">
<div class="card-header bg-secondary bg-gradient ml-0 py-3">
<div class="row">
<div class="col-12 text-center">
<h2 class="text-info">Pokémon Rater</h2>
</div>
</div>
</div>
<!-- Section 1: Pokemon Selection -->
<div class="card-body p-4 col-12" >
<div class="row pb-3">
<div class="col-3">
<label for="pokemonSelect">Select Pokémon</label>
<select class="form-control form-control-lg" @bind="SelectedPokemonId">
<option value="" disabled selected>Choose your Pokémon...</option>
@foreach (var pokemon in PokemonList)
{
if(pokemon.IsVariation)
{
<option value="@pokemon.Id">@pokemon.PokemonId @pokemon.VariationName @pokemon.PokemonName</option>
}
else
{
<option value="@pokemon.Id">@pokemon.PokemonId @pokemon.PokemonName</option>
}
}
</select>
</div>
</div>
<!-- Section 2: Pokemon Rating -->
@if (SelectedPokemon != null)
{
<div class="border rounded p-3 row" >
<div class="d-flex align-top col">
<!-- Pokemon Interface -->
<div class="m-1 p-1 col-5" >
<!-- Image -->
@if (SelectedPokemon.IsVariation)
{
<div class="flip-container" @onclick="() => ToggleImage(SelectedPokemon.Id)">
<div class="flipper @(isShiny[SelectedPokemon.Id] ? "flipped" : "")">
<img class="front" src="/pokemon_images/normal/@(SelectedPokemon.IsVariation ? $"{SelectedPokemon.PokemonId}-{SelectedPokemon.VariationName.ToLower()}{SelectedPokemon.PokemonName.ToLower()}" : SelectedPokemon.PokemonId).png" />
<img class="back" src="/pokemon_images/shiny/@(SelectedPokemon.IsVariation ? $"{SelectedPokemon.PokemonId}-{SelectedPokemon.VariationName.ToLower()}{SelectedPokemon.PokemonName.ToLower()}" : SelectedPokemon.PokemonId).png" />
</div>
</div>
}
else
{
<div class="flip-container" @onclick="() => ToggleImage(SelectedPokemon.Id)">
<div class="flipper @(isShiny[SelectedPokemon.Id] ? "flipped" : "")">
<img class="front" src="/pokemon_images/normal/@(SelectedPokemon.IsVariation ? $"{SelectedPokemon.PokemonId}-{SelectedPokemon.VariationName.ToLower()}{SelectedPokemon.PokemonName.ToLower()}" : SelectedPokemon.PokemonId).png" />
<img class="back" src="/pokemon_images/shiny/@(SelectedPokemon.IsVariation ? $"{SelectedPokemon.PokemonId}-{SelectedPokemon.VariationName.ToLower()}{SelectedPokemon.PokemonName.ToLower()}" : SelectedPokemon.PokemonId).png" />
</div>
</div>
}
<div class="row">
<div class="col-7" >
<!-- Name -->
<div class="row mb-0">
@if (SelectedPokemon.IsVariation) // If a Variant
{
<h2 class="">@SelectedPokemon.VariationName @SelectedPokemon.PokemonName</h2>
}
else // Otherwise, Base Case
{
<h3 class="">@SelectedPokemon.PokemonName</h3>
}
</div>
<!-- Pokedex Number -->
<div class="mt-0">
<p class="col-4">Pokédex #<strong>@SelectedPokemon.PokemonId</strong></p>
</div>
</div>
<!-- Pokemon Sleep Stats-->
<div class="col-5 p-1 ">
<div class="row d-flex justify-content-between">
<div class="m-1 col badge @SelectedPokemon.SleepType.ToLower()"><p class="statText">@SelectedPokemon.SleepType</p></div>
<div class="m-1 col badge @SelectedPokemon.Speciality.ToLower()"><p class="statText">@SelectedPokemon.Speciality</p></div>
</div>
</div>
</div>
</div>
<!-- Nature / Subskill Selection Dropdowns-->
<div class="m-1 p-1 col " >
<h4 class="mb-3">Select Nature & Subskills</h4>
<!-- Nature -->
<div class="row">
<div class="col-12">
<label>Select Nature</label>
<select class="form-control form-control-lg mb-2" @bind="SelectedNatureId">
<option value="" disabled>Choose Nature...</option>
@foreach (var nature in NatureList)
{
<option value="@nature.Id">@nature.Nature</option>
}
</select>
</div>
</div>
<!-- Subskills -->
<div class="row">
<div class="col-4">
<label for="subskillSelect1">Select Level 10 Subskill</label>
<select id="subskillSelect1" class="form-control form-control-lg mb-2" @bind="subskillSelect1">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="col-4">
<label for="subskillSelect2">Select Level 25 Subskill</label>
<select id="subskillSelect2" class="form-control form-control-lg mb-2" @bind="subskillSelect2">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="col-4">
<label for="subskillSelect3">Select Level 50 Subskill</label>
<select id="subskillSelect3" class="form-control form-control-lg mb-2" @bind="subskillSelect3">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
</div>
</div>
<!-- Calculate -->
<div class="d-flex justify-content-between align-items-center mt-3">
<button class="btn btn-primary" @onclick="CalculateScore">Calculate Final Score</button>
<h4>Final Score: <span class="finalScore" style="background-color: @ScoreBackgroundColor">@FinalScore</span></h4>
</div>
</div>
}
</div>
</div>
}
@code {
private List<Pokemon> PokemonList;
private List<PokemonNature> NatureList;
private List<PokemonSubskill> SubskillList;
private Dictionary<int, bool> isShiny = new Dictionary<int, bool>();
private int _selectedPokemonId;
private int SelectedPokemonId
{
get => _selectedPokemonId;
set
{
_selectedPokemonId = value;
OnPokemonSelected();
}
}
private int SelectedNatureId;
private int subskillSelect1;
private int subskillSelect2;
private int subskillSelect3;
private int[] SelectedSubskills = new int[3];
private Pokemon SelectedPokemon;
private int FinalScore;
private string ScoreBackgroundColor;
private string ScoreColor;
private string PokemonImageUrl => SelectedPokemon != null
? $"https://www.serebii.net/pokemonsleep/pokemon/{SelectedPokemon.Id}.png"
: string.Empty;
protected override async Task OnInitializedAsync()
{
PokemonList = await PokemonService.GetAllPokemonAsync();
NatureList = await PokemonNatureService.GetAllPokemonNaturesAsync();
SubskillList = await PokemonSubskillService.GetAllPokemonSubskillsAsync();
if (PokemonList is not null)
{
PokemonList.Sort((x, y) => x.PokemonId.CompareTo(y.PokemonId));
// Initialize dictionary with false (show base image first)
foreach (var pokemon in PokemonList)
{
isShiny[pokemon.Id] = false;
}
}
}
private async void OnPokemonSelected()
{
if (SelectedPokemonId > 0)
{
SelectedPokemon = await PokemonService.GetPokemonByIdAsync(SelectedPokemonId);
StateHasChanged(); // Force UI to refresh
}
}
private void ToggleImage(int Id)
{
if (isShiny.ContainsKey(Id))
{
isShiny[Id] = !isShiny[Id];
}
}
private void CalculateScore()
{
if (SelectedPokemon == null || SelectedNatureId == 0 || subskillSelect1 == 0 || subskillSelect2 == 0 || subskillSelect3 == 0 )
{
return;
}
var nature = NatureList.FirstOrDefault(n => n.Id == SelectedNatureId);
var subskill1 = SubskillList.FirstOrDefault(s => s.Id == subskillSelect1);
var subskill2 = SubskillList.FirstOrDefault(s => s.Id == subskillSelect2);
var subskill3 = SubskillList.FirstOrDefault(s => s.Id == subskillSelect3);
if (nature == null || subskill1 == null || subskill2 == null || subskill3 == null)
{
return;
}
FinalScore = SelectedPokemon.Speciality switch
{
"Berries" => nature.BerryRating + subskill1.BerryRank + subskill2.BerryRank + subskill3.BerryRank,
"Ingredients" => nature.IngredientRating + subskill1.IngredientRank + subskill2.IngredientRank + subskill3.IngredientRank,
"Skills" => nature.SkillRating + subskill1.SkillRank + subskill2.SkillRank + subskill3.SkillRank,
_ => 0
};
ScoreBackgroundColor = FinalScore switch
{
8 => "#16C47F",
7 => "#33CB8F",
6 => "#50D39F",
5 => "#6DDAAF",
4 => "#8BE2BF",
3 => "#A8E9CF",
2 => "#C5F0DF",
1 => "#E2F8EF",
0 => "#FFFFFF",
-1 => "#FFE7E7",
-2 => "#FED0D0",
-3 => "#FEB8B8",
-4 => "#FDA0A0",
-5 => "#FD8888",
-6 => "#FC7171",
-7 => "#FC5959",
-8 => "#FB4141",
_ => "#FFFFFF"
};
ScoreColor = FinalScore switch
{
8 => "#FFFFFF",
7 => "#FFFFFF",
6 => "#FFFFFF",
5 => "#FFFFFF",
4 => "#FFFFFF",
3 => "#FFFFFF",
2 => "#FFFFFF",
1 => "#FFFFFF",
0 => "#000",
-1 => "#FFFFFF",
-2 => "#FFFFFF",
-3 => "#FFFFFF",
-4 => "#FFFFFF",
-5 => "#FFFFFF",
-6 => "#FFFFFF",
-7 => "#FFFFFF",
-8 => "#FFFFFF",
_ => "#FFFFFF"
};
}
}