@using SharedLibraryCore.Configuration @using Data.Models.Client.Stats @using Stats.Helpers @using Data.Models.Client @using Data.Models.Client.Stats.Reference @using Humanizer @using Humanizer.Localisation @using IW4MAdmin.Plugins.Stats @using WebfrontCore.ViewModels @using System.Text.Json @using IW4MAdmin.Plugins.Stats.Web.Dtos @model Stats.Dtos.AdvancedStatsInfo @{ ViewBag.Title = ViewBag.Localization["WEBFRONT_ADV_STATS_TITLE"]; ViewBag.Description = Model.ClientName.StripColors(); const string headshotKey = "MOD_HEAD_SHOT"; const string headshotKey2 = "head"; const string meleeKey = "MOD_MELEE"; var suicideKeys = new[] { "MOD_SUICIDE", "MOD_FALLING" }; // if they've not copied default settings config this could be null var config = (GameStringConfiguration)ViewBag.Config ?? new GameStringConfiguration(); string GetWeaponNameForHit(EFClientHitStatistic stat) { if (stat == null) { return null; } var rebuiltName = stat.RebuildWeaponName(); var name = config.GetStringForGame(rebuiltName, stat.Weapon?.Game); return !rebuiltName.Equals(name, StringComparison.InvariantCultureIgnoreCase) ? name : config.GetStringForGame(stat.Weapon.Name, stat.Weapon.Game); } string GetWeaponAttachmentName(EFWeaponAttachmentCombo attachment) { if (attachment == null) { return null; } var attachmentText = string.Join(" + ", new[] { config.GetStringForGame(attachment.Attachment1.Name, attachment.Attachment1.Game), config.GetStringForGame(attachment.Attachment2?.Name, attachment.Attachment2?.Game), config.GetStringForGame(attachment.Attachment3?.Name, attachment.Attachment3?.Game) }.Where(attach => !string.IsNullOrWhiteSpace(attach))); return attachmentText; } var weapons = Model.ByWeapon .Where(hit => hit.DamageInflicted > 0 || (hit.DamageInflicted == 0 && hit.HitCount > 0)) .GroupBy(hit => new { hit.WeaponId }) .Select(group => { var withoutAttachments = group.FirstOrDefault(hit => hit.WeaponAttachmentComboId == null); var mostUsedAttachment = group.Except(new[] { withoutAttachments }) .OrderByDescending(g => g.DamageInflicted) .GroupBy(g => g.WeaponAttachmentComboId) .FirstOrDefault() ?.FirstOrDefault(); if (withoutAttachments == null || mostUsedAttachment == null) { return withoutAttachments; } withoutAttachments.WeaponAttachmentComboId = mostUsedAttachment.WeaponAttachmentComboId; withoutAttachments.WeaponAttachmentCombo = mostUsedAttachment.WeaponAttachmentCombo; return withoutAttachments; }) .Where(hit => hit != null) .OrderByDescending(hit => hit.KillCount) .ToList(); var allPerServer = Model.All.Where(hit => hit.ServerId == Model.ServerId).ToList(); // if the serverId is supplied we want all the entries with serverID but nothing else var aggregate = Model.ServerId == null ? Model.Aggregate : allPerServer.Where(hit => hit.WeaponId == null) .Where(hit => hit.HitLocation == null) .Where(hit => hit.ServerId == Model.ServerId) .Where(hit => hit.WeaponAttachmentComboId == null) .FirstOrDefault(hit => hit.MeansOfDeathId == null); var filteredHitLocations = Model.ByHitLocation .Where(hit => hit.HitCount > 0) .Where(hit => hit.HitLocation.Name != "none") .Where(hit => hit.HitLocation.Name != "neck") .Where(hit => hit.ServerId == Model.ServerId) .OrderByDescending(hit => hit.HitCount) .ThenBy(hit => hit.HitLocationId) .ToList(); var uniqueWeapons = allPerServer.Any() ? Model.ByWeapon.Where(hit => hit.ServerId == Model.ServerId) .Where(weapon => weapon.DamageInflicted > 0) .GroupBy(weapon => weapon.WeaponId) .Count() : (int?)null; // want to default to -- in ui instead of 0 var activeTime = weapons.Any() ? TimeSpan.FromSeconds(weapons.Sum(weapon => weapon.UsageSeconds ?? 0)) : (TimeSpan?)null; // want to default to -- in ui instead of 0 var kdr = aggregate == null ? null : Math.Round(aggregate.KillCount / (float)aggregate.DeathCount, 2).ToString(Utilities.CurrentLocalization.Culture); var serverLegacyStat = Model.LegacyStats .FirstOrDefault(stat => stat.ServerId == Model.ServerId); // legacy stats section var performance = Model.Performance; var skill = Model.ServerId != null ? serverLegacyStat?.Skill.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.Skill), 0).ToNumericalString(); var elo = Model.ServerId != null ? serverLegacyStat?.EloRating.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.EloRating), 0).ToNumericalString(); var spm = Model.ServerId != null ? serverLegacyStat?.SPM.ToNumericalString() : Model.LegacyStats.WeightValueByPlaytime(nameof(EFClientStatistics.SPM), 0).ToNumericalString(); var performanceHistory = Model.Ratings .OrderBy(rating => rating.CreatedDateTime) .Select(rating => new PerformanceHistory { Performance = rating.PerformanceMetric, OccurredAt = rating.CreatedDateTime }); if (performance != null && performance != Model.Ratings.FirstOrDefault().PerformanceMetric) { performanceHistory = performanceHistory.Append(new PerformanceHistory { Performance = performance.Value, OccurredAt = Model.Ratings.FirstOrDefault()?.CreatedDateTime ?? DateTime.UtcNow }); } var score = allPerServer.Any() ? allPerServer.Sum(stat => stat.Score) : null; var headShots = allPerServer.Any() ? allPerServer.Where(hit => hit.MeansOfDeath?.Name == headshotKey || (hit.HitLocation?.Name?.StartsWith(headshotKey2) ?? false)).Sum(hit => hit.HitCount) : (int?)null; // want to default to -- in ui instead of 0 var meleeKills = allPerServer.Any() ? allPerServer.Where(hit => hit.MeansOfDeath?.Name == meleeKey).Sum(hit => hit.KillCount) : (int?)null; var suicides = allPerServer.Any() ? allPerServer.Where(hit => suicideKeys.Contains(hit.MeansOfDeath?.Name ?? "")).Sum(hit => hit.KillCount) : (int?)null; var statCards = new[] { new { Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_KILLS"] as string).Titleize(), Value = aggregate?.KillCount.ToNumericalString() }, new { Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_DEATHS"] as string).Titleize(), Value = aggregate?.DeathCount.ToNumericalString() }, new { Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_KDR"] as string).Titleize(), Value = kdr }, new { Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_SCORE"] as string).Titleize(), Value = score.ToNumericalString() }, new { Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_ZSCORE"] as string), Value = Model.ZScore.ToNumericalString(2) }, new { Name = (ViewBag.Localization["PLUGINS_STATS_TEXT_SKILL"] as string).ToLower().Titleize(), Value = skill }, new { Name = (ViewBag.Localization["WEBFRONT_ADV_STATS_ELO"] as string).Titleize(), Value = elo }, new { Name = (ViewBag.Localization["PLUGINS_STATS_META_SPM"] as string).Titleize(), Value = spm }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_DAMAGE"] as string, Value = aggregate?.DamageInflicted.ToNumericalString() }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_SUICIDES"] as string, Value = suicides.ToNumericalString() }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_HEADSHOTS"] as string, Value = headShots.ToNumericalString() }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_MELEES"] as string, Value = meleeKills.ToNumericalString() }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_FAV_WEAP"] as string, Value = GetWeaponNameForHit(weapons.FirstOrDefault()) }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_FAV_ATTACHMENTS"] as string, Value = GetWeaponAttachmentName(weapons.FirstOrDefault()?.WeaponAttachmentCombo) }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_WEAPONS_USED"] as string, Value = uniqueWeapons.ToNumericalString() }, new { Name = ViewBag.Localization["WEBFRONT_ADV_STATS_TOTAL_ACTIVE_TIME"] as string, Value = activeTime?.HumanizeForCurrentCulture() } }; }