1    	package acl2s.lib.bool;
2    	
3    	import java.awt.BorderLayout;
4    	import java.awt.Color;
5    	import java.awt.FlowLayout;
6    	import java.awt.Font;
7    	import java.awt.GridLayout;
8    	import java.awt.event.ActionEvent;
9    	import java.awt.event.ActionListener;
10   	import java.awt.event.MouseEvent;
11   	import java.awt.event.MouseListener;
12   	
13   	import javax.swing.ButtonGroup;
14   	import javax.swing.JButton;
15   	import javax.swing.JFrame;
16   	import javax.swing.JLabel;
17   	import javax.swing.JPanel;
18   	import javax.swing.JTextArea;
19   	import javax.swing.border.CompoundBorder;
20   	import javax.swing.border.EmptyBorder;
21   	import javax.swing.border.LineBorder;
22   	
23   	import org.peterd.util.Misc;
24   	
25   	import acl2s.lib.session.BootstrapParseContext;
26   	
27   	public class SwingPickEquivGame extends JPanel implements ActionListener, MouseListener {
28   		/**
29   		 * 
30   		 */
31   		private static final long serialVersionUID = 7294461562446425929L;
32   	
33   		JTextArea problemArea;
34   	
35   		JTextArea answerTextArea;
36   	
37   		JTextArea[] choiceTextAreas;
38   		JButton[]   choiceButtons;
39   		BooleanFormula[] choiceFormulas = new BooleanFormula[NCHOICES];
40   		
41   		JLabel recordLabel;
42   	
43   		boolean answerShown; // iff answerTextArea added to answerPanel
44   		BooleanFormula formula;
45   	
46   		long startingTime;
47   		Integer guess;
48   		int whichSame;
49   	
50   		int numCorrect;
51   		int numAttempted;
52   		long millisAccum;
53   	
54   		VarOccChoice varOccConfig;
55   		OpsChoice opsConfig;
56   	
57   		static final int NCHOICES = 3;
58   		static final int WIDTH = 60;
59   		
60   		public SwingPickEquivGame() {
61   			setLayout(new BorderLayout());
62   			
63   			JPanel main = new JPanel(new BorderLayout());
64   			
65   			problemArea = new JTextArea(3,WIDTH);
66   			problemArea.setFont(Font.decode("Monospaced BOLD 16"));
67   			problemArea.setEditable(false);
68   			problemArea.setLineWrap(false);
69   			problemArea.addMouseListener(this);
70   			problemArea.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
71   					                                  new EmptyBorder(2,2,2,2)));
72   			
73   			main.add(problemArea, BorderLayout.NORTH);
74   			
75   			JPanel ctp = new JPanel(new GridLayout(NCHOICES, 1));
76   			JPanel cbp = new JPanel(new GridLayout(NCHOICES, 1));
77   	
78   			choiceTextAreas = new JTextArea[NCHOICES];
79   			choiceButtons = new JButton[NCHOICES];
80   			for (int i = 0; i < NCHOICES; i++) {
81   				choiceTextAreas[i] = new JTextArea(3,WIDTH);
82   				choiceTextAreas[i].setFont(Font.decode("Monospaced BOLD 14"));
83   				choiceTextAreas[i].setEditable(false);
84   				choiceTextAreas[i].setLineWrap(false);
85   				choiceTextAreas[i].addMouseListener(this);
86   				choiceTextAreas[i].setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
87   						                                        new EmptyBorder(2,2,2,2)));
88   				ctp.add(choiceTextAreas[i]);
89   				choiceButtons[i] = new JButton("  " + (char)('A' + i) + "  ");
90   				choiceButtons[i].addActionListener(this);
91   				cbp.add(choiceButtons[i]);
92   			}
93   	
94   			main.add(ctp, BorderLayout.CENTER);
95   			main.add(cbp, BorderLayout.WEST);
96   			
97   			add(main, BorderLayout.CENTER);
98   	
99   			answerTextArea = new JTextArea(14, 16);
100  			answerTextArea.setFont(Font.decode("Monospaced BOLD 14"));
101  			answerTextArea.setEditable(false);
102  			answerTextArea.setLineWrap(false);
103  			answerTextArea.addMouseListener(this);
104  			answerTextArea.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
105  					                                     new EmptyBorder(4,4,4,4)));
106  			
107  			JPanel radioPanel1 = new JPanel(new GridLayout(5,1));
108  			ButtonGroup grp = new ButtonGroup();
109  			VarOccChoice voc;
110  			voc = new VarOccChoice(2,2,this); // default
111  			grp.add(voc);
112  			radioPanel1.add(voc);
113  			voc.setSelected(true);
114  			varOccConfig = voc;
115  			voc = new VarOccChoice(3,3,this);
116  			grp.add(voc);
117  			radioPanel1.add(voc);
118  			voc = new VarOccChoice(2,3,this);
119  			grp.add(voc);
120  			radioPanel1.add(voc);
121  			voc = new VarOccChoice(3,4,this);
122  			grp.add(voc);
123  			radioPanel1.add(voc);
124  			
125  			JPanel radioPanel2 = new JPanel(new GridLayout(5,1));
126  			grp = new ButtonGroup();
127  			OpsChoice oc = new OpsChoice(BooleanBinaryOperator.TWO_BASIC,this);
128  			grp.add(oc);
129  			radioPanel2.add(oc);
130  			oc = new OpsChoice(BooleanBinaryOperator.THREE_BASIC,this); // default;
131  			grp.add(oc);
132  			radioPanel2.add(oc);
133  			oc.setSelected(true);
134  			opsConfig = oc;
135  			oc = new OpsChoice(BooleanBinaryOperator.FOUR_BASIC,this); // default;
136  			grp.add(oc);
137  			radioPanel2.add(oc);
138  	
139  			JPanel bottomPanel = new JPanel(new GridLayout(1,3));
140  			bottomPanel.add(radioPanel1);
141  			bottomPanel.add(answerTextArea);
142  			bottomPanel.add(radioPanel2);
143  			main.add(bottomPanel, BorderLayout.SOUTH);
144  	
145  			JPanel rp = new JPanel();
146  			rp.setLayout(new FlowLayout());
147  			JButton resetButton = new JButton("Reset");
148  			resetButton.addActionListener(new ActionListener() {
149  				public void actionPerformed(ActionEvent e) {
150  					reset();
151  				}
152  			});
153  			rp.add(resetButton);
154  			recordLabel = new JLabel("Record: ----------------   Avg time: ---------");
155  			rp.add(recordLabel);
156  			
157  			add(rp,BorderLayout.SOUTH);
158  			
159  			reset();
160  		}
161  		
162  		public void reset() {
163  			numAttempted = 0;
164  			numCorrect = 0;
165  			millisAccum = 0;
166  			updateRecordInfo();
167  			answerShown = true;
168  			problemArea.setText("Click any white text area to continue,\nnow and after each problem.");
169  			answerTextArea.setText("");
170  			for (JTextArea choiceTextArea : choiceTextAreas) {
171  				choiceTextArea.setText("");
172  			}
173  		}
174  		
175  		public void updateRecordInfo() {
176  			float pct;
177  			float time;
178  			if (numAttempted == 0) {
179  				pct = 100f;
180  				time = 0f;
181  			} else {
182  				pct = 100f * (float)numCorrect / (float) numAttempted;
183  				time = (float) millisAccum / (float) numAttempted / 1000f;
184  			}
185  			recordLabel.setText("Record: " + numCorrect + " / " + numAttempted + "  (" +
186  					            pct + "%)    Avg time: " + time + "s");
187  		}
188  		
189  		public void step() {
190  			if (answerShown) {
191  				formula = RandomBooleanFormula.fromNumVarsOcc(varOccConfig.numVars,
192  						varOccConfig.numOcc, opsConfig.ops, true, false);
193  				problemArea.setText("" + formula.toString() + "\n\n" +
194  						formula.toACL2Expr().toString(BootstrapParseContext.instance));
195  				whichSame = Misc.random.nextInt(NCHOICES);
196  				for (int i = 0; i < NCHOICES; i++) {
197  					BooleanFormula cf;
198  					gen:
199  					for (;;) {
200  						cf = RandomBooleanFormula.fromNumVarsOcc(varOccConfig.numVars,
201  								varOccConfig.numOcc, opsConfig.ops, true, true);
202  						if (cf.equals(formula)) continue gen;
203  						if ((i == whichSame) != formula.iff(cf)) continue gen;
204  						for (int j = 0; j < i; j++) {
205  							if (cf.equals(choiceFormulas[j])) continue gen;
206  						}
207  						break;
208  					}
209  					choiceFormulas[i] = cf;
210  					choiceTextAreas[i].setText("" + cf.toString() + "\n\n" +
211  							cf.toACL2Expr().toString(BootstrapParseContext.instance));
212  				}
213  				guess = null;
214  				answerShown = false;
215  				answerTextArea.setText("");
216  				startingTime = System.currentTimeMillis();
217  			} else {
218  				StringBuilder aText = new StringBuilder();
219  				numAttempted++;
220  				long endingTime = System.currentTimeMillis();
221  				millisAccum += endingTime - startingTime;
222  				if (guess != null) {
223  					if (guess.intValue() == whichSame) {
224  						aText.append("Correct!\n");
225  						numCorrect++;
226  					} else {
227  						aText.append("INCORRECT!\n");
228  					}
229  					aText.append("(" + (char)('A' + whichSame) + " is equivalent)\n\n");
230  				}
231  				aText.append(formula.getTruthTable().toStringTF());
232  				
233  				answerTextArea.setText(aText.toString());
234  				updateRecordInfo();
235  				
236  				guess = null;
237  				answerShown = true;
238  			}
239  		}
240  		
241  		public void mouseClicked(MouseEvent e) {
242  			if (answerShown) {
243  				step();
244  			}
245  		}
246  		
247  		public void actionPerformed(ActionEvent e) {
248  			if (e.getSource() instanceof VarOccChoice) {
249  				varOccConfig = (VarOccChoice) e.getSource();
250  				reset();
251  			} else if (e.getSource() instanceof OpsChoice) {
252  				opsConfig = (OpsChoice) e.getSource();
253  				reset();
254  			} else if (answerShown) {
255  				step();
256  			} else {
257  				Object src = e.getSource();
258  				for (int i = 0; i < NCHOICES; i++) {
259  					if (src == choiceButtons[i]) {
Event do_not_call: "java.lang.Integer(int arg1)" is not recommended for performance reasons. Consider using Integer.valueOf(int) instead.
260  						guess = new Integer(i);
261  						step();
262  						break;
263  					}
264  				}
265  			}
266  		}
267  	
268  		
269  		// UNUSED:
270  		public void mouseEntered(MouseEvent e) {}
271  		public void mouseExited(MouseEvent e) {}
272  		public void mousePressed(MouseEvent e) {}
273  		public void mouseReleased(MouseEvent e) {}
274  		
275  		
276  		
277  		
278  		public static void main(String[] args) {
279  			JFrame f = new JFrame("Boolean Logic Game");
280  			f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
281  			f.getContentPane().add(new SwingPickEquivGame());
282  			f.pack();
283  			f.setVisible(true);
284  		}
285  	
286  		public static String SAME_STRING = "Equivalent";
287  		public static String DIFF_STRING = "Different";
288  	}