diff --git a/build.xml b/build.xml
index da22126..0013d84 100644
--- a/build.xml
+++ b/build.xml
@@ -9,6 +9,12 @@
+
+
+
+
+
+
@@ -24,8 +30,12 @@
+ destdir="${build.dir}/classes">
+
+
+
+
+
@@ -36,12 +46,19 @@
+
+
+
+
+
+
+
diff --git a/lib/groovy-all-1.7.2.jar b/lib/groovy-all-1.7.2.jar
deleted file mode 100644
index 7b50f70..0000000
Binary files a/lib/groovy-all-1.7.2.jar and /dev/null differ
diff --git a/lib/log4j-1.2.15.jar b/lib/log4j-1.2.15.jar
new file mode 100644
index 0000000..c930a6a
Binary files /dev/null and b/lib/log4j-1.2.15.jar differ
diff --git a/lib/miglayout-3.7.1-swing.jar b/lib/miglayout-3.7.1-swing.jar
deleted file mode 100644
index 5a762c8..0000000
Binary files a/lib/miglayout-3.7.1-swing.jar and /dev/null differ
diff --git a/log4j.properties b/log4j.properties
new file mode 100644
index 0000000..aff155b
--- /dev/null
+++ b/log4j.properties
@@ -0,0 +1,10 @@
+log4j.rootLogger=TRACE,stdout
+log4j.com.jdbernard.teammaker=TRACE,file
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
+
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.file=teammaker.log
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.pattern=%-5p (%c)[%t]: %m%n
diff --git a/project.properties b/project.properties
index 7b97afb..e53b4ae 100644
--- a/project.properties
+++ b/project.properties
@@ -1,6 +1,8 @@
+#Tue, 06 Jul 2010 06:30:26 -0500
#Mon Jul 05 23:10:39 CDT 2010
app.version=0.3.0
-build.number=47
+build.number=67
src.dir=src
+lib.dir=lib
build.dir=build
app.name=team-maker
diff --git a/src/com/jdbernard/teammaker/OddsCalculator.groovy b/src/com/jdbernard/teammaker/OddsCalculator.groovy
index 84bb4f5..4043f2a 100644
--- a/src/com/jdbernard/teammaker/OddsCalculator.groovy
+++ b/src/com/jdbernard/teammaker/OddsCalculator.groovy
@@ -1,14 +1,26 @@
package com.jdbernard.teammaker
+import org.apache.log4j.Logger
+
public class OddsCalculator {
Map odds = [:]
+ protected Logger log = Logger.getLogger(getClass())
+
public void recalculate(List players, int spotsOpen, PlayerChooser chooser) {
+ if (log.isTraceEnabled()) log.trace("Recalculating odds.")
+
// reset computed player odds
odds = [:]
+ // first check the trivial case: more spots than players
+ if (spotsOpen >= players.size()) {
+ players.each { odds[(it)] = 1f }
+ return
+ }
+
/* this list will contain each possible selection path with
* the odds at each node. It is a list of lists of lists::
*
@@ -24,7 +36,7 @@ public class OddsCalculator {
* ]
*/
- def oddsList = buildOdds([], players, spotsOpen)
+ def oddsList = buildOdds([], players, spotsOpen, chooser)
/* The oddsMap is a condensed version of the oddsList, calculating
* the overall probability of each path::
@@ -67,9 +79,12 @@ public class OddsCalculator {
odds[(player)] = playerOdds
}
+
+ if (log.isTraceEnabled()) log.trace("Finished recalculating odds.")
}
- protected List buildOdds(List chosenPath, List players, int spotsOpen) {
+ protected List buildOdds(List chosenPath, List players, int spotsOpen,
+ PlayerChooser chooser) {
def oddsList = []
if (spotsOpen == 0) return [chosenPath]
@@ -78,7 +93,8 @@ public class OddsCalculator {
def odds = chooser.getOdds(players, player)
def newPath = chosenPath.clone()
newPath << [player, odds]
- oddsList.addAll(buildOdds(newPath, players - [player], spotsOpen - 1))
+ oddsList.addAll(buildOdds(newPath, players - [player],
+ spotsOpen - 1, chooser))
}
return oddsList
diff --git a/src/com/jdbernard/teammaker/PlayerChooser.groovy b/src/com/jdbernard/teammaker/PlayerChooser.groovy
index b040be9..ddddba6 100644
--- a/src/com/jdbernard/teammaker/PlayerChooser.groovy
+++ b/src/com/jdbernard/teammaker/PlayerChooser.groovy
@@ -1,13 +1,29 @@
package com.jdbernard.teammaker
+import org.apache.log4j.Logger
+
public abstract class PlayerChooser {
+ // ======== CLASS DATA ======== //
protected static final Random rand = new Random(System.currentTimeMillis())
+ // ======== PUBLIC METHODS ======== //
public abstract Player choose (def players)
public abstract float getOdds(def players, Player player)
+ // ======== INSTANCE DATA ======== //
+ protected Logger log = Logger.getLogger(getClass())
+
+ // ======== NON-PUBLIC METHODS ======== //
protected Player chooseRandomly(List choices) {
+
+ if (log.isTraceEnabled())
+ log.trace("Choosing randomly from: ${choices})")
+
choices.sort { rand.nextInt() }
+
+ if (log.isTraceEnabled()) log.trace("Chose: ${choices[0]}")
+
+ return choices[0]
}
}
diff --git a/src/com/jdbernard/teammaker/PlayerListCellRenderer.groovy b/src/com/jdbernard/teammaker/PlayerListCellRenderer.groovy
index 75b65e8..5c860c4 100644
--- a/src/com/jdbernard/teammaker/PlayerListCellRenderer.groovy
+++ b/src/com/jdbernard/teammaker/PlayerListCellRenderer.groovy
@@ -58,8 +58,8 @@ public class PlayerListCellRenderer extends JPanel implements ListCellRenderer {
else setBorder(emptyBorder)
if (showStats) {
- int odds = Math.round(teamMaker.playerChooser.calculateOdds(
- list.model, teamMaker.spotsOpen, value) * 100)
+ def odds = teamMaker.oddsCalculator.odds[(value)]
+ odds = odds ? Math.round(odds * 100) : "?"
statsLabel.text = "${value.gamesSat} (${odds}%)"
}
diff --git a/src/com/jdbernard/teammaker/RandomPlayerChooser.groovy b/src/com/jdbernard/teammaker/RandomPlayerChooser.groovy
index ba40877..5e03182 100644
--- a/src/com/jdbernard/teammaker/RandomPlayerChooser.groovy
+++ b/src/com/jdbernard/teammaker/RandomPlayerChooser.groovy
@@ -1,6 +1,6 @@
package com.jdbernard.teammaker
-public class RandomPlayerChooser extends AbstractPlayerChooser {
+public class RandomPlayerChooser extends PlayerChooser {
public Player choose(def players) {
def choices = []
diff --git a/src/com/jdbernard/teammaker/TeamMaker.groovy b/src/com/jdbernard/teammaker/TeamMaker.groovy
index 540c3d4..eea7e04 100644
--- a/src/com/jdbernard/teammaker/TeamMaker.groovy
+++ b/src/com/jdbernard/teammaker/TeamMaker.groovy
@@ -8,6 +8,7 @@ import java.awt.BorderLayout
import javax.swing.DefaultListModel
import javax.swing.JFrame
import javax.swing.JOptionPane
+import org.apache.log4j.Logger
public class TeamMaker {
@@ -24,7 +25,10 @@ public class TeamMaker {
def newGameButton
def sittingList
- AbstractPlayerChooser playerChooser = GameWeightedChooser.getInstance()
+ protected Logger log = Logger.getLogger(getClass())
+
+ PlayerChooser playerChooser = new WeightedChooser(hardLimit: 2)
+ OddsCalculator oddsCalculator = new OddsCalculator()
class Observables {
@Bindable boolean inGame = false
@@ -134,6 +138,7 @@ public class TeamMaker {
}
}
+
}
@@ -147,6 +152,7 @@ public class TeamMaker {
}
TeamMaker() {
+ log.fatal("Is this thing on?")
init()
}
@@ -167,6 +173,13 @@ public class TeamMaker {
player.name = name
player.gamesSat = 0
sittingList.model.addElement(player)
+
+ // recalculate odds
+ def players = sittingList.model.collect { it }
+ swing.doOutside {
+ oddsCalculator.recalculate(players, getSpotsOpen(), playerChooser)
+ swing.edt { sittingList.repaint() }
+ }
}
private void newGame() {
@@ -177,9 +190,13 @@ public class TeamMaker {
populate(team2List)
model.inGame = true
- //team1WinsButton.enabled = true
- //team2WinsButton.enabled = true
- //newGameButton.enabled = false
+
+ // recalculate odds
+ def players = sittingList.model.collect { it }
+ swing.doOutside {
+ oddsCalculator.recalculate(players, getSpotsOpen(), playerChooser)
+ swing.edt { sittingList.repaint() }
+ }
}
private void declareWinner(def teamList) {
@@ -188,12 +205,18 @@ public class TeamMaker {
player.gamesSat = 0
sittingList.model.addElement(player)
}
+
+ //recalculate odds
+ def players = sittingList.model.collect { it }
+ swing.doOutside {
+ oddsCalculator.recalculate(players, getSpotsOpen(), playerChooser)
+ swing.edt { sittingList.repaint() }
+ }
+
teamList.model.clear()
teamList.repaint()
sittingList.repaint()
model.inGame = false
- //team1WinsButton.enabled = false
- //team2WinsButton.enabled = false
}
private void populate(def teamList) {
diff --git a/src/com/jdbernard/teammaker/WeightedChooser.groovy b/src/com/jdbernard/teammaker/WeightedChooser.groovy
index 15f4fbd..5b80149 100644
--- a/src/com/jdbernard/teammaker/WeightedChooser.groovy
+++ b/src/com/jdbernard/teammaker/WeightedChooser.groovy
@@ -1,14 +1,20 @@
package com.jdbernard.teammaker
-public abstract class WeightedChooser extends AbstractPlayerChooser {
+public class WeightedChooser extends PlayerChooser {
int hardLimit = 5
public Player choose(def players) {
+ // make a proper list
+ players = players.collect { it }
def choices = []
+ def threshold = getThreshold(players)
- // find sitting threshold (longest sat - hard limit)
- int threshold = (player.max { it.gamesSat }) - hardLimit
+ if (log.isTraceEnabled()) {
+ log.trace("Choosing a player weighted by games sat.")
+ log.trace("Players: $players")
+ log.trace("Threshold: $threshold")
+ }
// add players, ignoring those past the hard limit
players.each { player ->
@@ -17,12 +23,28 @@ public abstract class WeightedChooser extends AbstractPlayerChooser {
player.gamesSat.times { choices << player }
}
}
+
return chooseRandomly(choices)
}
public float getOdds(def players, Player player) {
- def playerGames = player.gamesSat + 1
- def totalGames = players.sum { it.gamesSat + 1 }
+ def threshold = getThreshold(players)
+
+ def playerGames = player.gamesSat >= threshold ?
+ player.gamesSat + 1 : 0
+
+ def totalGames = players.sum {
+ it.gamesSat >= threshold ? it.gamesSat + 1 : 0
+ }
+
+ if (log.isTraceEnabled())
+ log.trace("Odds for $player: $playerGames / $totalGames = " +
+ ((float) playerGames / (float) totalGames))
+
return (float) playerGames / (float) totalGames
}
+
+ protected int getThreshold(def players) {
+ return (players.max { it.gamesSat }).gamesSat - hardLimit
+ }
}