private void HandleDisconnectCalculations(EFClient client, HitState state) { // todo: this not added to states fast connect/disconnect var serverStats = state.Hits.FirstOrDefault(stat => stat.ServerId == state.Server.ServerId && stat.WeaponId == null && stat.WeaponAttachmentComboId == null && stat.HitLocationId == null && stat.MeansOfDeathId == null); if (serverStats == null) { _logger.LogWarning("No server hits were found for {serverId} on disconnect for {client}", state.Server.ServerId, client.ToString()); return; } var aggregate = state.Hits.FirstOrDefault(stat => stat.WeaponId == null && stat.WeaponAttachmentComboId == null && stat.HitLocationId == null && stat.MeansOfDeathId == null && stat.ServerId == null); if (aggregate == null) { _logger.LogWarning("No aggregate found for {serverId} on disconnect for {client}", state.Server.ServerId, client.ToString()); return; } var sessionScores = client.GetAdditionalProperty <List <(int, DateTime)> >(SessionScores); if (sessionScores == null) { _logger.LogWarning("No session scores available for {Client}", client.ToString()); return; } foreach (var stat in new[] { serverStats, aggregate }) { stat.Score ??= 0; if (sessionScores.Count == 0) { stat.Score += client.Score > 0 ? client.Score : client.GetAdditionalProperty <int?>(Helpers.StatManager.ESTIMATED_SCORE) ?? 0 * 50; } else { stat.Score += sessionScores.Sum(item => item.Item1) + (sessionScores.Last().Item1 == client.Score && (DateTime.Now - sessionScores.Last().Item2).TotalMinutes < 1 ? 0 : client.Score); } } }
private void RunCalculation(EFClientHitStatistic clientHit, HitInfo hitInfo, HitState hitState) { if (hitInfo.HitType == HitType.Kill || hitInfo.HitType == HitType.Damage) { if (clientHit.WeaponId != null) // we only want to calculate usage time for weapons { var timeElapsed = DateTime.Now - hitState.LastUsage; var isSameWeapon = clientHit.WeaponId == hitState.LastWeaponId; clientHit.UsageSeconds ??= 60; if (timeElapsed.HasValue && timeElapsed <= _maxActiveTime) { clientHit.UsageSeconds += // if it's the same weapon we can count the entire elapsed time // otherwise we split it to make a best guess (int)Math.Round(timeElapsed.Value.TotalSeconds / (isSameWeapon ? 1.0 : 2.0)); } hitState.LastUsage = DateTime.Now; } clientHit.DamageInflicted += hitInfo.Damage; clientHit.HitCount++; } if (hitInfo.HitType == HitType.Kill) { clientHit.KillCount++; } if (hitInfo.HitType == HitType.WasKilled || hitInfo.HitType == HitType.WasDamaged || hitInfo.HitType == HitType.Suicide) { clientHit.ReceivedHitCount++; clientHit.DamageReceived += hitInfo.Damage; } if (hitInfo.HitType == HitType.WasKilled) { clientHit.DeathCount++; } }
private async Task UpdateClientStatistics(int clientId, HitState locState = null) { if (!_clientHitStatistics.ContainsKey(clientId) && locState == null) { _logger.LogError("No {statsName} found for id {id}", nameof(EFClientHitStatistic), clientId); return; } var state = locState ?? _clientHitStatistics[clientId]; try { await using var context = _contextFactory.CreateContext(); context.Set <EFClientHitStatistic>().UpdateRange(state.Hits); await context.SaveChangesAsync(); } catch (Exception ex) { _logger.LogError(ex, "Could not update hit location stats for id {id}", clientId); } }