internal JamTeamData ReadData(SqlDataReader reader) { JamTeamData jamFoul = new JamTeamData(); jamFoul.JamID = reader.GetInt32(reader.GetOrdinal("JamID")); jamFoul.TeamID = reader.GetInt32(reader.GetOrdinal("TeamID")); jamFoul.BlockerBoxTime = reader.GetInt32(reader.GetOrdinal("BlockerBoxTime")); jamFoul.JammerBoxTime = reader.GetInt32(reader.GetOrdinal("JammerBoxTime")); jamFoul.OppBlockerBoxTime = reader.GetInt32(reader.GetOrdinal("OppBlockerBoxTime")); jamFoul.OppJammerBoxTime = reader.GetInt32(reader.GetOrdinal("OppJammerBoxTime")); jamFoul.PointDelta = reader.GetInt32(reader.GetOrdinal("PointDelta")); return jamFoul; }
internal static double GetEstimatedValueWithoutBoxTime(Dictionary<FoulComparison, Dictionary<int, float>> sss, JamTeamData jamData, bool isJammer) { if (!sss.ContainsKey(jamData.FoulComparison)) { throw new InvalidOperationException("This is bad data"); } // figure out the foul differential if this team did not commit fouls of this type this jam int jammerPenaltyDiff = (isJammer ? 0 : jamData.JammerBoxTime) - jamData.OppJammerBoxTime; int blockerPenaltyDiff = (isJammer ? jamData.BlockerBoxTime : 0) - jamData.OppBlockerBoxTime; double jammerBoxComp = Math.Round(jammerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; double blockerBoxComp = Math.Round(blockerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; FoulComparison foul = new FoulComparison { JammerBoxComparison = jammerBoxComp, BlockerBoxComparison = blockerBoxComp }; if (!sss.ContainsKey(foul)) { // lacking anything better, sum the distance of each factor from the percentile of the base JamTeamData baseJamData = new JamTeamData { BlockerBoxTime = 0, JammerBoxTime = 0, OppBlockerBoxTime = 0, OppJammerBoxTime = 0, PointDelta = jamData.PointDelta }; double baseDelta = GetPercentileForScore(sss[baseJamData.FoulComparison], jamData.PointDelta); // pull team 1 values baseJamData.BlockerBoxTime = isJammer ? jamData.BlockerBoxTime : 0; baseJamData.JammerBoxTime = isJammer ? 0 : jamData.JammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } double score1 = GetPercentileForScore(sss[baseJamData.FoulComparison], jamData.PointDelta); // pull team 2 blocker baseJamData.BlockerBoxTime = 0; baseJamData.JammerBoxTime = 0; baseJamData.OppBlockerBoxTime = jamData.OppBlockerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } // special case, for now if (baseJamData.OppBlockerBoxTime > 135) { // just treat it as 135 for now baseJamData.OppBlockerBoxTime = 135; } if (baseJamData.OppBlockerBoxTime < -135) { baseJamData.OppBlockerBoxTime = -135; } double score2 = GetPercentileForScore(sss[baseJamData.FoulComparison], jamData.PointDelta); // pull team 2 jammer baseJamData.OppBlockerBoxTime = 0; baseJamData.OppJammerBoxTime = jamData.OppJammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } double score3 = GetPercentileForScore(sss[baseJamData.FoulComparison], jamData.PointDelta); return score1 + score2 + score3 - 2 * baseDelta; } else { return GetPercentileForScore(sss[foul], jamData.PointDelta); } }
private double DetermineQualityWithoutPenalty(JamTeamData jamData, bool isJammer) { // figure out the foul differential if this team did not commit fouls of this time this jam int jammerPenaltyDiff = (isJammer ? 0 : jamData.JammerBoxTime) - jamData.OppJammerBoxTime; int blockerPenaltyDiff = (isJammer ? jamData.BlockerBoxTime : 0) - jamData.OppBlockerBoxTime; double jammerBoxComp = Math.Round(jammerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; double blockerBoxComp = Math.Round(blockerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; FoulComparison foul = new FoulComparison { JammerBoxComparison = jammerBoxComp, BlockerBoxComparison = blockerBoxComp }; if (!_sss.ContainsKey(foul)) { // lacking anything better, sum the distance of each factor from the percentile of the base JamTeamData baseJamData = new JamTeamData { BlockerBoxTime = 0, JammerBoxTime = 0, OppBlockerBoxTime = 0, OppJammerBoxTime = 0, PointDelta = jamData.PointDelta }; double baseQuality = DetermineQualityWithoutPenalty(baseJamData, isJammer); // pull team 1 values baseJamData.BlockerBoxTime = isJammer ? jamData.BlockerBoxTime : 0; baseJamData.JammerBoxTime = isJammer ? 0 : jamData.JammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0.5; } double quality1 = DetermineQualityWithoutPenalty(baseJamData, isJammer) - baseQuality; // pull team 2 blocker baseJamData.BlockerBoxTime = 0; baseJamData.JammerBoxTime = 0; baseJamData.OppBlockerBoxTime= jamData.OppBlockerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0.5; } double quality2 = DetermineQualityWithoutPenalty(baseJamData, isJammer) - baseQuality; // pull team 2 jammer baseJamData.OppBlockerBoxTime = 0; baseJamData.OppJammerBoxTime = jamData.OppJammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0.5; } double quality3 = DetermineQualityWithoutPenalty(baseJamData, isJammer) - baseQuality; return baseQuality + quality1 + quality2 + quality3; } else if(!_sss[foul].ContainsKey(jamData.PointDelta)) { // extrapolate from the points we do have var bottomList = _sss[foul].Keys.Where(k => k < jamData.PointDelta); int bottom = bottomList.Any() ? bottomList.Max() : -55; double bottomPercentile =bottomList.Any() ? _sss[foul][bottom] : 0; var topList = _sss[foul].Keys.Where(k => k > jamData.PointDelta); int top = topList.Any() ? topList.Min() : 55; double topPercentile = topList.Any() ? _sss[foul][top] : 1; int distance = top - bottom; int portion = jamData.PointDelta - bottom; double ratio = ((double)portion) / distance; return bottomPercentile + ((topPercentile - bottomPercentile) * ratio); } else { return _sss[foul][jamData.PointDelta]; } }
internal static double GetEstimatedPointsWithoutBoxTime(Dictionary<FoulComparison, Dictionary<int, float>> sss, JamTeamData jamData, bool isJammer) { float basePercentile; if (!sss.ContainsKey(jamData.FoulComparison)) { throw new InvalidOperationException("This is bad data"); } else if (!sss[jamData.FoulComparison].ContainsKey(jamData.PointDelta)) { basePercentile = GetPercentileForScore(sss[jamData.FoulComparison], jamData.PointDelta); } else { basePercentile = sss[jamData.FoulComparison][jamData.PointDelta]; } // figure out the foul differential if this team did not commit fouls of this type this jam int jammerPenaltyDiff = (isJammer ? 0 : jamData.JammerBoxTime) - jamData.OppJammerBoxTime; int blockerPenaltyDiff = (isJammer ? jamData.BlockerBoxTime : 0) - jamData.OppBlockerBoxTime; double jammerBoxComp = Math.Round(jammerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; double blockerBoxComp = Math.Round(blockerPenaltyDiff / 15.0, MidpointRounding.AwayFromZero) / 2.0; FoulComparison foul = new FoulComparison { JammerBoxComparison = jammerBoxComp, BlockerBoxComparison = blockerBoxComp }; if (!sss.ContainsKey(foul)) { // lacking anything better, sum the distance of each factor from the percentile of the base JamTeamData baseJamData = new JamTeamData { BlockerBoxTime = 0, JammerBoxTime = 0, OppBlockerBoxTime = 0, OppJammerBoxTime = 0, PointDelta = jamData.PointDelta }; double baseDelta = GetScoreForPercentile(sss[baseJamData.FoulComparison], basePercentile); // pull team 1 values baseJamData.BlockerBoxTime = isJammer ? jamData.BlockerBoxTime : 0; baseJamData.JammerBoxTime = isJammer ? 0 : jamData.JammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } if(!sss.ContainsKey(baseJamData.FoulComparison)) { sss[baseJamData.FoulComparison] = new Dictionary<int, float>(); int pointDifferential = (int)((((baseJamData.OppBlockerBoxTime - baseJamData.BlockerBoxTime)*2.5)+((baseJamData.OppJammerBoxTime - baseJamData.JammerBoxTime)*10))/30.0); sss[baseJamData.FoulComparison][pointDifferential] = 0.5f; } double score1 = GetScoreForPercentile(sss[baseJamData.FoulComparison], basePercentile); // pull team 2 blocker baseJamData.BlockerBoxTime = 0; baseJamData.JammerBoxTime = 0; baseJamData.OppBlockerBoxTime = jamData.OppBlockerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } if (!sss.ContainsKey(baseJamData.FoulComparison)) { sss[baseJamData.FoulComparison] = new Dictionary<int, float>(); int pointDifferential = (int)((((baseJamData.OppBlockerBoxTime - baseJamData.BlockerBoxTime) * 2.5) + ((baseJamData.OppJammerBoxTime - baseJamData.JammerBoxTime) * 10)) / 30.0); sss[baseJamData.FoulComparison][pointDifferential] = 0.5f; } double score2 = GetScoreForPercentile(sss[baseJamData.FoulComparison], basePercentile); // pull team 2 jammer baseJamData.OppBlockerBoxTime = 0; baseJamData.OppJammerBoxTime = jamData.OppJammerBoxTime; if (baseJamData.FoulComparison.Equals(foul)) { return 0; } if (!sss.ContainsKey(baseJamData.FoulComparison)) { sss[baseJamData.FoulComparison] = new Dictionary<int, float>(); int pointDifferential = (int)((((baseJamData.OppBlockerBoxTime - baseJamData.BlockerBoxTime) * 2.5) + ((baseJamData.OppJammerBoxTime - baseJamData.JammerBoxTime) * 10)) / 30.0); sss[baseJamData.FoulComparison][pointDifferential] = 0.5f; } double score3 = GetScoreForPercentile(sss[baseJamData.FoulComparison], basePercentile); return score1 + score2 + score3 - 2 * baseDelta; } else { return GetScoreForPercentile(sss[foul], basePercentile); } }