-
-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathEFClientStatistics.cs
130 lines (121 loc) · 3.85 KB
/
EFClientStatistics.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading;
using Data.Models.Server;
namespace Data.Models.Client.Stats
{
public class EFClientStatistics : SharedEntity
{
public EFClientStatistics()
{
ProcessingHit = new SemaphoreSlim(1, 1);
}
~EFClientStatistics()
{
ProcessingHit.Dispose();
}
public int ClientId { get; set; }
[ForeignKey("ClientId")]
public virtual EFClient Client { get; set; }
public long ServerId { get; set; }
[ForeignKey("ServerId")]
public virtual EFServer Server { get; set; }
[Required]
public int Kills { get; set; }
[Required]
public int Deaths { get; set; }
public double EloRating { get; set; }
public double ZScore { get; set; }
public DateTime? UpdatedAt { get; set; }
public virtual ICollection<EFHitLocationCount> HitLocations { get; set; }
public double RollingWeightedKDR { get; set; }
public double AverageSnapValue { get; set; }
public int SnapHitCount { get; set; }
[NotMapped]
public double Performance
{
get => Math.Round(EloRating * 1/3.0 + Skill * 2/3.0, 2);
}
[NotMapped]
public double KDR
{
get => Deaths == 0 ? Kills : Math.Round(Kills / (double)Deaths, 2);
}
[Required]
public double SPM { get; set; }
[Required]
public double Skill { get; set; }
[Required]
public int TimePlayed { get; set; }
[Required]
public double MaxStrain { get; set; }
[NotMapped]
public float AverageHitOffset =>
(float) Math.Round(
HitLocations.Sum(c => c.HitOffsetAverage) /
Math.Max(1, HitLocations.Count(c => c.HitOffsetAverage > 0)), 4);
[NotMapped]
public int SessionKills { get; set; }
[NotMapped]
public int SessionDeaths { get; set; }
[NotMapped]
public int KillStreak { get; set; }
[NotMapped]
public int DeathStreak { get; set; }
[NotMapped]
public DateTime LastStatCalculation { get; set; }
[NotMapped]
public int LastScore { get; set; }
[NotMapped]
public DateTime LastActive { get; set; }
[NotMapped]
public double MaxSessionStrain { get; set; }
public void StartNewSession()
{
KillStreak = 0;
DeathStreak = 0;
LastScore = 0;
_sessionScores.Add(0);
Team = 0;
}
[NotMapped]
public int SessionScore
{
set => _sessionScores[^1] = value;
get
{
lock (_sessionScores)
{
return new List<int>(_sessionScores).Sum();
}
}
}
[NotMapped]
public int RoundScore => _sessionScores[^1];
[NotMapped]
private readonly List<int> _sessionScores = new List<int> { 0 };
[NotMapped]
public int Team { get; set; }
[NotMapped]
public DateTime LastStatHistoryUpdate { get; set; } = DateTime.UtcNow;
[NotMapped]
public double SessionSPM { get; set; }
[NotMapped]
public SemaphoreSlim ProcessingHit { get; }
[NotMapped] public MatchData MatchData { get; } = new MatchData();
}
public class MatchData
{
public int Kills { get; set; }
public int Deaths { get; set; }
public double Kdr => Deaths == 0 ? Kills : Math.Round(Kills / (double) Deaths, 2);
public void StartNewMatch()
{
Kills = 0;
Deaths = 0;
}
}
}