private void SwapSameClanTags(ref List<PlayerModel> usScrambled, ref List<PlayerModel> ruScrambled)
{
/*
Since all players have been moved to squad 0 at this point, only need to swap PlayerModel items
between the two scramble lists. No actual moving is required.
*/
DebugScrambler(" ");
if (KeepFriendsInSameTeam) {
DebugScrambler("Keeping clan tags and friends to same team");
} else {
DebugScrambler("Keeping clan tags to same team");
}
try {
PerModeSettings perMode = GetPerModeSettings();
String usName = GetTeamName(1);
String ruName = GetTeamName(2);
Dictionary<String,int[]> matesDistribution = new Dictionary<String,int[]>();
// Calculate distribution between the two teams
foreach (PlayerModel clone in usScrambled) {
String tagOrFriendex = ExtractTagOrFriendex(clone);
if (String.IsNullOrEmpty(tagOrFriendex)) continue;
int[] teamCounts = null;
if (matesDistribution.TryGetValue(tagOrFriendex, out teamCounts) && teamCounts != null) {
teamCounts[1] = teamCounts[1] + 1;
} else {
teamCounts = new int[3]{0,0,0};
teamCounts[1] = teamCounts[1] + 1;
matesDistribution[tagOrFriendex] = teamCounts;
}
}
foreach (PlayerModel clone in ruScrambled) {
String tagOrFriendex = ExtractTagOrFriendex(clone);
if (String.IsNullOrEmpty(tagOrFriendex)) continue;
int[] teamCounts = null;
if (matesDistribution.TryGetValue(tagOrFriendex, out teamCounts) && teamCounts != null) {
teamCounts[2] = teamCounts[2] + 1;
} else {
teamCounts = new int[3]{0,0,0};
teamCounts[2] = teamCounts[2] + 1;
matesDistribution[tagOrFriendex] = teamCounts;
}
}
// Find split tag counts
List<String> splitTagsOrFriends = new List<String>();
foreach (String id in matesDistribution.Keys) {
if (matesDistribution[id][1] == 0) continue;
if (matesDistribution[id][2] == 0) continue;
// Split!
DebugScrambler("Identifier ^b[" + id + "]^n is split: " + matesDistribution[id][1] + "/" + usName + " vs " + matesDistribution[id][2] + "/" + ruName);
splitTagsOrFriends.Add(id);
}
if (splitTagsOrFriends.Count == 0) {
if (KeepFriendsInSameTeam) {
DebugScrambler("No clan tags or friends were split");
} else {
DebugScrambler("No clan tags were split");
}
return;
}
// Build squad table
Dictionary<int,SquadRoster> squads = new Dictionary<int,SquadRoster>();
foreach (PlayerModel us in usScrambled) {
int key = (1 * 1000) + us.ScrambledSquad;
AddPlayerToSquadRoster(squads, us, key, us.ScrambledSquad, false);
}
foreach (PlayerModel ru in ruScrambled) {
int key = (2 * 1000) + ru.ScrambledSquad;
AddPlayerToSquadRoster(squads, ru, key, ru.ScrambledSquad, false);
}
// Swap to maintain squad sizes and team sizes
int target = 0;
int opposing = 0;
List<PlayerModel> targetList = null;
List<PlayerModel> opposingList = null;
bool allOk = true;
foreach (String splitId in splitTagsOrFriends) {
try {
DebugScrambler("Working on identifier [^b" + splitId + "^n]");
// Target team is the one with the majority
if (matesDistribution[splitId][1] > matesDistribution[splitId][2]) {
target = 1;
opposing = 2;
targetList = usScrambled;
opposingList = ruScrambled;
} else {
target = 2;
opposing = 1;
targetList = ruScrambled;
opposingList = usScrambled;
}
DebugScrambler("Target team is " + GetTeamName(target) + " with " + matesDistribution[splitId][target] + ", opposing team is " + GetTeamName(opposing) + " with " + matesDistribution[splitId][opposing]);
// List all squads that have this clan tag or friendex
List<int> clan = GetSquadsWithClanTagOrFriendex(splitId, squads);
// List players that need to move
List<PlayerModel> minority = new List<PlayerModel>();
List<PlayerModel> replacements = new List<PlayerModel>();
foreach (int key in clan) {
if ((key / 1000) != target) { // squad containing minority clan member from opposing team
foreach (PlayerModel mate in squads[key].Roster) {
String mId = ExtractTagOrFriendex(mate);
if (mId == splitId && !minority.Contains(mate)) minority.Add(mate);
}
}
}
if (minority.Count == 0) {
DebugScrambler("ASSERT: No minority clan members for [" + splitId + "]");
return;
}
// Need a list of replacements from the target team to swap, try non-clan members from target squads first
foreach (int key in clan) {
if ((key / 1000) == target) { // squad containing majority clan members from target team
foreach (PlayerModel rep in squads[key].Roster) {
String rId = ExtractTagOrFriendex(rep);
if (String.IsNullOrEmpty(rId) && !replacements.Contains(rep)) {
replacements.Add(rep);
}
if (replacements.Count == minority.Count) break;
}
}
}
// Might not be any room in target squads, so pick non-tagged extras from end of sorted list
if (replacements.Count < minority.Count && targetList.Count > 0) {
// start at the bottom of the sorted list and go up in metric
for (int x = (targetList.Count-1); x >= 0; --x) {
if (replacements.Count == minority.Count) break;
PlayerModel extra = targetList[x];
String xId = ExtractTagOrFriendex(extra);
if (String.IsNullOrEmpty(xId) && !replacements.Contains(extra)) {
replacements.Add(extra);
}
}
}
// If not enough replacements, abandon minority players until equal
while (replacements.Count < minority.Count) {
if (minority.Count == 0) break;
// Not enough replacements
PlayerModel mate = minority[0];
DebugScrambler("ASSERT: Not enough replacements " + minority.Count + " vs " + replacements.Count + " abandoning " + mate.Name);
minority.Remove(mate);
}
if (minority.Count == 0 || replacements.Count == 0 || (replacements.Count != minority.Count)) {
if (KeepFriendsInSameTeam) {
DebugScrambler("Unable to swap clan members or friends to the target team");
} else {
DebugScrambler("Unable to swap clan members to the target team");
}
return;
}
// Purge the minority movers from the squad table and opposing list
foreach (PlayerModel mate in minority) {
RemovePlayerFromSquadRoster(squads, mate.Name);
opposingList = RemovePlayerFromList(opposingList, mate.Name);
}
// Purge the replacements from the squad table and target list
foreach (PlayerModel rep in replacements) {
RemovePlayerFromSquadRoster(squads, rep.Name);
targetList = RemovePlayerFromList(targetList, rep.Name);
}
// Swap the minority movers with the replacements
int i = 0;
foreach (PlayerModel mate in minority) {
try {
PlayerModel extra = replacements[i];
String mId = ExtractTagOrFriendex(mate);
String xId = ExtractTagOrFriendex(extra);
String mateName = (KeepFriendsInSameTeam && !String.IsNullOrEmpty(mId)) ? ("[" + mId + "]" + mate.Name) : (mate.FullName);
String extraName = (KeepFriendsInSameTeam && !String.IsNullOrEmpty(xId)) ? ("[" + xId + "]" + extra.Name) : (extra.FullName);
DebugScrambler("SWAP: ^b" + mateName + "^n/" + GetTeamName(opposing) + "/" + GetSquadName(mate.ScrambledSquad) + " with ^b" + extraName + "^n/" + GetTeamName(target) + "/" + GetSquadName(extra.ScrambledSquad));
int tmpSquad = extra.ScrambledSquad;
extra.ScrambledSquad = mate.ScrambledSquad;
mate.ScrambledSquad = tmpSquad;
extra.Team = opposing;
mate.Team = target;
targetList.Add(mate);
int mateKey = (1000 * mate.Team) + mate.ScrambledSquad;
AddPlayerToSquadRoster(squads, mate, mateKey, mate.ScrambledSquad, false);
opposingList.Add(extra);
int extraKey = (1000 * extra.Team) + extra.ScrambledSquad;
AddPlayerToSquadRoster(squads, extra, extraKey, extra.ScrambledSquad, false);
DebugScrambler(" Team " + GetTeamName(mate.Team) + " now has ^b" + mateName + "^n in " + GetSquadName(mate.ScrambledSquad) + " squad");
DebugScrambler(" Team " + GetTeamName(extra.Team) + " now has ^b" + extraName + "^n in " + GetSquadName(extra.ScrambledSquad) + " squad");
} catch (Exception e) {
ConsoleException(e);
}
++i;
}
// Validate
int maxTeam = perMode.MaxPlayers/2;
allOk = true;
if (targetList.Count > maxTeam) {
ConsoleDebug("ASSERT: too many players on team " + GetTeamName(target));
allOk = false;
}
if (opposingList.Count > maxTeam) {
ConsoleDebug("ASSERT: too many players on team " + GetTeamName(opposing));
allOk = false;
}
foreach (PlayerModel extra in opposingList) {
String testTag = ExtractTagOrFriendex(extra);
if (testTag == splitId) {
if (KeepFriendsInSameTeam) {
ConsoleDebug("ASSERT: minority clan member or friend not swapped ^b" + extra.FullName + "^n");
} else {
ConsoleDebug("ASSERT: minority clan member not swapped ^b" + extra.FullName + "^n");
}
// this is tolerable, so leave allOk set to true
}
}
} catch (Exception e) {
ConsoleException(e);
} finally {
// Must update the refs passed in
if (allOk) {
if (target == 1) {
if (targetList != null) usScrambled = targetList;
if (opposingList != null) ruScrambled = opposingList;
} else {
if (opposingList != null) usScrambled = opposingList;
if (targetList != null) ruScrambled = targetList;
}
}
}
}
if (KeepFriendsInSameTeam) {
DebugScrambler("Done keeping clan members or friends on the same teams!");
} else {
DebugScrambler("Done keeping clan members on the same teams!");
}
} catch (Exception e) {
ConsoleException(e);
} finally {
DebugScrambler(" ");
}
}