// BJTrainer in java// TODO://		Fix layout of panel to use a GridBag and get things positioned more like a javax.swing.Box//Note://The flashcards approach is superior to playing out real shoes of real cards.//The distribution of plays is as follows://	Hard Hands	1716	78.11%//	Splits		 169	 7.69%//	Soft Hands	 312	14.20%//The splits and soft hands with doubling lead to larger bets and require more//in-depth knowledge of how to play.import java.lang.StringBuffer;import java.util.Random;import java.lang.Math;import java.util.Vector;import java.util.Enumeration;import java.util.Hashtable;import java.util.Observable;import java.util.Observer;import java.awt.*;import java.applet.Applet;/* Generate random numbers within a specified range */class RandomRange extends java.util.Random {	/* generate a number, r, such that 0 <= r < limit */	int randrange( int limit ) {		return Math.abs(nextInt()) % limit;	}	/* generate a number, r, low <= r < high */	int randrange( int low, int high ) {		return low + Math.abs(nextInt()) % (high-low);	}}/* Model simple playing cards */class Card {	static final int Clubs= 0;	static final int Diamonds= 1;	static final int Hearts= 2;	static final int Spades= 3;	String[] suitNames = { "C", "D", "H", "S" };	String[] rankNames = { "", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };	int suit;	int rank;	public Card( int aRank, int aSuit ) {		// System.out.println( "Card(" + aRank + "," + aSuit + ")" );		rank= aRank;		suit= aSuit;	}	public String toString() {		return rankNames[rank] + suitNames[suit];	}}/* Model a simple blackjack hand */class Hand {	Vector cards= new Vector(5);	public Hand( Card c1, Card c2 ) {		cards.addElement( c1 );		cards.addElement( c2 );	}	public void addCard( Card aCard ) {		cards.addElement( aCard );	}	public String toString() {		StringBuffer r= new StringBuffer();		Enumeration e= cards.elements();		Card c= (Card)e.nextElement();		r.append( c );		while( e.hasMoreElements() ) {			r.append( " " );			c= (Card)e.nextElement();			r.append( c );		}		return r.toString();	}}/* Model a simple hard-hands playing rule for blackjack */class Rule {	String name;	int youHave;	int[] dealerHas;	String response;	String hint;	String explanation;	RandomRange r= new RandomRange();	public Rule() {	}	public Rule( String aName, int aYouHave, int[] aDealer, String aResponse, String aHint, String anExplanation ) {		name= aName;		youHave= aYouHave;		dealerHas= aDealer;		response= aResponse;		hint= aHint;		explanation= anExplanation;	}	public Card makeCard( int points ) {		int suit= r.randrange(4);		int rank= 0;		if( points == 11 ) { rank= 1; }		else if( points == 10 ) { rank= r.randrange(10,14); }		else { rank= points; }		return new Card( rank, suit );	}	public Hand make2Cards( int points ) {		// For a hard hand, create two cards that add to the required number.		// Pick a value, c1, such that 2 <= c1 <= int((number-1)/2).		// C1 is provably less than number/2, so we won't get a pair.		// Also, 2 <= c1 <= 10 and 2 <= number-c1 <= 10; must be changed when number > 12.		// For number > 12, must raise the lower limit above 2 to satisfy the <= 10 constraint		// (wouldn't want to generate 4H, 12D to make a hard 16!)		int upper= ((int)(points-1)/2)+1;		int lower= 2;		if( points - 10 > 2 ) { lower= points-10; }		int c1= r.randrange(lower,upper);		return new Hand( makeCard(c1), makeCard(points-c1) );	}	public Card dealerCard() {		int c= r.randrange( dealerHas.length );		return makeCard( dealerHas[c] );	}	public Hand playerHand() {		return make2Cards( youHave );	}	public boolean rightPlay( String play ) {		return response.equals(play);	}	public String toString() {		StringBuffer r= new StringBuffer();		r.append( "(" );		r.append( '"' ).append( name ).append( '"' ).append( "," );		r.append( youHave ).append( ",[" ).append( dealerHas[0] );		for( int i= 1; i != dealerHas.length; ++i ) {			r.append( "," ).append( dealerHas[i] );		}		r.append( "]," );		r.append( '"' ).append( response ).append( '"' ).append( "," );		r.append( '"' ).append( hint ).append( '"' ).append( "," );		r.append( '"' ).append( explanation ).append( '"' );		r.append( ")" );		return r.toString();	}}/* Model soft or split hands */class RuleSplitSoft extends Rule {	int[] youHave;	public RuleSplitSoft( String aName, int[] aYouHave, int[] aDealer, String aResponse, String aHint, String anExplanation ) {		name= aName;		youHave= aYouHave;		dealerHas= aDealer;		response= aResponse;		hint= aHint;		explanation= anExplanation;	}	public Hand playerHand() {		return new Hand( makeCard(youHave[0]), makeCard(youHave[1]) );	}}/* A Presentation records the number of presentations and the number of right answers for a rule */class Presentation {	String rule= "";	int shown= 1;	int right= 0;	public Presentation( String aRule ) {		rule= aRule;	}	public boolean problem() {		return shown != right;	}	public String toString() {		return rule + " " + shown + " " + right;	}}/* A History is an observable that records all hands presented */class History extends Observable {	int totalPresent= 0;	int totalRight= 0;	Hashtable details= new Hashtable();	Rule current;	public History() {	}	public void present( Rule aRule ) {		current= aRule;		Presentation newCount;		if( details.containsKey( current.name ) ) {			newCount= (Presentation)details.get( current.name );			newCount.shown= newCount.shown + 1;		}		else {			newCount= new Presentation( current.name );		}		details.put( current.name, newCount );	}	public void right() {		totalPresent = totalPresent + 1;		totalRight= totalRight + 1;		Presentation newCount= (Presentation)details.get( current.name );		newCount.right= newCount.right + 1;		setChanged();		notifyObservers();	}	public void wrong() {		totalPresent = totalPresent + 1;		setChanged();		notifyObservers();	}	public Enumeration keys() {		return details.keys();	}	public String summary() {		if( totalPresent == 0 ) return "";		return "" + totalRight + " out of " + totalPresent + ": " + (100*totalRight)/totalPresent + "%";	}	public String missedReport() {		StringBuffer rpt= new StringBuffer();		Enumeration e= details.elements();		while( e.hasMoreElements() ) {			Presentation p= (Presentation)e.nextElement();			if( p.problem() ) {				rpt.append( p.rule + ": " + p.shown + " shown, " + p.right + " right: " + (100*p.right)/p.shown + "%\n" );			}		}		return rpt.toString();	}}/* A Trainer has a set of rules and presents one rule, flashcards-style */class Trainer {	RandomRange r= new RandomRange();	int[] cardAll=	{2,3,4,5,6,7,8,9,10,11};	int[] card3_6 = {3,4,5,6};	int[] card27_11={2,7,8,9,10,11};	int[] card2_9=  {2,3,4,5,6,7,8,9};	int[] card1011= {10,11};	int[] card2_10= {2,3,4,5,6,7,8,9,10};	int[] card11=   {11};	int[] card23=   {2,3};	int[] card4_6=  {4,5,6};	int[] card7_11= {7,8,9,10,11};	int[] card2_6=  {2,3,4,5,6};	int[] card2_47_11={2,3,4,7,8,9,10,11};	int[] card56=	{5,6};	int[] card2_37_11={2,3,7,8,9,10,11};	int[] card456=	{4,5,6};	int[] card278=  {2,7,8};	int[] card91011={9,10,11};	int[] card2_7=  {2,3,4,5,6,7};	int[] card8_11= {8,9,10,11};	int[] card2_689={2,3,4,5,6,8,9};	int[] card71011={7,10,11};	int[] Ace2=		{11,2};	int[] Ace3=		{11,3};	int[] Ace4=		{11,4};	int[] Ace5=		{11,5};	int[] Ace6=		{11,6};	int[] Ace7=		{11,7};	int[] Ace8=		{11,8};	int[] Ace9=		{11,9};	int[] Pr2=		{2,2};	int[] Pr3=		{3,3};	int[] Pr4=		{4,4};	int[] Pr5=		{5,5};	int[] Pr6=		{6,6};	int[] Pr7=		{7,7};	int[] Pr8=		{8,8};	int[] Pr9=		{9,9};	int[] Pr10=		{10,10};	int[] PrA=		{11,11};	Rule[] rSet= {		new Rule("<=8", 5, cardAll,	"hit",	"need to meet or beat 17", "always hit <= 8" ),		new Rule("<=8", 6, cardAll,	"hit",	"need to meet or beat 17", "always hit <= 8" ),		new Rule("<=8", 7, cardAll,	"hit",	"need to meet or beat 17", "always hit <= 8" ),		new Rule("<=8", 8, cardAll,	"hit",	"need to meet or beat 17", "always hit <= 8" ),		new Rule(  "9", 9, card3_6,	"double","dealer may bust with 3-6", "double on 9 when dealer weak (3-6), hoping for win" ),		new Rule(  "9", 9, card27_11,"hit",	"need to meet or beat 19", "hit 9 when dealer strong (2,>=7), hoping for tie" ),		new Rule( "10", 10,card2_9,	"double","dealer weaker with 2-9", "double on 10 when dealer has less" ),		new Rule( "10", 10,card1011,"hit",	"need to meet or beat 20", "hit 10 when dealer may have 20 or 21" ),		new Rule( "11", 11,card2_10,"double","dealer weaker with 2-10", "double on 11 when dealer has less" ),		new Rule( "11", 11,card11,	"hit",	"need to meet 21", "hit 11 when dealer may have 21" ),		new Rule( "12", 12,card23,	"hit",	"need to meet or beat 17", "hit 12 against dealer's medium 2 or 3" ),		new Rule( "12", 12,card4_6, "stand","play it safe, dealer weak", "stand on 12 when dealer weak (4-6)" ),		new Rule( "12", 12,card7_11,"hit",	"need to meet or beat 17", "hit 12 when dealer strong (>=7)" ),		new Rule("13-16",13,card2_6,"stand","play it safe, dealer weak", "stand on 13 when dealer weak (2-6)" ),		new Rule("13-16",13,card7_11,"hit",	"need to meet or beat 17", "hit 13 when dealer strong (>=7)" ),		new Rule("13-16",14,card2_6,"stand","play it safe, dealer weak", "stand on 14 when dealer weak (2-6)" ),		new Rule("13-16",14,card7_11,"hit",	"need to meet or beat 17", "hit 14 when dealer strong (>=7)" ),		new Rule("13-16",15,card2_6,"stand","play it safe, dealer weak", "stand on 15 when dealer weak (2-6)" ),		new Rule("13-16",15,card7_11,"hit",	"need to meet or beat 17", "hit 15 when dealer strong (>=7)" ),		new Rule("13-16",16,card2_6,"stand","play it safe, dealer weak", "stand on 16 when dealer weak (2-6)" ),		new Rule("13-16",16,card7_11,"hit",	"need to meet or beat 17", "hit 16 when dealer strong (>=7)" ),		new Rule("17-19",17,cardAll,"stand","good hand", "stand, excellent hand" ),		new Rule("17-19",18,cardAll,"stand","good hand", "stand, excellent hand" ),		new Rule("17-19",19,cardAll,"stand","good hand", "stand, excellent hand" ),		new RuleSplitSoft("A2",Ace2, card2_47_11, "hit",	"dealer 12-14, >=17 beats your 13", "hit unless dealer weak with 5 or 6" ),		new RuleSplitSoft("A2",Ace2, card56,	  "double", "dealer may bust with 5-6", "double when dealer weak with 5 or 6" ),		new RuleSplitSoft("A3",Ace3, card2_47_11, "hit",	"dealer 12-14, >=17 beats your 14", "hit unless dealer weak with 5 or 6" ),		new RuleSplitSoft("A3",Ace3, card56,	  "double", "dealer may bust with 5-6", "double when dealer weak with 5 or 6" ),		new RuleSplitSoft("A45",Ace4,card2_37_11, "hit",	"dealer 12-13, >=17 beats your 15", "hit unless dealer weak with 4-6" ),		new RuleSplitSoft("A45",Ace4,card456,	  "double", "dealer may bust with 4-6", "double when dealer weak with 4-6" ),		new RuleSplitSoft("A45",Ace5,card2_37_11, "hit",	"dealer 12-13, >=17 beats your 16", "hit unless dealer weak with 4-6" ),		new RuleSplitSoft("A45",Ace5,card456,	  "double", "dealer may bust with 4-6", "double when dealer weak with 4-6" ),		new RuleSplitSoft("A6",Ace6, card27_11,	  "hit",	"dealer 12, >=17 beats your 16", "hit unless dealer weak with 3-6" ),		new RuleSplitSoft("A6",Ace6, card3_6,	  "double", "dealer may bust with 3-6", "double when dealer weak with 3-6" ),		new RuleSplitSoft("A7",Ace7, card278,	  "stand","likely to get hard 18", "stand, excellent hand when dealer medium 2,7,8" ),		new RuleSplitSoft("A7",Ace7, card91011,	  "hit",	"dealer has 19-21", "hit when dealer strong with 9-A" ),		new RuleSplitSoft("A7",Ace7, card3_6,	  "double","dealer may bust with 3-6", "double when dealer weak with 3-6" ),		new RuleSplitSoft("A89",Ace8,cardAll, 	  "stand",   "soft 19", "stand, excellent hand" ),		new RuleSplitSoft("A89",Ace9,cardAll,	  "stand",   "soft 20", "stand, excellent hand" ),		new RuleSplitSoft("22",Pr2,  card2_7,	  "split","dealer may bust with 2-6, win with 7", "2 12's best against weak dealer with 2-7" ),		new RuleSplitSoft("22",Pr2,  card8_11,	  "hit",	"dealer 18-21 beats your hard 14", "hit 4 to beat dealer with >=8" ),		new RuleSplitSoft("33",Pr3,  card2_7,	  "split","dealer may bust with 2-6, win with 7", "2 13's best against weak dealer with 2-7" ),		new RuleSplitSoft("33",Pr3,  card8_11,	  "hit",	"dealer 18-21 beats your hard 16", "hit 6 to beat dealer with >=8" ),		new RuleSplitSoft("44",Pr4,  card56,	  "split","dealer may bust with 5-6", "2 14's best against very weak dealer with 5-6" ),		new RuleSplitSoft("44",Pr4,  card2_47_11, "hit",	"dealer 12-14, >=17 may beat your 8", "hit 8 to beat dealer with 2-4,>=8" ),		new RuleSplitSoft("55",Pr5,  card2_9,	  "double","likely to get 20", "double on 10 when dealer has less" ),		new RuleSplitSoft("55",Pr5,  card1011,	  "hit",	"likely to get 20", "hit 10 when dealer may have 20 or 21" ),		new RuleSplitSoft("66",Pr6,  card2_6,	  "split","dealer may bust with 2-6", "2 16's best against weak dealer with 2-6" ),		new RuleSplitSoft("66",Pr6,  card7_11,	  "hit",	"dealer 17-21 beats your 12", "hit 12 to beat strong dealer with >=7" ),		new RuleSplitSoft("77",Pr7,  card2_7,	  "split","dealer may bust with 2-6, win with 7", "2 17's best against weak dealer with 2-7" ),		new RuleSplitSoft("77",Pr7,  card8_11,	  "hit",	"dealer >= 18 may beat your 14", "hit 14 to beat strong dealer with >=8" ),		new RuleSplitSoft("88",Pr8,  cardAll, 	  "split", "two 18's", "2 18's are excellent hands" ),		new RuleSplitSoft("99",Pr9,  card2_689,   "stand","dealer may bust with 2-6, lose with 8,9", "stand on 18, excellent hand with dealer 2-6,8,9" ),		new RuleSplitSoft("99",Pr9,  card71011,   "split","dealer may lose with 17, win with 10,A", "2 19's best against dealer with 7,10,A" ),		new RuleSplitSoft("1010",Pr10,cardAll,    "stand", "hard 20", "stand, excellent hand" ),		new RuleSplitSoft("AA",PrA,  cardAll,	  "split","two 21's", "2 21's are excellent hands" )	};	Rule current;	boolean currentWrong= false;	History myHistory;	TrainerView myView;	public Trainer( TrainerView aView, History aHistory ) {		myView= aView;		myHistory= aHistory;	}	public void next() {		int rn= r.randrange( rSet.length );		current= rSet[rn];		currentWrong= false;		myHistory.present(current);		myView.dealer( current.dealerCard().toString() );		myView.player( current.playerHand().toString() );		myView.message( "" );		myView.present();	}	public void play( String command ) {		if( current.rightPlay( command ) ) {			// show explanation, enable Next, disable hit/stand/split/double			myView.message( "Yes! " + current.explanation );			if( ! currentWrong ) { myHistory.right(); currentWrong= true; }			myView.right();		}		else {			// show hint			myView.message( "No, " + current.hint );			if( ! currentWrong ) {				myHistory.wrong();				System.out.println( current );			}			currentWrong= true;		}	}	public void test1() {		for( int i= 0; i != rSet.length; ++i ) {			System.out.println( rSet[i] );		}	}	public void test2() {		for( int i= 0; i != 100; ++i ) {			int rn= r.randrange( rSet.length );			System.out.println( "rule " + rn );			current= rSet[rn];			System.out.println( current.dealerCard() + " " + current.playerHand() );		}	}}/* Any panel must also implement the TrainerView so that the model can control the view */interface TrainerView {		public void dealer( String aCard );		public void player( String aHand );		public void message( String message );		public void present();		public void right();}/* The TrainerPanel is used by a trainer to present a problem */class TrainerPanel extends Panel implements TrainerView {	Button hit= new Button( "Hit" );	Button stand= new Button( "Stand" );	Button split= new Button( "Split" );	Button doubleDown= new Button( "Double" );	Button next= new Button( "Next" );	Button score= new Button( "Score" );	TextField hint= new TextField(40);	TextField dealer= new TextField(8);	TextField player= new TextField(8);	Trainer myTrainer;	Frame historyPopup;	TrainerPanel() {		setLayout( new GridLayout( 4, 1 ) );		Panel dBox= new Panel();		dBox.add( new Label( "Dealer:" ) );		dBox.add( dealer );		dealer.setEditable( false );		add( dBox );		Panel pBox= new Panel();		pBox.add( new Label( "Player:" ) );		pBox.add( player );		player.setEditable( false );		add( pBox );		add( hint );		hint.setEditable( false );		Panel buttons= new Panel();		buttons.add( next );		buttons.add( hit );		buttons.add( stand );		buttons.add( split );		buttons.add( doubleDown );		buttons.add( score );		add( buttons );	}	/* A trainerView is essentially an observer of a Trainer,	any interactions are sent directly to the trainer */	public void setTrainer( Trainer aTrainer ) {		/*next.addActionListener( new ButtonNext(aTrainer) );		hit.addActionListener( new ButtonPlay("hit",aTrainer) );		stand.addActionListener( new ButtonPlay("stand",aTrainer) );		split.addActionListener( new ButtonPlay("split",aTrainer) );		doubleDown.addActionListener( new ButtonPlay("double",aTrainer) );		score.addActionListener( new ButtonScore(aTrainer.myHistory) );		*/		myTrainer= aTrainer;	}	public void setHistory( Frame aFrame ) {		historyPopup= aFrame;	}	public void dealer( String aCard ) {		dealer.setText( aCard );	}	public void player( String aHand ) {		player.setText( aHand );	}	public void message( String message ) {		hint.setText( message );	}	public void present() {		next.disable(); //setEnabled( false );		hit.enable(); //setEnabled( true );		stand.enable(); //setEnabled( true );		split.enable(); //setEnabled( true );		doubleDown.enable(); //setEnabled( true );	}	public void right() {		next.enable(); //setEnabled( true );		hit.disable(); //setEnabled( false );		stand.disable(); //setEnabled( false );		split.disable(); //setEnabled( false );		doubleDown.disable(); //setEnabled( false );	}	public boolean action( Event e, Object arg ) {		if( e.target == next ) { myTrainer.next(); return true; }		if( e.target == score ) { historyPopup.show(); return true; } //setVisible(true);		if( e.target == hit ) { myTrainer.play( "hit" ); return true; }		if( e.target == stand ) { myTrainer.play( "stand" ); return true; }		if( e.target == split ) { myTrainer.play( "split" ); return true; }		if( e.target == doubleDown ) { myTrainer.play( "double" ); return true; }		System.out.println( e );		return false;	}}/* HistoryPanel displays the current history of missed hands */class HistoryPanel extends Panel implements Observer {	TextField score= new TextField(50);	TextArea  missed= new TextArea();	Button close= new Button( "Close" );	Frame myFrame;	public HistoryPanel( History aHistory ) {		setLayout( new BorderLayout() );		Panel ps= new Panel();		ps.add( new Label( "Summary: " ) );		ps.add( score );		score.setEditable( false );		add( "North", ps );		add( "Center", missed );		missed.setEditable( false );		Panel pc= new Panel();		pc.add( close );		add( "South", pc );		aHistory.addObserver( this );		resize(190,290);	}	public void score( String aScore ) {		score.setText( aScore );	}	public void missed( String aMissedReport ) {		missed.setText( aMissedReport );	}	public void update( Observable o, Object arg ) {		History source= (History)o;		score.setText( source.summary() );		missed.setText( source.missedReport() );	}	public void setFrame( Frame aFrame ) {		myFrame= aFrame;		myFrame.pack();	}	public boolean action( Event e, Object arg ) {		if( e.target == close ) { myFrame.hide();  return true; }	// setVisible(FALSE)		System.out.println( e );		return false;	}}class BaseFrame extends Frame {	/*public BaseFrame() {		super();	}*/	public boolean handleEvent(Event e) {		if (e.id == Event.WINDOW_DESTROY) {			dispose();			System.exit(0);			return true;		}		return super.handleEvent( e );	}}class PopupFrame extends Frame {	/*public PopupFrame() {		super();	}	*/	public boolean handleEvent(Event e) {		if (e.id == Event.WINDOW_DESTROY) {			hide(); //setVisible( false );			dispose();			return true;		}		//System.out.println( e );		return super.handleEvent( e );	}}/* Respond to the next button *//*class ButtonNext implements ActionListener {	Trainer myTrainer;	public ButtonNext( Trainer aTrainer ) {		myTrainer= aTrainer;	}	public void actionPerformed(ActionEvent e) {		//System.out.println(e);		myTrainer.next();	}}*//* Respond to one of the play buttons: hit, stand, split, double *//*class ButtonPlay implements ActionListener {	String myCommand;	Trainer myTrainer;	public ButtonPlay( String aCommand, Trainer aTrainer ) {		myTrainer= aTrainer;		myCommand= aCommand;	}	public void actionPerformed(ActionEvent e) {		//System.out.println(e);		myTrainer.play( myCommand );	}}*//* Respond to the score button *//*class ButtonScore implements ActionListener {	History myHistory;	Frame myFrame;	public ButtonScore( History aHistory ) {		myHistory= aHistory;	}	public void setHistoryFrame( Frame aFrame ) {		myFrame= aFrame;	}	public void actionPerformed(ActionEvent e) {		String buttonName= e.getActionCommand();		if( buttonName.equals( "Score" ) ) {			myFrame.setVisible(true);			//ask myHistory to update all observers			myHistory.notifyObservers();		}		else if( buttonName.equals( "Close" ) ) {			myFrame.setVisible(false);		}		else {			System.out.println(e);		}	}	public void closeFrame() {		myFrame.setVisible(false);	}}*//* Close the history window when the frame is closed *//*class HistoryWindowClose extends WindowAdapter {	Frame myWindow;	public HistoryWindowClose( Frame aWindow ) {		myWindow= aWindow;	}	public void windowClosing(WindowEvent e) {		myWindow.dispose();	}}*//* Close the trainer window when the frame is closed *//*class TrainerWindowClose extends WindowAdapter {	Frame myWindow;	public TrainerWindowClose( Frame aWindow ) {		myWindow= aWindow;	}	public void windowClosing(WindowEvent e) {		myWindow.dispose();		System.exit(0);	}}*//* Main applet (or stand-alone application) to present panel */public class BJTrainer extends Applet {	History myHistory;	Trainer myTrainer;	TrainerPanel myPanel;	Frame historyFrame;	HistoryPanel myHistoryPanel;	public static void test1() {		History h= new History();		Trainer t= new Trainer(null, h);		t.test1();		t.test2();	}	public static void main(String[] argv) {		// create a frame, add this applet to the frame		BJTrainer aTest= new BJTrainer();		Frame aFrame= new BaseFrame();		aFrame.setTitle("Blackjack Trainer");		aFrame.add(aTest);		aFrame.resize(200,300);		//aFrame.addWindowListener( new TrainerWindowClose( aFrame ) ); // REMOVE THIS		aTest.init();		aFrame.pack();		aFrame.show();	// setVisible(TRUE);	}	void makeHistoryFrame( HistoryPanel aHistoryPanel ) {		historyFrame= new PopupFrame();		historyFrame.setTitle( "Score" );		historyFrame.resize(200,300);		//historyFrame.addWindowListener( new HistoryWindowClose( historyFrame ) );		historyFrame.add( aHistoryPanel );		historyFrame.pack();		aHistoryPanel.setFrame( historyFrame );	}	public void init() {		myPanel= new TrainerPanel();		myHistory= new History();		myTrainer= new Trainer( myPanel, myHistory );		myPanel.setTrainer( myTrainer );		setLayout( new BorderLayout() );		add( "North", new Label("Blackjack Trainer") );		add( "Center", myPanel );		myHistoryPanel= new HistoryPanel( myHistory );		makeHistoryFrame( myHistoryPanel );		myPanel.setHistory( historyFrame );		myTrainer.next();	}}