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.JLayeredPane;
18   	import javax.swing.JPanel;
19   	import javax.swing.JTextArea;
20   	import javax.swing.JTextField;
21   	import javax.swing.border.CompoundBorder;
22   	import javax.swing.border.EmptyBorder;
23   	import javax.swing.border.LineBorder;
24   	
25   	import org.peterd.util.Misc;
26   	
27   	import acl2s.lib.session.BootstrapParseContext;
28   	
29   	public class SwingEquivGame extends JPanel implements ActionListener, MouseListener {
30   		/**
31   		 * 
32   		 */
33   		private static final long serialVersionUID = -3360000868109989528L;
34   		JTextField problemField1a;
35   		JTextField problemField1b;
36   		JTextField problemField2a;
37   		JTextField problemField2b;
38   		
39   		JLayeredPane answerPane1;
40   		JLayeredPane answerPane2;
41   		JTextArea answerTextArea1;
42   		JTextArea answerTextArea2;
43   		JButton sameButton;
44   		JButton diffButton;
45   		
46   		JLabel recordLabel;
47   	
48   		boolean answerShown; // iff answerTextArea added to answerPanel
49   		BooleanFormula formula1;
50   		BooleanFormula formula2;
51   	
52   		long startingTime;
53   		Boolean guess;
54   	
55   		int numCorrect;
56   		int numAttempted;
57   		long millisAccum;
58   	
59   		VarOccChoice varOccConfig;
60   		OpsChoice opsConfig;
61   		
62   		static final int WIDTH = 40;
63   		
64   		public SwingEquivGame() {
65   			setLayout(new BorderLayout());
66   			
67   			JPanel main = new JPanel(new GridLayout(1, 2));
68   			JPanel left = new JPanel(new BorderLayout());
69   			JPanel right = new JPanel(new BorderLayout());
70   	
71   			JPanel problemField1 = new JPanel(new GridLayout(2,1));
72   			
73   			problemField1a = new JTextField(WIDTH);
74   			problemField1a.setFont(Font.decode("Monospaced BOLD 16"));
75   			problemField1a.setEditable(false);
76   			problemField1a.addMouseListener(this);
77   			problemField1a.setBackground(Color.WHITE);
78   			problemField1a.setHorizontalAlignment(JTextField.RIGHT);
79   			problemField1a.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
80   					                                    new EmptyBorder(3,6,3,6)));
81   			problemField1b = new JTextField(WIDTH);
82   			problemField1b.setFont(Font.decode("Monospaced BOLD 16"));
83   			problemField1b.setEditable(false);
84   			problemField1b.addMouseListener(this);
85   			problemField1b.setBackground(Color.WHITE);
86   			problemField1b.setHorizontalAlignment(JTextField.RIGHT);
87   			problemField1b.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
88   					                                    new EmptyBorder(3,6,3,6)));
89   	
90   			problemField1.add(problemField1a);
91   			problemField1.add(problemField1b);
92   			left.add(problemField1, BorderLayout.NORTH);
93   			
94   			JPanel problemField2 = new JPanel(new GridLayout(2,1));
95   			
96   			problemField2a = new JTextField(WIDTH);
97   			problemField2a.setFont(Font.decode("Monospaced BOLD 16"));
98   			problemField2a.setEditable(false);
99   			problemField2a.addMouseListener(this);
100  			problemField2a.setBackground(Color.WHITE);
101  			problemField2a.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
102  					                                    new EmptyBorder(3,6,3,6)));
103  			problemField2b = new JTextField(WIDTH);
104  			problemField2b.setFont(Font.decode("Monospaced BOLD 16"));
105  			problemField2b.setEditable(false);
106  			problemField2b.addMouseListener(this);
107  			problemField2b.setBackground(Color.WHITE);
108  			problemField2b.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
109  					                                    new EmptyBorder(3,6,3,6)));
110  			problemField2.add(problemField2a);
111  			problemField2.add(problemField2b);
112  			right.add(problemField2, BorderLayout.NORTH);
113  					
114  			
115  			answerPane1 = new JLayeredPane();
116  			answerPane2 = new JLayeredPane();
117  			
118  			answerTextArea1 = new JTextArea(13, 16);
119  			answerTextArea1.setFont(Font.decode("Monospaced BOLD 14"));
120  			answerTextArea1.setEditable(false);
121  			answerTextArea1.setLineWrap(false);
122  			answerTextArea1.addMouseListener(this);
123  			answerTextArea1.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
124  					                                     new EmptyBorder(4,4,4,4)));
125  			
126  			sameButton = new JButton(SAME_STRING);
127  			sameButton.addActionListener(this);
128  	
129  			answerTextArea2 = new JTextArea(13, 16);
130  			answerTextArea2.setFont(Font.decode("Monospaced BOLD 14"));
131  			answerTextArea2.setEditable(false);
132  			answerTextArea2.setLineWrap(false);
133  			answerTextArea2.addMouseListener(this);
134  			answerTextArea2.setBorder(new CompoundBorder(new LineBorder(Color.BLACK),
135  					                                     new EmptyBorder(4,4,4,4)));
136  	
137  			diffButton = new JButton(DIFF_STRING);
138  			diffButton.addActionListener(this);
139  	
140  			answerPane1.setPreferredSize(Misc.maxDimensions(answerTextArea1.getPreferredSize(),
141  					                                        sameButton.getPreferredSize()));
142  			answerPane2.setPreferredSize(Misc.maxDimensions(answerTextArea2.getPreferredSize(),
143  					                                        diffButton.getPreferredSize()));
144  			
145  			answerPane1.add(sameButton, new Integer(0));
146  			sameButton.setSize(answerPane1.getPreferredSize());
147  			answerPane1.add(answerTextArea1, new Integer(1));
148  			answerTextArea1.setSize(answerPane1.getPreferredSize());
149  			answerPane2.add(diffButton, new Integer(0));
150  			diffButton.setSize(answerPane2.getPreferredSize());
Event do_not_call: "java.lang.Integer(int arg1)" is not recommended for performance reasons. Consider using Integer.valueOf(int) instead.
151  			answerPane2.add(answerTextArea2, new Integer(1));
152  			answerTextArea2.setSize(answerPane2.getPreferredSize());
153  	
154  			left.add(answerPane1, BorderLayout.EAST);
155  			right.add(answerPane2, BorderLayout.WEST);
156  			
157  			
158  			JPanel radioPanel1 = new JPanel(new GridLayout(5,1));
159  			ButtonGroup grp = new ButtonGroup();
160  			VarOccChoice voc;
161  			voc = new VarOccChoice(2,2,this); // default
162  			grp.add(voc);
163  			radioPanel1.add(voc);
164  			voc.setSelected(true);
165  			varOccConfig = voc;
166  			voc = new VarOccChoice(3,3,this);
167  			grp.add(voc);
168  			radioPanel1.add(voc);
169  			voc = new VarOccChoice(2,3,this);
170  			grp.add(voc);
171  			radioPanel1.add(voc);
172  			voc = new VarOccChoice(3,4,this);
173  			grp.add(voc);
174  			radioPanel1.add(voc);
175  			
176  			JPanel radioPanel2 = new JPanel(new GridLayout(5,1));
177  			grp = new ButtonGroup();
178  			OpsChoice oc = new OpsChoice(BooleanBinaryOperator.TWO_BASIC,this);
179  			grp.add(oc);
180  			radioPanel2.add(oc);
181  			oc = new OpsChoice(BooleanBinaryOperator.THREE_BASIC,this); // default;
182  			grp.add(oc);
183  			radioPanel2.add(oc);
184  			oc.setSelected(true);
185  			opsConfig = oc;
186  			oc = new OpsChoice(BooleanBinaryOperator.FOUR_BASIC,this); // default;
187  			grp.add(oc);
188  			radioPanel2.add(oc);
189  	
190  			left.add(radioPanel1, BorderLayout.WEST);
191  			right.add(radioPanel2, BorderLayout.EAST);
192  	
193  			left.add(new JPanel(), BorderLayout.CENTER);
194  			right.add(new JPanel(), BorderLayout.CENTER);
195  			
196  			main.add(left);
197  			main.add(right);
198  			add(main, BorderLayout.CENTER);
199  	
200  			JPanel rp = new JPanel();
201  			rp.setLayout(new FlowLayout());
202  			JButton resetButton = new JButton("Reset");
203  			resetButton.addActionListener(new ActionListener() {
204  				public void actionPerformed(ActionEvent e) {
205  					reset();
206  				}
207  			});
208  			rp.add(resetButton);
209  			recordLabel = new JLabel("Record: ----------------   Avg time: ---------");
210  			rp.add(recordLabel);
211  			
212  			add(rp,BorderLayout.SOUTH);
213  			
214  			reset();
215  		}
216  		
217  		public void reset() {
218  			numAttempted = 0;
219  			numCorrect = 0;
220  			millisAccum = 0;
221  			updateRecordInfo();
222  			answerShown = true;
223  			answerPane1.setLayer(answerTextArea1, 1);
224  			answerPane1.setLayer(sameButton, 0);
225  			answerPane2.setLayer(answerTextArea2, 1);
226  			answerPane2.setLayer(diffButton, 0);
227  			problemField1a.setText("Click any white text area to continue,");
228  			problemField1b.setText("");
229  			problemField2a.setText("now and after each problem.");
230  			problemField2b.setText("");
231  			answerTextArea1.setText("");
232  			answerTextArea2.setText("");
233  		}
234  		
235  		public void updateRecordInfo() {
236  			float pct;
237  			float time;
238  			if (numAttempted == 0) {
239  				pct = 100f;
240  				time = 0f;
241  			} else {
242  				pct = 100f * (float)numCorrect / (float) numAttempted;
243  				time = (float) millisAccum / (float) numAttempted / 1000f;
244  			}
245  			recordLabel.setText("Record: " + numCorrect + " / " + numAttempted + "  (" +
246  					            pct + "%)    Avg time: " + time + "s");
247  		}
248  		
249  		public void step() {
250  			if (answerShown) {
251  				formula1 = RandomBooleanFormula.fromNumVarsOcc(varOccConfig.numVars, varOccConfig.numOcc, opsConfig.ops, true, false);
252  				boolean same = Misc.random.nextBoolean();
253  				do {
254  					formula2 = RandomBooleanFormula.fromNumVarsOcc(varOccConfig.numVars, varOccConfig.numOcc, opsConfig.ops, true, true);
255  				} while (formula1.equals(formula2) || same != formula1.iff(formula2));
256  	
257  				problemField1a.setText(formula1.toString());
258  				problemField1b.setText(formula1.toACL2Expr().toString(BootstrapParseContext.instance));
259  				problemField2a.setText(formula2.toString());
260  				problemField2b.setText(formula2.toACL2Expr().toString(BootstrapParseContext.instance));
261  	
262  				guess = null;
263  				answerShown = false;
264  				answerPane1.setLayer(answerTextArea1, 1);
265  				answerPane1.setLayer(sameButton, 2);
266  				answerPane2.setLayer(answerTextArea2, 1);
267  				answerPane2.setLayer(diffButton, 2);
268  				startingTime = System.currentTimeMillis();
269  			} else {
270  				StringBuilder aText1 = new StringBuilder();
271  				StringBuilder aText2 = new StringBuilder();
272  				numAttempted++;
273  				long endingTime = System.currentTimeMillis();
274  				millisAccum += endingTime - startingTime;
275  				if (guess != null) {
276  					boolean ans = formula1.iff(formula2);
277  					if (guess.booleanValue() == ans) {
278  						aText1.append("Correct!\n\n");
279  						numCorrect++;
280  					} else {
281  						aText1.append("INCORRECT!\n\n");
282  					}
283  					aText2.append(ans ? "(Equivalent)\n\n" : "(Different)\n\n");
284  				}
285  				aText1.append(formula1.getTruthTable().toStringTF());
286  				aText2.append(formula2.getTruthTable().toStringTF());
287  				
288  				answerTextArea1.setText(aText1.toString());
289  				answerTextArea2.setText(aText2.toString());
290  				updateRecordInfo();
291  				
292  				guess = null;
293  				answerShown = true;
294  				answerPane1.setLayer(answerTextArea1, 1);
295  				answerPane1.setLayer(sameButton, 0);
296  				answerPane2.setLayer(answerTextArea2, 1);
297  				answerPane2.setLayer(diffButton, 0);
298  			}
299  		}
300  		
301  		public void mouseClicked(MouseEvent e) {
302  			if (answerShown) {
303  				step();
304  			}
305  		}
306  		
307  		public void actionPerformed(ActionEvent e) {
308  			if (e.getSource() instanceof VarOccChoice) {
309  				varOccConfig = (VarOccChoice) e.getSource();
310  				reset();
311  			} else if (e.getSource() instanceof OpsChoice) {
312  				opsConfig = (OpsChoice) e.getSource();
313  				reset();
314  			} else if (answerShown) {
315  				step();
316  			} else {
317  				String v = e.getActionCommand();
318  				if (v.equals(SAME_STRING)) {
319  					guess = Boolean.TRUE;
320  					step();
321  				} else if (v.equals(DIFF_STRING)) {
322  					guess = Boolean.FALSE;
323  					step();
324  				} else {
325  					// ignore??
326  				}
327  			}
328  		}
329  	
330  		
331  		// UNUSED:
332  		public void mouseEntered(MouseEvent e) {}
333  		public void mouseExited(MouseEvent e) {}
334  		public void mousePressed(MouseEvent e) {}
335  		public void mouseReleased(MouseEvent e) {}
336  		
337  		
338  		
339  		
340  		public static void main(String[] args) {
341  			JFrame f = new JFrame("Boolean Logic Game");
342  			f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343  			f.getContentPane().add(new SwingEquivGame());
344  			f.pack();
345  			f.setVisible(true);
346  		}
347  	
348  		public static String SAME_STRING = "Equivalent";
349  		public static String DIFF_STRING = "Different";
350  	}