Created
October 4, 2018 21:28
-
-
Save Xirema/744ba7a0c00ddf87320405942af5d651 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.scratch.test; | |
import java.awt.Font; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import java.awt.event.WindowAdapter; | |
import java.awt.event.WindowEvent; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Random; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import javax.swing.JFrame; | |
import javax.swing.JTextArea; | |
import javax.swing.SwingUtilities; | |
import javax.swing.Timer; | |
import org.scratch.main.util.Pair; | |
//Pair is a basic utility class that simply stores two fields. Can be implemented in about 50 lines of code if needed, based on Apache Commons Pair. | |
public class ClassPopularity { | |
public static class Results { | |
final List<Pair<Integer, Integer>> sample; | |
final List<Pair<Integer, Boolean>> thresholds; | |
public Results(List<Pair<Integer, Integer>> b, List<Pair<Integer, Boolean>> c) { | |
sample = b; | |
thresholds = c; | |
} | |
} | |
public static Results sample(Random engine, int numOfBuckets, int numOfParticipants, int threshold) { | |
List<Pair<Integer, Integer>> results = new ArrayList<>(); | |
for(int i = 0; i < numOfBuckets; i++) { | |
results.add(Pair.of(i, 0)); | |
} | |
for(int i = 0; i < numOfParticipants; i++) { | |
int bucket = engine.nextInt(numOfBuckets); | |
results.set(bucket, Pair.of(bucket, results.get(bucket).second + 1)); | |
} | |
Collections.sort(results, new Comparator<Pair<Integer, Integer>>() { | |
@Override | |
public int compare(Pair<Integer, Integer> arg0, | |
Pair<Integer, Integer> arg1) { | |
return arg1.second - arg0.second; | |
} | |
}); | |
List<Pair<Integer, Boolean>> thresholds = new ArrayList<>(); | |
for(int i = 0; i < numOfBuckets; i++) { | |
threshold -= results.get(i).second; | |
thresholds.add(Pair.of(i, threshold <= 0)); | |
} | |
// Collections.sort(results, new Comparator<Pair<Integer, Integer>>() { | |
// @Override | |
// public int compare(Pair<Integer, Integer> arg0, | |
// Pair<Integer, Integer> arg1) { | |
// return arg0.first - arg1.first; | |
// } | |
// }); | |
return new Results(results, thresholds); | |
} | |
public static void main(String[] args) { | |
final int NUM_OF_BUCKETS = 12; | |
final int NUM_OF_PARTICIPANTS = 30; | |
final int THRESHOLD = (int)(NUM_OF_PARTICIPANTS * 0.50); | |
JFrame frame = new JFrame("Popularity Graph"); | |
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); | |
JTextArea resultsPanel = new JTextArea(NUM_OF_BUCKETS * 2 + 3, 50); | |
resultsPanel.setEditable(false); | |
resultsPanel.setFont(new Font("Courier New", Font.PLAIN, 18)); | |
frame.getContentPane().add(resultsPanel); | |
frame.pack(); | |
frame.setVisible(true); | |
frame.setLocationRelativeTo(null); | |
frame.setResizable(false); | |
final AtomicBoolean running = new AtomicBoolean(true); | |
frame.addWindowListener(new WindowAdapter() { | |
@Override | |
public void windowClosing(WindowEvent arg0) { | |
running.set(false); | |
} | |
}); | |
final AtomicBoolean shouldPrintResults = new AtomicBoolean(true); | |
Timer updateTimer = new Timer(500, new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent arg0) { | |
shouldPrintResults.set(true); | |
} | |
}); | |
updateTimer.start(); | |
long numOfTrials = 0; | |
long[] numOfSuccesses = new long[NUM_OF_BUCKETS]; | |
Arrays.fill(numOfSuccesses, 0L); | |
Random engine = new Random(); | |
while(running.get()) { | |
Results results = sample(engine, NUM_OF_BUCKETS, NUM_OF_PARTICIPANTS, THRESHOLD); | |
numOfTrials++; | |
for(Pair<Integer, Boolean> threshold : results.thresholds){ | |
if(threshold.second) | |
numOfSuccesses[threshold.first]++; | |
} | |
if(shouldPrintResults.get()) { | |
shouldPrintResults.set(false); | |
setTextArea(resultsPanel, numOfTrials, numOfSuccesses, results, THRESHOLD, NUM_OF_PARTICIPANTS); | |
} | |
} | |
System.out.println("Done."); | |
updateTimer.stop(); | |
} | |
private static void setTextArea(final JTextArea resultsPanel, final long numOfTrials, long[] numOfSuccesses, final Results currentResults, final int threshold, final int numOfParticipants) { | |
final long[] currentSuccesses = Arrays.copyOf(numOfSuccesses, numOfSuccesses.length); | |
SwingUtilities.invokeLater(new Runnable() { | |
@Override | |
public void run() { | |
String text = ""; | |
text += "Num of Trials:" + String.format("%10d", numOfTrials) + " (PARTICIPANTS=" + numOfParticipants + ")\n"; | |
text += "Num of Successes (THRESHOLD=" + threshold + "): \n"; | |
for(int i = 0; i < currentSuccesses.length; i++) { | |
text += String.format(" %2d: %10d (%5.2f%%)\n", i + 1, currentSuccesses[i], (double)currentSuccesses[i] / numOfTrials * 100.0); | |
} | |
text += "Current Results:\n"; | |
for(Pair<Integer, Integer> ret : currentResults.sample) { | |
text += " " + String.format("%-10s", classNames.get(ret.first)) + ": " + ret.second + "\n"; | |
} | |
text = text.substring(0, text.length() - 1); | |
resultsPanel.setText(text); | |
} | |
}); | |
} | |
static Map<Integer, String> classNames = new HashMap<>(); | |
static { | |
classNames.put(0, "Barbarian"); | |
classNames.put(1, "Bard"); | |
classNames.put(2, "Cleric"); | |
classNames.put(3, "Druid"); | |
classNames.put(4, "Fighter"); | |
classNames.put(5, "Paladin"); | |
classNames.put(6, "Rogue"); | |
classNames.put(7, "Monk"); | |
classNames.put(8, "Ranger"); | |
classNames.put(9, "Wizard"); | |
classNames.put(10, "Warlock"); | |
classNames.put(11, "Sorcerer"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment