private static Dictionary<int, PlayerPerformance> GeneratePlayerPerformanceIteration(Dictionary<int, PlayerPerformance> previousIteration, IOrderedEnumerable<Jam> jams, Dictionary<int, Dictionary<int, JamTeamData>> jamData, Dictionary<int, double> jamTotalPortionMap, Dictionary<int, Dictionary<int, JamPlayerEffectiveness>> jpe, AveragePenaltyCostPerJam avgPenCost) { Dictionary<int, PlayerPerformance> pps = new Dictionary<int, PlayerPerformance>(); foreach(Jam jam in jams) { var pe = jpe[jam.ID]; var grouped = pe.Values.GroupBy(p => p.TeamID); var team1Players = grouped.First().Select(p => previousIteration[p.PlayerID]); var team2Players = grouped.Last().Select(p => previousIteration[p.PlayerID]); IEnumerable<JamPlayerEffectiveness> jammers = pe.Values.Where(eff => eff.IsJammer); double team1Score = CalculateExpectedScore(team1Players, jammers, jam.BoutID); int team1ID = grouped.First().Key; double team2Score = CalculateExpectedScore(team2Players, jammers, jam.BoutID); foreach(var eff in pe.Values) { var previousPerformance = previousIteration[eff.PlayerID]; // get/set PlayerPerformance object if (!pps.ContainsKey(eff.PlayerID)) { pps[eff.PlayerID] = new PlayerPerformance { Player = previousPerformance.Player, Bouts = new List<BoutPerformance>() }; } PlayerPerformance curPP = pps[eff.PlayerID]; // get/set BoutPerformance object var prevBout = previousPerformance.Bouts.First(b => b.BoutID == jam.BoutID); BoutPerformance bp = null; if (!curPP.Bouts.Any() || curPP.Bouts.Last().BoutID != prevBout.BoutID ) { bp = new BoutPerformance { BoutID = prevBout.BoutID, AwayTeamName = prevBout.AwayTeamName, HomeTeamName = prevBout.HomeTeamName, BoutDate = prevBout.BoutDate, Jams = new List<JamPerformance>() }; if (prevBout.BlockerPerformance != null) { bp.BlockerPerformance = new RolledUpPerformanceData { TotalJamPortions = prevBout.BlockerPerformance.TotalJamPortions, TotalPenalties = prevBout.BlockerPerformance.TotalPenalties, TotalPenaltyCost = prevBout.BlockerPerformance.TotalPenaltyCost }; } if(prevBout.JammerPerformance != null) { bp.JammerPerformance = new RolledUpPerformanceData { TotalJamPortions = prevBout.JammerPerformance.TotalJamPortions, TotalPenalties = prevBout.JammerPerformance.TotalPenalties, TotalPenaltyCost = prevBout.JammerPerformance.TotalPenaltyCost }; } curPP.Bouts.Add(bp); } else { bp = curPP.Bouts.Last(); } JamTeamData jd = jamData[jam.ID][eff.TeamID]; JamPerformance prevJamPerformance = prevBout.Jams.First(j => j.JamID == jam.ID); double pointDifferential = 0; var playerPerf = prevJamPerformance.JammerJamPercentage > 0 ? previousPerformance.JammerPerformance : previousPerformance.BlockerPerformance; double playerScore = playerPerf.TotalPointsVersusMedian / playerPerf.TotalJamPortions; if(curPP.Player.TeamID == team1ID) { pointDifferential = jd.PointDelta - team1Score + team2Score + playerScore; } else { pointDifferential = jd.PointDelta - team2Score + team1Score + playerScore; } JamPerformance jp = new JamPerformance { BlockerJamPercentage = prevJamPerformance.BlockerJamPercentage, DeltaPercentile = prevJamPerformance.DeltaPercentile, IsFirstHalf = prevJamPerformance.IsFirstHalf, JamID = prevJamPerformance.JamID, JammerJamPercentage = prevJamPerformance.JammerJamPercentage, JamNumber = prevJamPerformance.JamNumber, JamPenalties = prevJamPerformance.JamPenalties, MedianDelta = prevJamPerformance.MedianDelta, PenaltyCost = prevJamPerformance.PenaltyCost, PointDelta = jd.PointDelta, DeltaPortionVersusMedian = pointDifferential //PlayerValue }; bp.Jams.Add(jp); } } Parallel.ForEach(pps.Values, pp => { RollUpIteratedPlayerPerformance(avgPenCost, jamTotalPortionMap, pp); }); return pps; }
public IList<PlayerPerformance> GetPlayerPointPerformancesForTeam(int teamID) { // pull data SqlConnection connection = new SqlConnection(_connectionString); connection.Open(); SqlTransaction transaction = connection.BeginTransaction(); var players = new PlayerGateway(connection, transaction).GetPlayersForTeam(teamID).ToDictionary(p => p.ID); var jams = new JamGateway(connection, transaction).GetJamsForTeamAfterDate(teamID, new DateTime(2016,1,1)).OrderBy(j => j.ID); var jamBoutMap = jams.ToDictionary(j => j.ID, j => j.BoutID); var jpe = new JamPlayerEffectivenessGateway(connection, transaction).GetJamPlayerEffectivenessForTeam(teamID); var jamData = new JamDataGateway(connection, transaction).GetJamDataForTeam(teamID).ToDictionary(jd => jd.JamID); var teams = new TeamGateway(connection, transaction).GetAllTeams().ToDictionary(t => t.ID); var bouts = new BoutGateway(connection, transaction).GetBouts().ToDictionary(t => t.ID); var penalties = new PenaltyGateway(connection, transaction).GetPenaltiesForTeam(teamID) .GroupBy(p => p.JamID) .ToDictionary( g => g.Key, g => g.GroupBy(g2 => g2.PlayerID).ToDictionary(g3 => g3.Key, g3 => g3.ToList())); var pgs = new PenaltyGroupGateway(connection, transaction).GetPenaltyGroupsForTeam(teamID); Dictionary<int, int> boxTimeEstimates = new BoxTimeEstimateGateway(connection, transaction).GetAllBoxTimeEstimates(); Dictionary<FoulComparison, Dictionary<int, float>> sss = new SituationalScoreGateway(connection, transaction).GetAllSituationalScores(); AveragePenaltyCostPerJam avgPenCost = new AveragePenaltyCostGateway(connection, transaction).GetAveragePenaltyCost(); transaction.Commit(); connection.Close(); Dictionary<FoulComparison, float> medians = CalculateMedianScores(sss); PenaltyCostCalculator ppcCalc = new PenaltyCostCalculator(_connectionString); Dictionary<int, double> groupPenaltyCostMap = ppcCalc.CalculatePointCostsForTeam(jamData, pgs, boxTimeEstimates, sss); Dictionary<int, PlayerPerformance> pps = new Dictionary<int, PlayerPerformance>(25); Dictionary<int, double> jamTotalPortionMap = new Dictionary<int, double>(300); foreach(Jam jam in jams) { var pe = jpe[jam.ID]; foreach(JamPlayerEffectiveness eff in pe.Values) { // get/set PlayerPerformance object if(!pps.ContainsKey(eff.PlayerID)) { pps[eff.PlayerID] = new PlayerPerformance { Player = players[eff.PlayerID], Bouts = new List<BoutPerformance>() }; } PlayerPerformance curPP = pps[eff.PlayerID]; // get/set BoutPerformance object Bout bout = bouts[jam.BoutID]; BoutPerformance bp = null; if (!curPP.Bouts.Any() || curPP.Bouts.Last().BoutID != bout.ID) { bp = new BoutPerformance { BoutID = bout.ID, AwayTeamName = teams[bout.AwayTeamID].Name, HomeTeamName = teams[bout.HomeTeamID].Name, BoutDate = bout.BoutDate, Jams = new List<JamPerformance>() }; curPP.Bouts.Add(bp); } else { bp = curPP.Bouts.Last(); } JamTeamData jd = jamData[jam.ID]; int penaltyCount = penalties.ContainsKey(jam.ID) && penalties[jam.ID].ContainsKey(eff.PlayerID) ? penalties[jam.ID][eff.PlayerID].Count() : 0; JamPerformance jp = new JamPerformance { BlockerJamPercentage = eff.IsJammer ? 0 : eff.JamPortion, DeltaPercentile = eff.BaseQuality, IsFirstHalf = jam.IsFirstHalf, JamID = jam.ID, JammerJamPercentage = eff.IsJammer ? eff.JamPortion : 0, JamNumber = jam.JamNumber, JamPenalties = penaltyCount, MedianDelta = medians[jd.FoulComparison], PenaltyCost = 0, PointDelta = jd.PointDelta }; if (jamTotalPortionMap.ContainsKey(jam.ID)) { jamTotalPortionMap[jam.ID] += eff.IsJammer ? eff.JamPortion * 4 : eff.JamPortion; } else { jamTotalPortionMap[jam.ID] = eff.IsJammer ? eff.JamPortion * 4 : eff.JamPortion; } bp.Jams.Add(jp); } } foreach(PenaltyGroup pg in pgs) { foreach(Penalty p in pg.Penalties) { if (jams.Any(j => j.ID == p.JamID)) { JamPerformance jp = pps[p.PlayerID].Bouts.SelectMany(b => b.Jams).Where(j => j.JamID == p.JamID).First(); jp.PenaltyCost += groupPenaltyCostMap[pg.GroupID]; } } } foreach(PlayerPerformance pp in pps.Values) { RollUpPlayerPerformance(avgPenCost, jamTotalPortionMap, pp); } CalculateTeamAverages(pps, bouts); foreach(PlayerPerformance pp in pps.Values) { pp.BlockerPerformance.PlayerValueVersusTeamAverage = pp.Bouts.Sum(b => b.BlockerPerformance.PlayerValueVersusTeamAverage); pp.JammerPerformance.PlayerValueVersusTeamAverage = pp.Bouts.Sum(b => b.JammerPerformance.PlayerValueVersusTeamAverage); } return pps.Values.ToList(); }
private static Dictionary<int, PlayerPerformance> GenerateInitialPlayerPerformance(Dictionary<int, Dictionary<int, Player>> players, IOrderedEnumerable<Jam> jams, Dictionary<int, Dictionary<int, JamPlayerEffectiveness>> jpe, Dictionary<int, Dictionary<int, JamTeamData>> jamData, Dictionary<int, Team> teams, Dictionary<int, Bout> bouts, Dictionary<int, Dictionary<int, List<Penalty>>> penalties, IList<PenaltyGroup> pgs, AveragePenaltyCostPerJam avgPenCost, Dictionary<FoulComparison, float> medians, Dictionary<int, double> groupPenaltyCostMap, Dictionary<int, double> jamTotalPortionMap) { Dictionary<int, PlayerPerformance> pps = new Dictionary<int, PlayerPerformance>(); foreach (Jam jam in jams) { var pe = jpe[jam.ID]; foreach(var eff in pe.Values) { // get/set PlayerPerformance object if (!pps.ContainsKey(eff.PlayerID)) { pps[eff.PlayerID] = new PlayerPerformance { Player = players[eff.PlayerID][eff.TeamID], Bouts = new List<BoutPerformance>() }; } PlayerPerformance curPP = pps[eff.PlayerID]; // get/set BoutPerformance object Bout bout = bouts[jam.BoutID]; BoutPerformance bp = null; if (!curPP.Bouts.Any() || curPP.Bouts.Last().BoutDate != bout.BoutDate || curPP.Bouts.Last().HomeTeamName != teams[bout.HomeTeamID].Name || curPP.Bouts.Last().AwayTeamName != teams[bout.AwayTeamID].Name) { bp = new BoutPerformance { BoutID = bout.ID, AwayTeamName = teams[bout.AwayTeamID].Name, HomeTeamName = teams[bout.HomeTeamID].Name, BoutDate = bout.BoutDate, Jams = new List<JamPerformance>() }; curPP.Bouts.Add(bp); } else { bp = curPP.Bouts.Last(); } JamTeamData jd = jamData[jam.ID][eff.TeamID]; int penaltyCount = penalties.ContainsKey(jam.ID) && penalties[jam.ID].ContainsKey(eff.PlayerID) ? penalties[jam.ID][eff.PlayerID].Count() : 0; JamPerformance jp = new JamPerformance { BlockerJamPercentage = eff.IsJammer ? 0 : eff.JamPortion, DeltaPercentile = eff.BaseQuality, IsFirstHalf = jam.IsFirstHalf, JamID = jam.ID, JammerJamPercentage = eff.IsJammer ? eff.JamPortion : 0, JamNumber = jam.JamNumber, JamPenalties = penaltyCount, MedianDelta = medians[jd.FoulComparison], PenaltyCost = 0, PointDelta = jd.PointDelta }; if (jamTotalPortionMap.ContainsKey(jam.ID)) { jamTotalPortionMap[jam.ID] += eff.IsJammer ? eff.JamPortion * 4 : eff.JamPortion; } else { jamTotalPortionMap[jam.ID] = eff.IsJammer ? eff.JamPortion * 4 : eff.JamPortion; } bp.Jams.Add(jp); }; } foreach (PenaltyGroup pg in pgs) { foreach (Penalty p in pg.Penalties) { JamPerformance jp = pps[p.PlayerID].Bouts.SelectMany(b => b.Jams).Where(j => j.JamID == p.JamID).First(); jp.PenaltyCost += groupPenaltyCostMap[pg.GroupID]; } } Parallel.ForEach(pps.Values, pp => { RollUpPlayerPerformance(avgPenCost, jamTotalPortionMap, pp); }); return pps; }