Improve rounds generation

This commit is contained in:
Flamefire committed 2014-12-21 12:09:54 +01:00
1 parent 76859942b8
commit 24edcc7328
3 files changed
+67 -12

No files matched your search

@@ -46,6 +46,18 @@ namespace VocaluxeLib.PartyModes.Challenge
playersPerRound = numPlayer; playersPerRound = numPlayer;
_BuildRounds(numRounds, numPlayer, playersPerRound); _BuildRounds(numRounds, numPlayer, playersPerRound);
if (Count > numRounds)
{
//Try again and take the better one
List<CRound> old = new List<CRound>(_Rounds);
_Rounds.Clear();
_BuildRounds(numRounds, numPlayer, playersPerRound);
if (Count > old.Count)
{
_Rounds.Clear();
_Rounds.AddRange(old);
}
}
} }
/// <summary> /// <summary>
@@ -74,7 +86,7 @@ namespace VocaluxeLib.PartyModes.Challenge
combinations.Shuffle(); combinations.Shuffle();
} }
private static CRound _GetMatchingCombination(List<int> playersInRound, List<CRound> combinations) private static CRound _GetMatchingCombination(List<int> playersInRound, List<int> numSung, List<CRound> combinations)
{ {
foreach (CRound round in combinations) foreach (CRound round in combinations)
{ {
@@ -83,8 +95,23 @@ namespace VocaluxeLib.PartyModes.Challenge
if (matching == round.Players.Count || matching == playersInRound.Count) if (matching == round.Players.Count || matching == playersInRound.Count)
return round; return round;
} }
Debug.Assert(false, "This should not happen!"); // It may happen, that there are only players that already sung against each other. So create a 2nd best option with the most number of players that should sing in it
return combinations[0]; int maxMatching = combinations.Max(c => c.Players.Count(playersInRound.Contains));
List<CRound> nextOptions = combinations.Where(c => c.Players.Count(playersInRound.Contains) == maxMatching).ToList();
// And select the combination that minimizes the sum of the number of songs sung (--> favor rounds with players that sung less than others)
CRound result = null;
int minSung = int.MaxValue;
foreach (CRound round in nextOptions)
{
int curNumSung = round.Players.Sum(pl => numSung[pl]);
if (curNumSung < minSung)
{
minSung = curNumSung;
result = round;
}
}
Debug.Assert(result != null);
return result;
} }
private void _BuildRounds(int numRounds, int numPlayer, int playersPerRound) private void _BuildRounds(int numRounds, int numPlayer, int playersPerRound)
@@ -101,16 +128,15 @@ namespace VocaluxeLib.PartyModes.Challenge
if (combinations.Count == 0) if (combinations.Count == 0)
_AddCombinations(numPlayer, playersPerRound, combinations); _AddCombinations(numPlayer, playersPerRound, combinations);
List<int> playersInRound = _GetPlayersForRound(numSung); List<int> playersInRound = _GetPlayersForRound(numSung);
CRound curRound = _GetMatchingCombination(playersInRound, combinations); CRound curRound = _GetMatchingCombination(playersInRound, numSung, combinations);
foreach (int player in curRound.Players) foreach (int player in curRound.Players)
numSung[player]++; numSung[player]++;
_Rounds.Add(curRound); _Rounds.Add(curRound);
combinations.Remove(curRound);
//Stop if we have enough rounds and all players sung the same amount of songs //Stop if we have enough rounds and all players sung the same amount of songs
if (_Rounds.Count >= numRounds && numSung.All(ct => ct == numSung[0])) if (_Rounds.Count >= numRounds && numSung.All(ct => ct == numSung[0]))
break; break;
} }
if (_Rounds.Count != numRounds)
CBase.Log.LogDebug("Number of rounds does not match. Expected: " + numRounds + ", Is: " + _Rounds.Count + " for " + numPlayer + "/" + playersPerRound);
} }
} }
@@ -46,6 +46,18 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
playersPerRound = numPlayer; playersPerRound = numPlayer;
_BuildRounds(numRounds, numPlayer, playersPerRound); _BuildRounds(numRounds, numPlayer, playersPerRound);
if (Count > numRounds)
{
//Try again and take the better one
List<CRound> old = new List<CRound>(_Rounds);
_Rounds.Clear();
_BuildRounds(numRounds, numPlayer, playersPerRound);
if (Count > old.Count)
{
_Rounds.Clear();
_Rounds.AddRange(old);
}
}
} }
/// <summary> /// <summary>
@@ -74,7 +86,7 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
combinations.Shuffle(); combinations.Shuffle();
} }
private static CRound _GetMatchingCombination(List<int> playersInRound, List<CRound> combinations) private static CRound _GetMatchingCombination(List<int> playersInRound, List<int> numSung, List<CRound> combinations)
{ {
foreach (CRound round in combinations) foreach (CRound round in combinations)
{ {
@@ -83,8 +95,23 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
if (matching == round.Players.Count || matching == playersInRound.Count) if (matching == round.Players.Count || matching == playersInRound.Count)
return round; return round;
} }
Debug.Assert(false, "This should not happen!"); // It may happen, that there are only players that already sung against each other. So create a 2nd best option with the most number of players that should sing in it
return combinations[0]; int maxMatching = combinations.Max(c => c.Players.Count(playersInRound.Contains));
List<CRound> nextOptions = combinations.Where(c => c.Players.Count(playersInRound.Contains) == maxMatching).ToList();
// And select the combination that minimizes the sum of the number of songs sung (--> favor rounds with players that sung less than others)
CRound result = null;
int minSung = int.MaxValue;
foreach (CRound round in nextOptions)
{
int curNumSung = round.Players.Sum(pl => numSung[pl]);
if (curNumSung < minSung)
{
minSung = curNumSung;
result = round;
}
}
Debug.Assert(result != null);
return result;
} }
private void _BuildRounds(int numRounds, int numPlayer, int playersPerRound) private void _BuildRounds(int numRounds, int numPlayer, int playersPerRound)
@@ -101,16 +128,15 @@ namespace VocaluxeLib.PartyModes.ChallengeMedley
if (combinations.Count == 0) if (combinations.Count == 0)
_AddCombinations(numPlayer, playersPerRound, combinations); _AddCombinations(numPlayer, playersPerRound, combinations);
List<int> playersInRound = _GetPlayersForRound(numSung); List<int> playersInRound = _GetPlayersForRound(numSung);
CRound curRound = _GetMatchingCombination(playersInRound, combinations); CRound curRound = _GetMatchingCombination(playersInRound, numSung, combinations);
foreach (int player in curRound.Players) foreach (int player in curRound.Players)
numSung[player]++; numSung[player]++;
_Rounds.Add(curRound); _Rounds.Add(curRound);
combinations.Remove(curRound);
//Stop if we have enough rounds and all players sung the same amount of songs //Stop if we have enough rounds and all players sung the same amount of songs
if (_Rounds.Count >= numRounds && numSung.All(ct => ct == numSung[0])) if (_Rounds.Count >= numRounds && numSung.All(ct => ct == numSung[0]))
break; break;
} }
if (_Rounds.Count != numRounds)
CBase.Log.LogDebug("Number of rounds does not match. Expected: " + numRounds + ", Is: " + _Rounds.Count + " for " + numPlayer + "/" + playersPerRound);
} }
} }
+3
View File
@@ -60,6 +60,9 @@ namespace VocaluxeTests
CChallengeRounds rounds = new CChallengeRounds(numRounds, numPlayer, numMic); CChallengeRounds rounds = new CChallengeRounds(numRounds, numPlayer, numMic);
Assert.IsTrue(rounds.Count >= numRounds); Assert.IsTrue(rounds.Count >= numRounds);
_CheckRounds(rounds, numPlayer); _CheckRounds(rounds, numPlayer);
if (rounds.Count != numRounds)
CBase.Log.LogDebug("Number of rounds does not match. Expected: " + numRounds + ", Is: " + rounds.Count + " for " + numPlayer + "/" +
((numPlayer < numMic) ? numPlayer : numMic));
} }
} }
} }