Skip to content

Commit

Permalink
Minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Foulest committed Jan 15, 2025
1 parent fac649f commit 08ddd77
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 49 deletions.
85 changes: 46 additions & 39 deletions src/main/java/net/foulest/swiss/Swiss.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import lombok.Data;
import net.foulest.swiss.brackets.ChampionsBracket;
import net.foulest.swiss.brackets.StandardBracket;
import net.foulest.swiss.match.Match;
import net.foulest.swiss.team.Team;

import java.util.ArrayList;
Expand All @@ -46,40 +47,39 @@ public static void main(String[] args) {
Scanner scanner = new Scanner(System.in, "UTF-8").useLocale(Locale.ROOT);

// Create teams with data from HLTV
Team g2 = new Team("G2", 1, 2, 3, 1.056);
// Team natusVincere = new Team("Natus Vincere", 2, 1, 1.098); // Eliminated
Team vitality = new Team("Vitality", 3, 3, 2, 1.122);
Team spirit = new Team("Spirit", 4, 4, 4, 1.076);
Team mouz = new Team("MOUZ", 5, 5, 8, 1.042);
Team faze = new Team("FaZe", 6, 6, 7, 1.030);
Team heroic = new Team("Heroic", 7, 7, 6, 1.094);
// Team _3DMAX = new Team("3DMAX", 8, 16, 1.056); // Eliminated
Team theMongolZ = new Team("The MongolZ", 9, 9, 1, 1.120);
Team liquid = new Team("Liquid", 10, 13, 5, 1.036);
// Team gamerLegion = new Team("GamerLegion", 11, 20, 1.032); // Eliminated
// Team furia = new Team("FURIA", 12, 8, 1.044); // Eliminated
// Team paiN = new Team("paiN", 13, 15, 1.108); // Eliminated
// Team wildcard = new Team("Wildcard", 14, 22, 1.056); // Eliminated
// Team big = new Team("BIG", 15, 19, 1.060); // Eliminated
// Team mibr = new Team("MIBR", 16, 17, 1.064); // Eliminated

// Add teams to the list
teams.add(g2);
// teams.add(natusVincere);
teams.add(vitality);
teams.add(spirit);
teams.add(mouz);
teams.add(faze);
teams.add(heroic);
// teams.add(_3DMAX);
teams.add(theMongolZ);
Team furia = new Team("FURIA", 8, 1, 1, 1.038);
Team mongolz = new Team("The MongolZ", 11, 7, 7, 1.112);
Team virtusPro = new Team("Virtus.Pro", 12, 2, 2, 1.060);
Team liquid = new Team("Liquid", 13, 3, 3, 1.044);
Team complexity = new Team("Complexity", 14, 4, 4, 1.030);
Team pain = new Team("PaiN", 17, 8, 8,1.094);
Team big = new Team("BIG", 18, 5, 5, 1.070);
Team mibr = new Team("MIBR", 19, 10, 10, 1.054);
Team flyQuest = new Team("FlyQuest", 20, 12, 12, 1.102);
Team gamerLegion = new Team("GamerLegion", 22, 9, 9,1.026);
Team wildcard = new Team("Wildcard", 24, 14, 14, 1.070);
Team imperial = new Team("Imperial", 26, 16, 16, 1.032);
Team passionUa = new Team("Passion UA", 28, 13, 13, 1.076);
Team fnatic = new Team("FNATIC", 29, 6, 6, 1.008);
Team cloud9 = new Team("Cloud9", 35, 11, 11, 1.098);
Team rareAtom = new Team("Rare Atom", 58, 15, 15, 0.950);

teams.add(furia);
teams.add(mongolz);
teams.add(virtusPro);
teams.add(liquid);
// teams.add(gamerLegion);
// teams.add(furia);
// teams.add(paiN);
// teams.add(wildcard);
// teams.add(big);
// teams.add(mibr);
teams.add(complexity);
teams.add(pain);
teams.add(big);
teams.add(mibr);
teams.add(flyQuest);
teams.add(gamerLegion);
teams.add(wildcard);
teams.add(imperial);
teams.add(passionUa);
teams.add(fnatic);
teams.add(cloud9);
teams.add(rareAtom);

System.out.println("Swiss - CS2 Major Monte Carlo Simulation");
System.out.println("by Foulest | github.com/Foulest");
Expand All @@ -100,12 +100,19 @@ public static void main(String[] args) {
return;
}

// // You can also display the winner of a match based on win probability
// // instead of simulating the entire bracket (these are just examples).
// if (bracketNumber == 0) {
// Match.displayWinnerFromProbability(wildcard, gamerLegion, true);
// return;
// }
// You can also display the winner of a match based on win probability
// instead of simulating the entire bracket (these are just examples).
if (bracketNumber == 0) {
Match.displayWinnerFromProbability(furia, gamerLegion, false);
Match.displayWinnerFromProbability(virtusPro, mibr, false);
Match.displayWinnerFromProbability(liquid, cloud9, false);
Match.displayWinnerFromProbability(complexity, flyQuest, false);
Match.displayWinnerFromProbability(big, passionUa, false);
Match.displayWinnerFromProbability(fnatic, wildcard, false);
Match.displayWinnerFromProbability(mongolz, rareAtom, false);
Match.displayWinnerFromProbability(pain, imperial, false);
return;
}

boolean standardBracket = bracketNumber == 1;

Expand Down
31 changes: 31 additions & 0 deletions src/main/java/net/foulest/swiss/brackets/Bracket.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,37 @@ default void printMatchResult(@NotNull Team winner,
+ " beat " + loserName + " (" + loserRecords[0] + "-" + loserRecords[1] + ")");
}

