using System; using System.Collections.Generic; namespace VocaluxeLib.PartyModes.Challenge { public class CChallengeRounds { private readonly Random _Rand; private readonly int _NumPlayer; public List Rounds; public CChallengeRounds(int numRounds, int numPlayer, int numPlayerAtOnce) { Rounds = new List(); _Rand = new Random(DateTime.Now.Millisecond); if (numPlayerAtOnce < 1 || numRounds < 1 || numPlayer == 0) _NumPlayer = 0; else { _NumPlayer = numPlayer; _BuildRounds(numRounds, numPlayerAtOnce, _Rand); } } public CCombination GetRound(int roundNr) { if (roundNr >= Rounds.Count || _NumPlayer == 0 || Rounds.Count == 0) return null; return Rounds[roundNr]; } private void _BuildRounds(int numRounds, int numPlayerAtOnce, Random rand) { CCombinations combinations = new CCombinations(_NumPlayer, numPlayerAtOnce, rand); Rounds.Add(combinations.GetNextCombination(null)); for (int i = 1; i < numRounds; i++) Rounds.Add(combinations.GetNextCombination(_GetPlayerDemand(i))); } private List _GetPlayerDemand(int roundIndex) { List numPlayed = new List(_NumPlayer); for (int i = 0; i < _NumPlayer; i++) numPlayed.Add(0); for (int i = 0; i < roundIndex; i++) { foreach (int playerIndex in Rounds[i].Player) numPlayed[playerIndex]++; } int max = 0; foreach (int p in numPlayed) { if (p > max) max = p; } int num = Rounds[0].Player.Count; List result = new List(); List other = new List(); List last = new List(); for (int i = 0; i < numPlayed.Count; i++) { if (roundIndex == 0 || numPlayed[i] < max) { if (roundIndex == 0 || roundIndex > 0 && numPlayed[i] < max && !Rounds[roundIndex - 1].IsAvailable(i)) result.Add(i); else if (numPlayed[i] < max) other.Add(i); } else { if (roundIndex > 0) { if (!Rounds[roundIndex - 1].IsAvailable(i)) other.Add(i); else last.Add(i); } else last.Add(i); } } while (result.Count < num && other.Count > 0) { int n = other.Count; int r = _Rand.Next(n); result.Add(other[r]); other.RemoveAt(r); } while (result.Count < num) { int n = last.Count; int r = _Rand.Next(n); result.Add(last[r]); last.RemoveAt(r); } while (result.Count > num) { int n = result.Count; int r = _Rand.Next(n); result.RemoveAt(r); } result.Sort(); return result; } } class CCombinations { private readonly List _Combs; private readonly Random _Rand; private readonly int _NumPlayer; private readonly int _NumMics; public CCombinations(int numPlayer, int numMics, Random rand) { _Combs = new List(); _NumMics = numMics; _NumPlayer = numPlayer; _Rand = rand; } public CCombination GetNextCombination(List playerNrDemand) { if (_Combs.Count == 0) _Create(); CCombination combs = new CCombination(); if (_NumPlayer == _NumMics) return _Combs[0]; //filter against PlayerNrDemand List combsFiltered = new List(); if (playerNrDemand != null) { for (int i = 0; i < _Combs.Count; i++) { if (_Combs[i].IsAvailableAll(playerNrDemand)) combsFiltered.Add(_Combs[i]); } } //1st fallback if (playerNrDemand != null && combsFiltered.Count == 0) { for (int i = 0; i < _Combs.Count; i++) { if (_Combs[i].IsAvailableSomeone(playerNrDemand)) combsFiltered.Add(_Combs[i]); } } //2nd fallback if (combsFiltered.Count == 0) { for (int i = 0; i < _Combs.Count; i++) combsFiltered.Add(_Combs[i]); } int num = combsFiltered.Count; int rand = _Rand.Next(num); CCombination c = new CCombination(); for (int i = 0; i < combsFiltered[rand].Player.Count; i++) c.Player.Add(combsFiltered[rand].Player[i]); _Combs.Remove(combsFiltered[rand]); return combsFiltered[rand]; } private void _Create() { _Combs.Clear(); int num = (int)Math.Pow(2, _NumPlayer); for (int i = 1; i <= num; i++) { CCombination c = new CCombination(); for (int j = 0; j < _NumPlayer; j++) { if ((i & (1 << j)) > 0) c.Player.Add(j); } if (c.Player.Count == _NumMics) _Combs.Add(c); } } } public class CCombination { public List Player; public CCombination() { Player = new List(); } public bool IsAvailable(int playerIndex) { foreach (int p in Player) { if (p == playerIndex) return true; } return false; } public bool IsAvailableAll(List playerIndices) { bool result = true; foreach (int p in playerIndices) result &= IsAvailable(p); return result; } public bool IsAvailableSomeone(List playerIndices) { bool result = false; foreach (int p in playerIndices) result |= IsAvailable(p); return result; } } }