diff --git a/KingsAndQueensHat/KingsAndQueensHat.csproj b/KingsAndQueensHat/KingsAndQueensHat.csproj index 1d87ee7..d4b7928 100644 --- a/KingsAndQueensHat/KingsAndQueensHat.csproj +++ b/KingsAndQueensHat/KingsAndQueensHat.csproj @@ -60,6 +60,7 @@ + diff --git a/KingsAndQueensHat/Model/Team.cs b/KingsAndQueensHat/Model/Team.cs index 53d6af8..09da48f 100644 --- a/KingsAndQueensHat/Model/Team.cs +++ b/KingsAndQueensHat/Model/Team.cs @@ -85,6 +85,15 @@ public int TotalSkill get { return Players.Sum(p => p.SkillValue); } } + [XmlIgnore] + public Dictionary GenderSkills + { + get + { + return Players.GroupBy(p => p.Gender).Select(g => new {g.Key, Skill = g.Sum(p => p.SkillValue)}).ToDictionary(x => x.Key, x => x.Skill); + } + } + [XmlIgnore] public int PlayerCount { diff --git a/KingsAndQueensHat/Model/Tournament.cs b/KingsAndQueensHat/Model/Tournament.cs index 1b2d80c..ccd0790 100644 --- a/KingsAndQueensHat/Model/Tournament.cs +++ b/KingsAndQueensHat/Model/Tournament.cs @@ -154,7 +154,8 @@ public async Task CreateNewRound(int teamCount, CancellationToken cancel) var penalty1 = new UnevenSkillPenalty(); var penalty3 = new TooManyWinnersPenalty(PlayerProvider); var penalty4 = new RangeOfSkillsPenalty(); - var penalties = new IPenalty[] { penalty1, _playerPairings, penalty3, penalty4 }; + var penalty5 = new UnevenGenderSkillPenalty(); + var penalties = new IPenalty[] { penalty1, _playerPairings, penalty3, penalty4, penalty5 }; var teams = await teamCreator.CreateApproximatelyOptimalTeams(penalties, PlayerProvider, numTeamGens, teamCount, cancel); diff --git a/KingsAndQueensHat/TeamGeneration/UnevenGenderSkillPenalty.cs b/KingsAndQueensHat/TeamGeneration/UnevenGenderSkillPenalty.cs new file mode 100644 index 0000000..978bdfb --- /dev/null +++ b/KingsAndQueensHat/TeamGeneration/UnevenGenderSkillPenalty.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using KingsAndQueensHat.Model; + +namespace KingsAndQueensHat.TeamGeneration +{ + /// + /// Penalise team allocations that leave some teams with a particular dominant gender + /// , while others do not + /// + public class UnevenGenderSkillPenalty : IPenalty + { + public double ScorePenalty(List teams) + { + var scores = teams.Select(team => team.GenderSkills).ToList(); + int result = 0; + foreach (var gender in new[] { Gender.Male, Gender.Female }) + { + var total = scores.Sum(s => s[gender]); + var teamCount = teams.Count; + var expectedTeamGenderSkill = total / teamCount; + + // Sum the deviations from the expected team skill + result += scores.Sum(s => Math.Abs(s[gender] - expectedTeamGenderSkill)); + } + return result; + } + + public double Weighting { get { return 1.0; } } + } +}