/**
* Print the match result with a win probability.
*
* @param winner The winning team.
* @param records The records of each team.
* @param loser The losing team.
* @param winProbability The win probability of the match for Team 1.
* @param team1 The first team.
*/
default void printMatchResult(@NotNull Team winner,
@NotNull Map<Team, int[]> records,
@NotNull Team loser,
double winProbability,
@NotNull Team team1) {
String winnerName = winner.getName();
String loserName = loser.getName();

int[] winnerRecords = records.get(winner);
int[] loserRecords = records.get(loser);

// Flip the win probability if team 1 isn't the winner
// This is needed because the win probability is always calculated for team 1
if (!winner.equals(team1)) {
winProbability = Math.abs(1 - winProbability);
}

System.out.println(winnerName + " (" + winnerRecords[0] + "-" + winnerRecords[1] + ")"
+ " beat " + loserName + " (" + loserRecords[0] + "-" + loserRecords[1] + ")"
+ " with a " + winProbability + "% win probability");
}

/**
* Append a probability to the result string if it exists.
*
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/net/foulest/swiss/brackets/StandardBracket.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ private void simulateBracket(Map<Team, Map<String, Integer>> results) {

// Create a match between the two teams
Match match = new Match(team1, team2, 1);
// double winProbability = Match.calculateWinProbability(team1, team2, false);

// Simulate the match
Team winner = match.simulate(false);
Expand All @@ -140,7 +141,7 @@ private void simulateBracket(Map<Team, Map<String, Integer>> results) {
updatePastOpponents(pastOpponents, winner, loser);

// // Print the match result
// printMatchResult(winner, records, loser);
// printMatchResult(winner, records, loser, winProbability, team1);
}

// Calculate Buchholz scores at the end of the group stage
Expand Down Expand Up @@ -283,6 +284,7 @@ private void simulateBracket(Map<Team, Map<String, Integer>> results) {
for (Match match : matches) {
Team team1 = match.getTeam1();
Team team2 = match.getTeam2();
// double winProbability = Match.calculateWinProbability(team1, team2, false);

// Simulate the match
Team winner = match.simulate(false);
Expand All @@ -298,7 +300,7 @@ private void simulateBracket(Map<Team, Map<String, Integer>> results) {
updatePastOpponents(pastOpponents, winner, loser);

// // Print the match result
// printMatchResult(winner, records, loser);
// printMatchResult(winner, records, loser, winProbability, team1);

// Add only teams that haven't been eliminated
if (records.get(winner)[1] < 3) {
Expand Down
35 changes: 27 additions & 8 deletions src/main/java/net/foulest/swiss/match/Match.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.foulest.swiss.team.Team;
import org.jetbrains.annotations.NotNull;

import java.sql.SQLOutput;
import java.util.Random;

/**
Expand Down Expand Up @@ -86,16 +87,16 @@ public Team simulate(boolean mostLikelyOnly) {
* @return The win probability of the first team.
*/
public static double calculateWinProbability(@NotNull Team t1, @NotNull Team t2, boolean bestOfThree) {
double worldRankingWeight = bestOfThree ? 0.60 / 100.0 : 0.40 / 100.0;
double worldRankingWeight = bestOfThree ? 0.60 : 0.40;
double playerRatingWeight = bestOfThree ? 0.40 : 0.60;
double scale = 5.0;

// Compute scores
double t1Score = worldRankingWeight * (100.0 - t1.getWorldRanking()) + playerRatingWeight * t1.getAvgPlayerRating();
double t2Score = worldRankingWeight * (100.0 - t2.getWorldRanking()) + playerRatingWeight * t2.getAvgPlayerRating();
double t1Score = (worldRankingWeight / 100.0) * (100.0 - t1.getWorldRanking()) + playerRatingWeight * t1.getAvgPlayerRating();
double t2Score = (worldRankingWeight / 100.0) * (100.0 - t2.getWorldRanking()) + playerRatingWeight * t2.getAvgPlayerRating();

// Calculate win probability
return 1.0 / (1.0 + Math.exp(-scale * (t1Score - t2Score)));
return (1.0 / (1.0 + Math.exp(-scale * (t1Score - t2Score))));
}

