Reorganized odds structure.
This commit is contained in:
parent
242fbf2e56
commit
5d6f5882de
21
build.xml
21
build.xml
@ -9,6 +9,12 @@
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="lib.class.path">
|
||||
<fileset dir="${lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<taskdef name="groovyc"
|
||||
classpathref="groovy.class.path"
|
||||
classname="org.codehaus.groovy.ant.Groovyc"/>
|
||||
@ -24,8 +30,12 @@
|
||||
<target name="compile" depends="init">
|
||||
<groovyc
|
||||
srcdir="${src.dir}"
|
||||
destdir="${build.dir}/classes"
|
||||
classpathref="groovy.class.path"/>
|
||||
destdir="${build.dir}/classes">
|
||||
<classpath>
|
||||
<path refid="groovy.class.path"/>
|
||||
<path refid="lib.class.path"/>
|
||||
</classpath>
|
||||
</groovyc>
|
||||
</target>
|
||||
|
||||
<target name="increment-build-number">
|
||||
@ -36,12 +46,19 @@
|
||||
</target>
|
||||
|
||||
<target name="build" depends="compile,increment-build-number">
|
||||
<copy todir="${build.dir}/classes" file="log4j.properties"/>
|
||||
<unjar dest="${build.dir}/classes">
|
||||
<fileset dir="${env.GROOVY_HOME}/embeddable">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</unjar>
|
||||
|
||||
<unjar dest="${build.dir}/classes">
|
||||
<fileset dir="${lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</unjar>
|
||||
|
||||
<jar
|
||||
destfile="${build.dir}/${app.name}-${app.version}.${build.number}.jar"
|
||||
basedir="${build.dir}/classes">
|
||||
|
Binary file not shown.
BIN
lib/log4j-1.2.15.jar
Normal file
BIN
lib/log4j-1.2.15.jar
Normal file
Binary file not shown.
Binary file not shown.
10
log4j.properties
Normal file
10
log4j.properties
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
@ -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}%)"
|
||||
}
|
||||
|
||||
|
@ -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 = []
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user