mirror of
https://github.com/DrMboga/WotBlitzStatisticsBlazor.git
synced 2026-10-21 02:17:20 +02:00
14 files changed
+170
-24
No files matched your search
@@ -6,6 +6,12 @@ namespace WotBlitzStatisticsPro.Blazor.Helpers
|
||||
{
|
||||
public static class DateDifferenceHelper
|
||||
{
|
||||
public static DateTime ConvertToLocalTime(this DateTimeOffset dateToConvert)
|
||||
{
|
||||
var specifiedTimeConvert = DateTime.SpecifyKind(dateToConvert.DateTime, DateTimeKind.Utc);
|
||||
return specifiedTimeConvert.ToLocalTime();
|
||||
}
|
||||
|
||||
public static string SinceTime(this int timeInLinuxTimeStamp, IStringLocalizer<App> localizer)
|
||||
{
|
||||
var currentDate = DateTime.Now;
|
||||
@@ -25,6 +31,11 @@ namespace WotBlitzStatisticsPro.Blazor.Helpers
|
||||
}
|
||||
|
||||
public static string SinceTime(this DateTimeOffset time, IStringLocalizer<App> localizer)
|
||||
{
|
||||
return time.DateTime.SinceTime(localizer);
|
||||
}
|
||||
|
||||
public static string SinceTime(this DateTime time, IStringLocalizer<App> localizer)
|
||||
{
|
||||
var currentDate = DateTime.Now;
|
||||
|
||||
@@ -41,6 +52,7 @@ namespace WotBlitzStatisticsPro.Blazor.Helpers
|
||||
return $"{difference.value} {ago}";
|
||||
}
|
||||
|
||||
|
||||
public static (int value, TimeInterval interval) ParseTheDifference(TimeSpan difference)
|
||||
{
|
||||
if (difference.TotalHours < 1)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using WotBlitzStatisticsPro.Blazor.GraphQl;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Blazor.Helpers
|
||||
{
|
||||
public static class TanksHelper
|
||||
{
|
||||
public static ITank FindMostRelevantTank(this IReadOnlyList<ITank> allTanks)
|
||||
{
|
||||
const int topTanksToMerge = 6;
|
||||
if (allTanks.Count == 1)
|
||||
{
|
||||
return allTanks.First();
|
||||
}
|
||||
|
||||
// Merge 6 tanks with max battles with 6 tanks with max Wn7, then with 6 tanks with max AvgDamage then with 6 tanks with Max Win rate. And sort result by max AvgXp and take first
|
||||
|
||||
var topByBattles = allTanks
|
||||
.OrderByDescending(t => t.Battles)
|
||||
.Take(topTanksToMerge)
|
||||
.Select(t => t.TankId)
|
||||
.ToList();
|
||||
var topByWn7 = allTanks
|
||||
.Where(t => topByBattles.Contains(t.TankId))
|
||||
.OrderByDescending(t => t.Wn7)
|
||||
.Take(topTanksToMerge)
|
||||
.Select(t => t.TankId)
|
||||
.ToList();
|
||||
var topByDamage = allTanks
|
||||
.Where(t => topByBattles.Contains(t.TankId))
|
||||
.OrderByDescending(t => t.AvgDamage)
|
||||
.Take(topTanksToMerge)
|
||||
.Select(t => t.TankId)
|
||||
.ToList();
|
||||
var topByWinRate = allTanks
|
||||
.Where(t => topByBattles.Contains(t.TankId))
|
||||
.OrderByDescending(t => t.WinRate)
|
||||
.Take(topTanksToMerge)
|
||||
.Select(t => t.TankId)
|
||||
.ToList();
|
||||
|
||||
var firstIntersection = topByBattles.Intersect(topByWn7).ToList();
|
||||
if (!firstIntersection.Any())
|
||||
{
|
||||
return allTanks.First(t => t.TankId == topByBattles.First());
|
||||
}
|
||||
if(firstIntersection.Count() == 1)
|
||||
{
|
||||
return allTanks.First(t => t.TankId == firstIntersection.First());
|
||||
}
|
||||
|
||||
var secondIntersection = topByDamage.Intersect(firstIntersection).ToList();
|
||||
if (!secondIntersection.Any())
|
||||
{
|
||||
return allTanks.First(t => t.TankId == firstIntersection.First());
|
||||
}
|
||||
if (secondIntersection.Count() == 1)
|
||||
{
|
||||
return allTanks.First(t => t.TankId == secondIntersection.First());
|
||||
}
|
||||
|
||||
var thirdIntersection = topByWinRate.Intersect(secondIntersection).ToList();
|
||||
if (!thirdIntersection.Any())
|
||||
{
|
||||
return allTanks.First(t => t.TankId == secondIntersection.First());
|
||||
}
|
||||
if (thirdIntersection.Count() == 1)
|
||||
{
|
||||
return allTanks.First(t => t.TankId == thirdIntersection.First());
|
||||
}
|
||||
|
||||
return allTanks
|
||||
.Where(t => thirdIntersection.Contains(t.TankId))
|
||||
.OrderByDescending(t => t.AvgXp)
|
||||
.First();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<small>@Localize["Created"]: <b>@AccountInfo.CreatedAt.ToString("d") | @AccountInfo.CreatedAt.SinceTime(Localize)</b></small>
|
||||
</div>
|
||||
<div>
|
||||
@Localize["Last battle"]: <b>@AccountInfo.LastBattleTime.ToString("g") | @AccountInfo.LastBattleTime.SinceTime(Localize)</b>
|
||||
@Localize["Last battle"]: <b>@AccountInfo.LastBattleTime.ConvertToLocalTime().ToString("g") | @AccountInfo.LastBattleTime.ConvertToLocalTime().SinceTime(Localize)</b>
|
||||
</div>
|
||||
</div>
|
||||
<RadzenTabs >
|
||||
@@ -29,6 +29,7 @@
|
||||
<PlayerInfoStatistics TanksList="@AccountInfo.Tanks"></PlayerInfoStatistics>
|
||||
</RadzenTabsItem>
|
||||
<RadzenTabsItem Icon="agriculture">
|
||||
@*TODO: In case of @SmallScreen == true, then show new tanks list component - mobile version *@
|
||||
<PlayerInfoTanksList TanksList="@AccountInfo.Tanks"></PlayerInfoTanksList>
|
||||
</RadzenTabsItem>
|
||||
<RadzenTabsItem Icon="military_tech">
|
||||
|
||||
@@ -22,6 +22,9 @@ namespace WotBlitzStatisticsPro.Blazor.Pages
|
||||
[Inject]
|
||||
public INotificationsService Notifications { get; set; }
|
||||
|
||||
[Inject]
|
||||
public IMediaQueriesService MediaQueriesService { get; set; }
|
||||
|
||||
|
||||
[Parameter]
|
||||
public long AccountId { get; set; }
|
||||
@@ -32,12 +35,16 @@ namespace WotBlitzStatisticsPro.Blazor.Pages
|
||||
|
||||
public IReadOnlyList<ISection> AchievementsBySection { get; set; }
|
||||
|
||||
public bool SmallScreen { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var loggedInInfo = await LocalStorageService.GetItemAsync<LoginInfo>(Constants.LoginInfoLocalStorageKey);
|
||||
var settings = await LocalStorageService.ReadSettings();
|
||||
CurrentRealmType = settings.RealmType;
|
||||
|
||||
SmallScreen = await MediaQueriesService.IsScreenWidthLessThen(1000);
|
||||
|
||||
try
|
||||
{
|
||||
// Maybe add refresh button instead of calling mutation each time
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<TankCard Tank=@MaxXpTank></TankCard>
|
||||
}
|
||||
</div>
|
||||
<div class="col-md-3 col-lg-3 align-items-center d-flex">
|
||||
<div class="col-md-3 col-lg-3 align-items-center d-flex">
|
||||
<div style="width: 100px; margin: 3px;">
|
||||
@Localize["Tank with Max frags"] (@AccountInfo.MaxFrags):
|
||||
</div>
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
MostRelevantTank = AccountInfo?.Tanks?.Where(t => t.Battles > 50).OrderByDescending(t => t.Wn7).FirstOrDefault();
|
||||
MostRelevantTank = AccountInfo?.Tanks?.FindMostRelevantTank();
|
||||
MaxXpTank = AccountInfo?.Tanks?.FirstOrDefault(t => t.TankId == AccountInfo.MaxXpTankId);
|
||||
MaxFragsTank = AccountInfo?.Tanks?.FirstOrDefault(t => t.TankId == AccountInfo.MaxFragsTankId);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn TItem="ITank" Title="" Sortable="false" Filterable="false" Width="55px">
|
||||
<Template Context="data">
|
||||
<RadzenImage Path="@data.PreviewImage" style="width: 50px; height: 40px; border-radius: 8px;"
|
||||
<RadzenImage Path="@data.PreviewImage" style="width: 50px; height: 40px; border-radius: 8px;"
|
||||
MouseEnter="@(args => ShowTankTooltip(args, data.PreviewImage, data.TankNationId, new TooltipOptions(){ Style = "background-color:#2F3D43" }) )" />
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
@@ -94,7 +94,7 @@
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn TItem="ITank" Property="Battles" Filterable="false" Sortable="true" Title="⚔" Frozen="false" Width="70px" TextAlign="TextAlign.Center">
|
||||
<FooterTemplate>
|
||||
<b>@TotalBattles.ToString("N0")</b>
|
||||
<b>@TotalBattles.ToString("N0")</b>
|
||||
</FooterTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn TItem="ITank" Property="WinRate"
|
||||
@@ -105,7 +105,7 @@
|
||||
Width="50px"
|
||||
TextAlign="TextAlign.Center">
|
||||
<Template Context="data">
|
||||
@data.WinRate.ToString("N0")%
|
||||
<span title="@($"{data.Wins:N0} / {data.Battles:N0}")">@data.WinRate.ToString("N0")%</span>
|
||||
<div style="background-color: @data.WinRate.ScaleColor(); width: 100%; height: 5px; margin-left: 2px; margin-right: 2px;"></div>
|
||||
</Template>
|
||||
<FooterTemplate>
|
||||
@@ -119,8 +119,7 @@
|
||||
Title="@Localize["Wn7"]"
|
||||
Frozen="false"
|
||||
Width="80px"
|
||||
TextAlign="TextAlign.Center"
|
||||
>
|
||||
TextAlign="TextAlign.Center">
|
||||
<Template Context="data">
|
||||
@data.Wn7.ToString("N0")
|
||||
<div style="background-color: @data.Wn7.Wn7ScaleColor(); width: 100%; height: 5px; margin-left: 2px; margin-right: 2px;"></div>
|
||||
@@ -154,14 +153,14 @@
|
||||
<b>∼@AvgTotalXp.ToString("N0")</b>
|
||||
</FooterTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn TItem="ITank" Property="MaxXp"
|
||||
Filterable="false"
|
||||
Sortable="true"
|
||||
Title="🌟"
|
||||
Frozen="false"
|
||||
Width="80px"
|
||||
TextAlign="TextAlign.Center"
|
||||
FormatString="{0:N0}"/>
|
||||
<RadzenDataGridColumn TItem="ITank" Property="MaxXp"
|
||||
Filterable="false"
|
||||
Sortable="true"
|
||||
Title="🌟"
|
||||
Frozen="false"
|
||||
Width="80px"
|
||||
TextAlign="TextAlign.Center"
|
||||
FormatString="{0:N0}" />
|
||||
<RadzenDataGridColumn TItem="ITank" Property="SurvivalRate"
|
||||
Filterable="false"
|
||||
Sortable="true"
|
||||
@@ -174,15 +173,19 @@
|
||||
<b>∼@AvgSurvivalRate.ToString("N0")%</b>
|
||||
</FooterTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn TItem="ITank" Property="LastBattleTime"
|
||||
Filterable="false"
|
||||
Sortable="true"
|
||||
Title="⌚"
|
||||
Frozen="false"
|
||||
Width="100px"
|
||||
<RadzenDataGridColumn TItem="ITank" Property="LastBattleTime"
|
||||
Filterable="false"
|
||||
Sortable="true"
|
||||
Title="⌚"
|
||||
Frozen="false"
|
||||
Width="100px"
|
||||
TextAlign="TextAlign.Center"
|
||||
FormatString="{0:d}"
|
||||
SortOrder="SortOrder.Descending"/>
|
||||
SortOrder="SortOrder.Descending">
|
||||
<Template Context="data">
|
||||
@data.LastBattleTime.ConvertToLocalTime().ToString("g")
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
</Columns>
|
||||
</RadzenDataGrid>
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace WotBlitzStatisticsPro.Blazor
|
||||
builder.Services.AddScoped<TooltipService>();
|
||||
builder.Services.AddScoped<ISearchDialogService, SearchDialogService>();
|
||||
builder.Services.AddScoped<IChartsService, ChartService>();
|
||||
builder.Services.AddScoped<IMediaQueriesService, MediaQueriesService>();
|
||||
|
||||
builder.Services.AddMediatR(typeof(Program));
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Blazor.Services
|
||||
{
|
||||
public interface IMediaQueriesService
|
||||
{
|
||||
ValueTask<bool> IsScreenWidthLessThen(long widthInPx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Microsoft.JSInterop;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Blazor.Services
|
||||
{
|
||||
public class MediaQueriesService : IMediaQueriesService
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public MediaQueriesService(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public ValueTask<bool> IsScreenWidthLessThen(long widthInPx)
|
||||
{
|
||||
return _jsRuntime.InvokeAsync<bool>("mediaQueries.IsScreenWidthLessThen", widthInPx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@
|
||||
</RadzenSidebar>
|
||||
<RadzenFooter>
|
||||
<ChildContent>
|
||||
<RadzenLabel Text="WOT Blitz statistics, Copyright © 2021">
|
||||
<RadzenLabel Text=@($"WOT Blitz statistics {@Version} © 2021")>
|
||||
</RadzenLabel>
|
||||
<RadzenLink Text="DrMboga" Path="https://github.com/DrMboga/WotBlitzStatisticsBlazor" Target="_blank" Style="margin-left:5px;vertical-align:bottom;" />
|
||||
</ChildContent>
|
||||
|
||||
@@ -8,6 +8,7 @@ using Radzen.Blazor;
|
||||
using WotBlitzStatisticsPro.Blazor.Messages;
|
||||
using WotBlitzStatisticsPro.Blazor.Model;
|
||||
using WotBlitzStatisticsPro.Blazor.Services;
|
||||
using System.Reflection;
|
||||
|
||||
namespace WotBlitzStatisticsPro.Blazor.Shared
|
||||
{
|
||||
@@ -27,6 +28,8 @@ namespace WotBlitzStatisticsPro.Blazor.Shared
|
||||
public bool SidebarExpanded { get; set; } = false;
|
||||
public bool BodyExpanded { get; set; } = true;
|
||||
|
||||
public string Version { get; set; }
|
||||
|
||||
public Dictionary<string, CultureInfo> CultureInfos { get; set; } = new()
|
||||
{
|
||||
{ "en-US", new CultureInfo("en-US", false)},
|
||||
@@ -63,6 +66,7 @@ namespace WotBlitzStatisticsPro.Blazor.Shared
|
||||
//}
|
||||
|
||||
NotificationsService.MessageArrived += NotificationsService_MessageArrived;
|
||||
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||
}
|
||||
|
||||
private void NotificationsService_MessageArrived()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
||||
<AssemblyVersion>1.0.0.1</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="echarts/echarts.js"></script>
|
||||
<script src="echarts/echarts-interop.js"></script>
|
||||
<script src="media-queries.js"></script>
|
||||
<script>navigator.serviceWorker.register('service-worker.js');</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
var mediaQueries = mediaQueries || {};
|
||||
|
||||
mediaQueries.IsScreenWidthLessThen = function (width) {
|
||||
let mql = window.matchMedia(`(max-width: ${width}px)`);
|
||||
return mql.matches;
|
||||
};
|
||||
Reference in new issue
Block a user