/**
Expand All @@ -105,14 +106,32 @@ public static double calculateWinProbability(@NotNull Team t1, @NotNull Team t2,
* @param t2 The second team.
*/
public static void displayWinnerFromProbability(@NotNull Team t1, @NotNull Team t2, boolean bestOfThree) {
double winProbability = calculateWinProbability(t1, t2, bestOfThree);
double t1WinProbability = calculateWinProbability(t1, t2, bestOfThree);
double t2WinProbability = 1 - t1WinProbability;

String t1Name = t1.getName();
String t2Name = t2.getName();

if (winProbability >= 0.5) {
System.out.println(t1Name + " has a " + (winProbability * 100) + "% chance of winning against " + t2Name);
if (t1WinProbability >= 0.5) {
System.out.println(t1Name + " has a " + (t1WinProbability * 100) + "% chance of winning against " + t2Name);
} else {
System.out.println(t2Name + " has a " + ((1 - winProbability) * 100) + "% chance of winning against " + t1Name);
System.out.println(t2Name + " has a " + ((1 - t1WinProbability) * 100) + "% chance of winning against " + t1Name);
}

// Calculate win probability for dynamic rating adjustment
double actualOutcome = (t1WinProbability >= 0.5) ? 1 : 0; // 1 if team1 wins, 0 if team2 wins

// Randomly generate the K-factor between 0.003 and 0.007
double K = 0.003 + Math.random() * 0.004;

// Get average player ratings
double t1AvgPlayerRating = t1.getAvgPlayerRating();
double t2AvgPlayerRating = t2.getAvgPlayerRating();

// Print ratings using Elo-like formula
System.out.println(t1Name + "'s rating would change from " + t1AvgPlayerRating + " to "
+ (t1AvgPlayerRating + K * (actualOutcome - t1WinProbability)));
System.out.println(t2Name + "'s rating would change from " + t2AvgPlayerRating + " to "
+ (t2AvgPlayerRating + K * ((1 - actualOutcome) - t2WinProbability)));
}
}

0 comments on commit 08ddd77

Please sign in to comment.