· 8 years ago · Jun 11, 2018, 09:38 AM
1//GraphicsPanel
2//Written by: Isaac Hu
3//Date: May 26, 2018
4//Description: Implements the panel to display user interface
5
6//Importing
7import java.awt.Color;
8import java.awt.Dimension;
9import java.awt.Font;
10import java.awt.FontMetrics;
11import java.awt.Graphics;
12import java.awt.Graphics2D;
13import java.awt.event.KeyEvent;
14import java.awt.event.KeyListener;
15import java.awt.event.MouseEvent;
16import java.awt.event.MouseListener;
17import java.math.BigDecimal;
18import java.math.MathContext;
19import java.text.DecimalFormat;
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.HashMap;
23import java.util.List;
24
25import javax.swing.JPanel;
26import javax.swing.Timer;
27
28//Main class area
29public class GraphicsPanel extends JPanel implements KeyListener, MouseListener{
30
31 //Instance variables
32
33 //UID
34 private static final long serialVersionUID = -4061074837434605510L;
35
36 //Timer
37 private Timer t;
38
39 //User's current tool
40 private String condition;
41
42 //Background molecules
43 private ArrayList<Character> background;
44
45 //List of jokes
46 HashMap<String, String> jokes = new HashMap<>();
47
48 //How long to display the joke
49 private int jokeTimer;
50
51 //Current joke index
52 private int jokeIndex;
53
54 //First reactant
55 private String reac1;
56
57 //Second reactant
58 private String reac2;
59
60 //Acid/base reaction screen selected area
61 private int abs;
62
63 //Acid location
64 private int acidLoc;
65
66 //Substance labels
67 private String[] labels;
68
69 //pH calculator selection
70 private int phs;
71
72 //Moles of acid
73 private String acidMoles;
74
75 //Moles of base
76 private String baseMoles;
77
78 //Whether or not the acid is weak
79 private boolean weakAcid;
80
81 //Whether or not the base is weak
82 private boolean weakBase;
83
84 //pKa value of acid
85 private String pKa;
86
87 //pKb value of base
88 private String pKb;
89
90 //Volume of the solution
91 private String pHVolume;
92
93 //Periodic table
94 private Character pHTable;
95
96 //Electron calculator focus
97 private int es;
98
99 //Electron number
100 private String eCount;
101
102 //Electron symbol
103 private String symbol;
104
105 //Electron charge
106 private int charge;
107
108 //List of elements
109 private String[] elements;
110
111 //Number of items
112 private int items;
113
114 //Number of lone pairs
115 private int lones;
116
117 //PVnRT selection
118 private int ps;
119
120 //Pressure
121 private String pres;
122
123 //Volume
124 private String vol;
125
126 //Moles
127 private String mol;
128
129 //Temperature
130 private String temp;
131
132 //Pressure units
133 private int presUn;
134
135 //Volume units
136 private int volUn;
137
138 //Temperature units
139 private int tempUn;
140
141 //Temperature's sign
142 private boolean negTemp;
143
144 //Last solved variable
145 private int solved;
146
147 public GraphicsPanel() {
148
149 //Setting background size
150 setPreferredSize(new Dimension(1280,800));
151
152 //Disable tab moving between items on the JFrame
153 this.setFocusTraversalKeysEnabled(false);
154
155 //Make the JPanel focusable
156 this.setFocusable(true);
157
158 //Add mouse and key listeners
159 this.addKeyListener(this);
160 this.addMouseListener(this);
161
162 //Creating characters
163 background = new ArrayList<>();
164 for(int i = 0; i < 3; i++) {
165 background.add(new Character(i, (int)(1450 * Math.random()) - 50, 100 + (int)(250 * i)));
166 }
167
168
169 //Initialize ct1 items
170 reac1 = "";
171 reac2 = "";
172 abs = 0;
173 acidLoc = 0;
174 labels = new String[4];
175 for(int i = 0; i < 4; i++) labels[i] = "";
176
177 //Initialize ct2 items
178 phs = 0;
179 acidMoles = "0";
180 baseMoles = "0";
181 weakAcid = false;
182 weakBase = false;
183 pKa = "0";
184 pKb = "0";
185 pHVolume = "0";
186 pHTable = new Character(3, 960, 400);
187
188 //Initialize ct3 items
189 es = 0;
190 eCount = "0";
191 symbol = "";
192 charge = 0;
193 elements = new String[] {"H", "He",
194 "Li", "Be", "B", "C", "N", "O", "F", "Ne",
195 "Na", "Mg", "Al", "Si", "P", "S", "Cl", "Ar",
196 "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co","Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr",
197 "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe",
198 "Cs", "Ba","La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "<Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn",
199 "Fr", "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", "Ds", "Rg", "Cn", "Nh", "Fl", "Mc", "Ly", "Ts", "Og"
200 };
201
202 //Initialize ct4 items
203 items = 2;
204 lones = 0;
205
206 //Initialize ct5 items
207 ps = 0;
208 pres = "0";
209 vol = "0";
210 mol = "0";
211 temp = "0";
212 presUn = 0;
213 volUn = 0;
214 tempUn = 0;
215 negTemp = false;
216 solved = 0;
217
218
219
220 //State of the game
221 condition = "start";
222
223 //Initialize and start timer
224 t = new Timer(50, new ClockListener(this));
225 t.start();
226
227 //Add all the jokes
228 jokes.put("Did you know that you can cool yourself to -273.15C", "and still be 0K?");
229 jokes.put("Why do chemists like nitrates so much?", "They are cheaper than day rates");
230 jokes.put("What did cesium and iodine watch on their date?", "CSI");
231 jokes.put("If the silver surfer and iron man team up", "They would be alloys");
232 jokes.put("Helium walks into a bar, but the bartender says 'We don't serve noble gasses here'", "Helium doesn't react");
233 jokes.put("Silver tells gold", "AU, get outta here!");
234 jokes.put("Online money has recently been discovered to be an unidentified super heavy element", "The proposed name is un-obtainium");
235 jokes.put("Optimists see a glass half full. Pessimists half empty.", "Chemists completely full. Half in liquid phase, half in vapor phase.");
236 jokes.put("A neutron asks the bartender for the price of a beer.", "He replies 'For you, no charge'.");
237 jokes.put("What do you call a tooth in a glass of water?", "One molar solution");
238 jokes.put("Why is a hamburger's energy yield lower than steak's?", "It is in the ground state");
239 jokes.put("A chemist asks another 'Whats new?'", "His response is C over lambda");
240 jokes.put("If you're not part of the solution", "you're part of the precipitate");
241 jokes.put("What is the name of 007's Eskimo cousin?", "Polar bond");
242 jokes.put("Why did the bear dissolve in water?", "It was polar");
243 jokes.put("How do you spot a chemist in the bathroom?", "They wash their hands before they use the toilet");
244 jokes.put("Would a mole of moles collapse under its weight...", "or become a black mole?");
245 jokes.put("Chemistry cat doesn't have 9 lives...", "it has 18 half-lives");
246 jokes.put("How do you repel a cation?", "With a dogion");
247 jokes.put("What did the thermometer say to the graduated cylinder?", "You may have graduated, but I have many degrees");
248 jokes.put("How many moles are in a guacamole?", "6.022X10^23");
249 jokes.put("When cops pull you over, do what Heisenburg does", "Say you knew where you were, but not how fast you were going.");
250 jokes.put("I hate learning about electrons...", "they Bohr me");
251
252 //Start without a joke
253 jokeTimer = 0;
254
255 //Choose a random joke to start with
256 jokeIndex = (int)(jokes.size()*Math.random());
257
258
259 }
260
261 // method: paintComponent
262 // description: This method will paint the items onto the graphics panel. This method is called when the panel is
263 // first rendered. It can also be called by this.repaint()
264 // parameters: Graphics g - This object is used to draw your images onto the graphics panel.
265 public void paintComponent(Graphics g) {
266 //New graphics
267 Graphics2D g2 = (Graphics2D) g;
268
269 //Gradient background
270 for(int i = 0; i < 800; i++) {
271 g2.setColor(new Color(135 - (int)(65 * ((double)i/800)),206 - (int)(76 * ((double)i/800)),250 - (int)(70 * ((double)i/800))));
272 g2.fillRect(0, i, 1280, 1);
273 }
274
275 //Draw background characters
276 for(Character c : background) c.draw(g2, this);
277
278 //Create fontmetrics variable
279 FontMetrics metrics;
280
281 //Draw different items depending on the state of the system
282 switch(condition) {
283
284 //Starting screen
285 case "start":
286
287 //Set color/font
288 g2.setColor(new Color(34,139,34));
289 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 100));
290 metrics = g2.getFontMetrics();
291
292 //Print program name
293 g2.drawString("CHEMTOOLS", 640 - (int)(0.5 * metrics.stringWidth("CHEMTOOLS")), 300);
294
295 //Change font
296 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
297 metrics = g2.getFontMetrics();
298
299 //Instructions
300 g2.drawString("Click a button on the side panel to begin", 640 - (int)(0.5 * metrics.stringWidth("Click a button on the side panel to begin")), 500);
301
302 //Change color/font
303 g2.setColor(Color.BLACK);
304 g2.setFont(new Font("Arial Bold", Font.BOLD, 20));
305 metrics = g2.getFontMetrics();
306
307 //Print program version
308 g2.drawString("Alpha Release", 1275 - metrics.stringWidth("Alpha Release"), 770);
309 break;
310
311 //Acid/base reaction calculator
312 case "ct1":
313
314 //Set color
315 g2.setColor(new Color(50, 205, 50));
316
317 //Find focus to make a green highlight
318 switch(abs) {
319
320 //First reactant
321 case 1:
322 g2.fillRect(0, 200, 320, 200);
323 for(Character c : background) c.draw(g2, this);
324 break;
325
326 //Second reactant
327 case 2:
328 g2.fillRect(320, 200, 320, 200);
329 for(Character c : background) c.draw(g2, this);
330 }
331
332 //Draw grey boxes
333 g2.setColor(Color.GRAY);
334 g2.fillRect(40, 300, 240, 50);
335 g2.fillRect(360, 300, 240, 50);
336 g2.fillRect(680, 300, 240, 50);
337 g2.fillRect(1000, 300, 240, 50);
338
339 //Switch color/font
340 g2.setColor(Color.BLACK);
341 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
342 metrics = g2.getFontMetrics();
343
344 //Instructions
345 g2.drawString("Enter the two reactants to find the products (Capitalization matters).", 640 - (int)(0.5 * metrics.stringWidth("Enter the two reactants to find the products (Capitalization matters).")), 600);
346
347 //Change color/font
348 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 30));
349 metrics = g2.getFontMetrics();
350
351 //Label acids/bases if it is known
352 for(int i = 0; i < 4; i++) {
353 if(labels[i].indexOf("Acid") > -1) g2.setColor(Color.GREEN);
354 else if(labels[i].indexOf("Base") > -1) g2.setColor(Color.PINK);
355 else g2.setColor(Color.BLACK);
356 g2.drawString(labels[i], 160 + (320 * i) - (int)(0.5 * metrics.stringWidth(labels[i])), 400);
357 }
358
359 //Color labels based on their status
360 if(acidLoc == 1) g2.setColor(Color.GREEN);
361 else if(acidLoc == 2) g2.setColor(Color.PINK);
362
363 //Draw first reactant if it exists
364 if(reac1.length() > 0) g2.drawString(reac1, 160 - (int)(0.5 * metrics.stringWidth(reac1)), 335);
365
366 //Color labels based on their status
367 if(acidLoc == 2) g2.setColor(Color.GREEN);
368 else if(acidLoc == 1) g2.setColor(Color.PINK);
369
370 //Draw second reactant if it exists
371 if(reac2.length() > 0) g2.drawString(reac2, 480 - (int)(0.5 * metrics.stringWidth(reac2)), 335);
372
373 //Products variable
374 String[] products;
375
376 //Set font
377 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
378 metrics = g2.getFontMetrics();
379
380 //See if known
381 switch(acidLoc) {
382
383 //Invalid input
384 case 3:
385 g2.drawString("INVALID", 800 - (int)(0.5 * metrics.stringWidth("INVALID")), 335);
386 g2.drawString("INVALID", 1120 - (int)(0.5 * metrics.stringWidth("INVALID")), 335);
387 break;
388
389 //Acid is in position 1
390 case 1:
391 products = findProducts(reac1, reac2);
392 g2.setColor(Color.PINK);
393 if(products[1].length() > 0) g2.drawString(products[1], 800 - (int)(0.5 * metrics.stringWidth(products[1])), 335);
394 g2.setColor(Color.GREEN);
395 g2.drawString(products[0], 1120 - (int)(0.5 * metrics.stringWidth(products[0])), 335);
396 break;
397
398 //Acid is in position 2
399 case 2:
400 products = findProducts(reac2, reac1);
401 g2.setColor(Color.GREEN);
402 g2.drawString(products[0], 800 - (int)(0.5 * metrics.stringWidth(products[0])), 335);
403 g2.setColor(Color.PINK);
404 if(products[1].length() > 0) g2.drawString(products[1], 1120 - (int)(0.5 * metrics.stringWidth(products[1])), 335);
405 break;
406 }
407
408 //Change color
409 g2.setColor(Color.BLACK);
410
411 //Label all items
412 g2.drawString("Reactant 1", 160 - (int)(0.5 * metrics.stringWidth("Reactant 1")), 250);
413 g2.drawString("Reactant 2", 480 - (int)(0.5 * metrics.stringWidth("Reactant 2")), 250);
414 g2.drawString("Product 1", 800 - (int)(0.5 * metrics.stringWidth("Product 1")), 250);
415 g2.drawString("Product 2", 1120 - (int)(0.5 * metrics.stringWidth("Product 2")), 250);
416 break;
417
418 //pH Calculator
419 case "ct2":
420
421 //Set color
422 g2.setColor(new Color(50, 205, 50));
423
424 //Highlight selected area
425 int x = 0;
426 int y = 0;
427 if(phs < 4) x = 0;
428 else if(phs != 7) x = 320;
429 else x = 800;
430 if(phs % 3 == 1 && phs != 7) y = 0;
431 else if(phs % 3 == 2) y = 150;
432 else y = 300;
433 if(phs >= 1 && phs <= 7) g2.fillRect(x, y + 300, 320, 150);
434
435 //Draw characters in background again over highlight
436 for(Character c : background) c.draw(g2, this);
437
438 //Set color and font
439 g2.setColor(Color.BLACK);
440 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 20));
441 metrics = g2.getFontMetrics();
442
443 //Instructions
444 g2.drawString("Note the calculator rounds pH to the hundredths, and cannot calculate pH of a solution with a weak acid and weak base.", 640 - (int)(0.5 * metrics.stringWidth("Note the calculator rounds pH to the hundredths, and cannot calculate pH of a solution with a weak acid and weak base.")), 775);
445
446 //Set font and color
447 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
448 metrics = g2.getFontMetrics();
449 g2.setColor(Color.GRAY);
450
451 //Draw grey boxes and switch red/green boxes
452 g2.fillRect(40, 350, 240, 50);
453 g2.fillRect(360, 350, 240, 50);
454 g2.setColor(weakAcid ? Color.GREEN : Color.RED);
455 g2.fillRect(230, 500, 50, 50);
456 g2.setColor(weakBase ? Color.GREEN : Color.RED);
457 g2.fillRect(550, 500, 50, 50);
458 g2.setColor(Color.GRAY);
459 g2.fillRect(40, 650, 240, 50);
460 g2.fillRect(360, 650, 240, 50);
461 g2.fillRect(840, 650, 240, 50);
462
463 //Change color/font
464 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
465 metrics = g2.getFontMetrics();
466 g2.setColor(Color.BLACK);
467
468 //Label every input/output box on screen
469 g2.drawString("pH", 960 - (int)(0.5 * metrics.stringWidth("pH")), 190);
470 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
471 metrics = g2.getFontMetrics();
472 g2.drawString("Volume {Liters}", 960 - (int)(0.5 * metrics.stringWidth("Volume {Liters}")), 640);
473 if(pHVolume != null) g2.drawString(pHVolume, 960 - (int)(0.5 * metrics.stringWidth(pHVolume)), 690);
474 g2.setColor(new Color(0, 100, 0));
475 g2.drawString("Acid", 160 - (int)(0.5 * metrics.stringWidth("Acid")), 190);
476 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
477 metrics = g2.getFontMetrics();
478 g2.drawString("Weak?", 40, 540);
479 g2.drawString("Moles {mol}", 160 - (int)(0.5 * metrics.stringWidth("Moles {mol}")), 340);
480 g2.drawString("pKa", 160 - (int)(0.5 * metrics.stringWidth("pKa")), 640);
481 g2.setColor(Color.BLACK);
482 if(acidMoles != null) g2.drawString(acidMoles, 160 - (int)(0.5 * metrics.stringWidth(acidMoles)), 390);
483 if(pKa != null) g2.drawString(pKa, 160 - (int)(0.5 * metrics.stringWidth(pKa)), 690);
484 g2.setColor(new Color(199, 21, 133));
485 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
486 metrics = g2.getFontMetrics();
487 g2.drawString("Base", 480 - (int)(0.5 * metrics.stringWidth("Base")), 190);
488 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
489 metrics = g2.getFontMetrics();
490 g2.drawString("Weak?", 360, 540);
491 g2.drawString("Moles {mol}", 480 - (int)(0.5 * metrics.stringWidth("Moles {mol}")), 340);
492 g2.drawString("pKb", 480 - (int)(0.5 * metrics.stringWidth("pKb")), 640);
493 g2.setColor(Color.BLACK);
494 if(baseMoles != null) g2.drawString(baseMoles, 480 - (int)(0.5 * metrics.stringWidth(baseMoles)), 390);
495 if(pKb != null) g2.drawString(pKb, 480 - (int)(0.5 * metrics.stringWidth(pKb)), 690);
496
497 //Draw pH Table
498 pHTable.draw(g2, this);
499
500 //If there is enough information, calculate and display the pH Value
501 if(fullInput()) {
502 if(findpH(acidMoles, weakAcid,pKa, baseMoles, weakBase, pKb) == null || Double.parseDouble(findpH(acidMoles, weakAcid, pKa, baseMoles, weakBase, pKb)) > 14 || Double.parseDouble(findpH(acidMoles, weakAcid, pKa, baseMoles, weakBase, pKb)) < 0) {
503 g2.drawLine((int)(763 + (394 * (7.0/14))), 368, (int)(763 + (394 * (0.5))), 550);
504 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 20));
505 metrics = g2.getFontMetrics();
506 g2.drawString("INVALID INPUT", ((int)(763 + (394 * (7.0/14)))) - (int)(0.5 * metrics.stringWidth("INVALID INPUT")), 575);
507 }
508 else {
509 DecimalFormat df = new DecimalFormat("00.00");
510 df.setMaximumFractionDigits(2);
511 double pH = Double.parseDouble(findpH(acidMoles, weakAcid, pKa, baseMoles, weakBase, pKb));
512 g2.drawLine((int)(763 + (394 * (pH/14))), 368, (int)(763 + (394 * (pH/14))), 550);
513 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 20));
514 metrics = g2.getFontMetrics();
515 g2.drawString(df.format(pH), (int)(763 + (394 * (pH/14))) - (int)(0.5 * metrics.stringWidth(df.format(pH))), 575);
516 }
517 }
518 break;
519
520 //Electron Configuration Calculator
521 case "ct3":
522
523 //Set color
524 g2.setColor(new Color(50, 205, 50));
525
526 //Highlight selected area
527 if(es == 1) g2.fillRect(150, 225, 340, 200);
528 else if(es == 2) g2.fillRect(790, 225, 340, 200);
529
530 //Fill boxes
531 g2.setColor(Color.GRAY);
532 g2.fillRect(200, 325, 240, 50);
533 g2.fillRect(840, 325, 240, 50);
534 g2.fillRect(270, 515, 100, 50);
535 g2.fillRect(50, 600, 1180, 150);
536
537 //Plus and minus charge buttons
538 g2.setColor(charge == -9 ? new Color(250, 128, 114) : Color.RED);
539 g2.fillRect(200, 515, 50, 50);
540 g2.setColor(charge == 9 ? new Color(84, 110, 0) : Color.GREEN);
541 g2.fillRect(390, 515, 50, 50);
542
543 //Set color/font
544 g2.setColor(Color.BLACK);
545 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
546 metrics = g2.getFontMetrics();
547
548 //Draw title
549 g2.drawString("Electron Configuration Calculator", 640 - (int)(0.5* metrics.stringWidth("Electron Configuration Calculator")), 200);
550
551 //Draw 'OR'
552 g2.drawString("OR", 640 - (int)(0.5* metrics.stringWidth("OR")), 400);
553
554 //Set color/font
555 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
556 metrics = g2.getFontMetrics();
557
558 //Draw labels
559 g2.drawString("Element Symbol", 320 - (int)(0.5* metrics.stringWidth("Element Symbol")), 275);
560 g2.drawString("# of Electrons", 960 - (int)(0.5* metrics.stringWidth("# of Electrons")), 275);
561 g2.drawString("Charge", 320 - (int)(0.5* metrics.stringWidth("Charge")), 465);
562
563 //Draw values
564 g2.drawString(symbol, 320 - (int)(0.5* metrics.stringWidth(symbol)), 365);
565 g2.drawString(eCount, 960 - (int)(0.5* metrics.stringWidth(eCount)), 365);
566 g2.drawString("" + charge, 320 - (int)(0.5* metrics.stringWidth("" + charge)), 555);
567
568 //Draw the result
569 if(!eCount.equals("NaN") && Integer.parseInt(eCount) > 0) {
570
571 //Separate into lines
572 String[] result = config(Integer.parseInt(eCount)).split(" ");
573 for(int i = 0; i < 3; i++) {
574
575 //Print 10 orbitals if they exist
576 if(result.length > (i * 10)) {
577 String print = "";
578 for(int j = 0; j < 10; j++) if(result.length > (10 * i) + j) print += result[(10 * i) + j] + " ";
579 g2.drawString(print.substring(0, print.length() - 1) + ((i == 2 & result.length > 30) ? " etc..." :""), 640 - (int)(0.5 * metrics.stringWidth(print.substring(0, print.length() - 1))), 640 + (50 * i));
580 }
581 }
582 }
583
584 //Set color/font
585 g2.setColor(Color.BLACK);
586 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
587 metrics = g2.getFontMetrics();
588
589 //Draw Charge buttons
590 g2.drawString("-", 225 - (int)(0.5 * metrics.stringWidth("-")), 555);
591 g2.drawString("+", 415 - (int)(0.5 * metrics.stringWidth("+")), 555);
592
593
594 break;
595
596 //Molecular and Electron Geometry
597 case "ct4":
598
599 //Drawing boxes
600 g2.setColor(Color.GRAY);
601 g2.fillRect(270, 400, 100, 50);
602 g2.fillRect(910, 400, 100, 50);
603 g2.fillRect(120, 550, 400, 50);
604 g2.fillRect(760, 550, 400, 50);
605
606 //Drawing + and - boxes
607 //Plus and minus charge buttons
608 g2.setColor(items == 2 ? new Color(250, 128, 114) : Color.RED);
609 g2.fillRect(200, 400, 50, 50);
610 g2.setColor(lones == 0 ? new Color(250, 128, 114) : Color.RED);
611 g2.fillRect(840, 400, 50, 50);
612 g2.setColor(items == 6 ? new Color(84, 110, 0) : Color.GREEN);
613 g2.fillRect(390, 400, 50, 50);
614 g2.setColor(lones == items - 2 ? new Color(84, 110, 0) : Color.GREEN);
615 g2.fillRect(1030, 400, 50, 50);
616
617 //Set color/font
618 g2.setColor(Color.BLACK);
619 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
620 metrics = g2.getFontMetrics();
621
622 //Draw title
623 g2.drawString("Molecular and Electron Geometry Calculator", 640 - (int)(0.5 * metrics.stringWidth("Molecular and Electron Geometry Calculator")), 275);
624
625 //Draw Charge buttons
626 g2.drawString("-", 225 - (int)(0.5 * metrics.stringWidth("-")), 440);
627 g2.drawString("+", 415 - (int)(0.5 * metrics.stringWidth("+")), 440);
628 g2.drawString("-", 865 - (int)(0.5 * metrics.stringWidth("-")), 440);
629 g2.drawString("+", 1055 - (int)(0.5 * metrics.stringWidth("+")), 440);
630
631 //Set font
632 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
633 metrics = g2.getFontMetrics();
634
635 //Write labels
636 g2.drawString("Number of bonds and electron pairs", 320 - (int)(0.5 * metrics.stringWidth("Number of bonds and electron pairs")), 390);
637 g2.drawString("Number of lone electron pairs", 960 - (int)(0.5 * metrics.stringWidth("Number of lone electron pairs")), 390);
638 g2.drawString("Molecular Geometry", 320 - (int)(0.5 * metrics.stringWidth("Molecular Geometry")), 540);
639 g2.drawString("Electron Geometry", 960 - (int)(0.5 * metrics.stringWidth("Electron Geometry")), 540);
640 g2.drawString("Calculator only supports valid shapes up to 6 items", 640 - (int)(0.5 * metrics.stringWidth("Calculator only supports valid shapes up to 6 items")), 750);
641
642 //Write values
643 g2.drawString("" + items, 320 - (int)(0.5 * metrics.stringWidth("" + items)), 440);
644 g2.drawString("" + lones, 960 - (int)(0.5 * metrics.stringWidth("" + lones)), 440);
645
646 //Solution and check
647 List<String> shape = shape(items, lones);
648 if(shape.size() > 1) {
649 g2.drawString(shape.get(0), 320 - (int)(0.5 * metrics.stringWidth(shape.get(0))), 590);
650 g2.drawString(shape.get(1), 960 - (int)(0.5 * metrics.stringWidth(shape.get(1))), 590);
651 }
652 break;
653
654 //PVnRT Calculator
655 case "ct5":
656
657 //Set color
658 g2.setColor(new Color(50, 205, 50));
659
660 //Highlight selected area
661 int X = 0;
662 for(int i = 1 ; i <= 3; i++) {
663 if(ps > i) X += 320;
664 }
665 if(ps >= 1 && ps <= 4) g2.fillRect(X, 325, 320, 150);
666
667 //Draw grey boxes
668 g2.setColor(Color.GRAY);
669 g2.fillRect(40, 400, 240, 50);
670 g2.fillRect(360, 400, 240, 50);
671 g2.fillRect(680, 400, 240, 50);
672 g2.fillRect(1000, 400, 240, 50);
673 g2.fillRect(40, 600, 240, 50);
674 g2.fillRect(360, 600, 240, 50);
675 g2.fillRect(1000, 600, 240, 50);
676 g2.fillRect(40, 700, 240, 50);
677 g2.fillRect(360, 700, 240, 50);
678 g2.fillRect(680, 700, 240, 50);
679 g2.fillRect(1000, 700, 240, 50);
680 g2.setColor(new Color(250, 128, 114));
681 g2.fillRect(680, 600, 240, 50);
682
683 //Set color/font
684 g2.setColor(Color.BLACK);
685 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 50));
686 metrics = g2.getFontMetrics();
687
688 //Draw title
689 g2.drawString("PVnRT Calculator", 640 - (int)(0.5 * metrics.stringWidth("PVnRT Calculator")), 250);
690
691 //Set font
692 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 43));
693 metrics = g2.getFontMetrics();
694
695 //Label Units
696 g2.drawString("Units", 640 - (int)(0.5 * metrics.stringWidth("Units")), 540);
697
698 //Set font
699 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 35));
700 metrics = g2.getFontMetrics();
701
702 //Instructions
703 g2.drawString("Click a unit to change it. Note: Calculator uses sig figs.", 640 - (int)(0.5 * metrics.stringWidth("Click a unit to change it. Note: Calculator uses sig figs.")), 305);
704
705 //Label Boxes
706 g2.drawString("Pressure", 160 - (int)(0.5 * metrics.stringWidth("Pressure")), 390);
707 g2.drawString("Volume", 480 - (int)(0.5 * metrics.stringWidth("Volume")), 390);
708 g2.drawString("Moles", 800 - (int)(0.5 * metrics.stringWidth("Moles")), 390);
709 g2.drawString("Temperature", 1120 - (int)(0.5 * metrics.stringWidth("Temperature")), 390);
710 g2.drawString("Solve", 160 - (int)(0.5 * metrics.stringWidth("Solve")), 740);
711 g2.drawString("Solve", 480 - (int)(0.5 * metrics.stringWidth("Solve")), 740);
712 g2.drawString("Solve", 800 - (int)(0.5 * metrics.stringWidth("Solve")), 740);
713 g2.drawString("Solve", 1120 - (int)(0.5 * metrics.stringWidth("Solve")), 740);
714
715 //Label values
716 g2.setColor(solved == 1 ? new Color(178, 34, 34) : Color.BLACK);
717 g2.drawString(pres, 160 - (int)(0.5 * metrics.stringWidth(pres)), 440);
718 g2.setColor(solved == 2 ? new Color(178, 34, 34) : Color.BLACK);
719 g2.drawString(vol, 480 - (int)(0.5 * metrics.stringWidth(vol)), 440);
720 g2.setColor(solved == 3 ? new Color(178, 34, 34) : Color.BLACK);
721 g2.drawString(mol, 800 - (int)(0.5 * metrics.stringWidth(mol)), 440);
722 g2.setColor(solved == 4 ? new Color(178, 34, 34) : Color.BLACK);
723 g2.drawString((negTemp ? "-" : "") + temp, 1120 - (int)(0.5 * metrics.stringWidth((negTemp ? "-" : "") + temp)), 440);
724 g2.setColor(Color.BLACK);
725 if(presUn == 0) g2.drawString("Atmospheres", 160 - (int)(0.5 * metrics.stringWidth("Atmospheres")), 640);
726 else if(presUn == 1) g2.drawString("mm Hg / Torr", 160 - (int)(0.5 * metrics.stringWidth("mm Hg / Torr")), 640);
727 else if(presUn == 2) g2.drawString("Kilopascal", 160 - (int)(0.5 * metrics.stringWidth("Kilopascals")), 640);
728 if(volUn == 0) g2.drawString("Liters", 480 - (int)(0.5 * metrics.stringWidth("Liters")), 640);
729 else if(volUn == 1) g2.drawString("Mililiters", 480 - (int)(0.5 * metrics.stringWidth("Mililiters")), 640);
730 g2.drawString("Moles", 800 - (int)(0.5 * metrics.stringWidth("Moles")), 640);
731 if(tempUn == 0) g2.drawString("Kelvin", 1120 - (int)(0.5 * metrics.stringWidth("Kelvin")), 640);
732 else if(tempUn == 1) g2.drawString("Centegrade", 1120 - (int)(0.5 * metrics.stringWidth("Centegrade")), 640);
733 break;
734 }
735
736 //Check if a joke is currently being displayed
737 if(jokeTimer > 0) {
738
739 //Decrement timer
740 jokeTimer--;
741
742 //Set color/font
743 g2.setColor(Color.BLACK);
744 g2.setFont(new Font("Comic Sans MS", Font.BOLD, 30));
745 metrics = g2.getFontMetrics();
746
747 //Draw the joke question
748 g2.drawString("" + (jokes.keySet().toArray()[jokeIndex]), 640 - (int)(0.5 * metrics.stringWidth("" + (jokes.keySet().toArray()[jokeIndex]))), 50);
749
750 //Draw the joke punch line
751 g2.drawString(jokes.get("" + (jokes.keySet().toArray()[jokeIndex])), 640 - (int)(0.5 * metrics.stringWidth(jokes.get("" + (jokes.keySet().toArray()[jokeIndex])))), 100);
752 }
753
754 }
755
756 //Method: clock
757 //Description: Calls the repaint method every couple of miliseconds
758 //Parameters: None
759 //Return: void
760 public void clock() {
761
762 //Updates background characters
763 for(Character c : background) c.timerMove();
764
765 //Repaint
766 this.repaint();
767 }
768
769 public String getCondition() {
770 return condition;
771 }
772
773
774 public void setCondition(String condition) {
775 this.condition = condition;
776 }
777
778 //Method: joke
779 //Description: Displays a joke for 10 seconds
780 //Parameters: None
781 //Return: void
782 public void joke() {
783
784 //Keeps it up for a 250 ticks
785 jokeTimer = 250;
786
787 //Increment the index of the joke within the hashmap
788 jokeIndex = (jokeIndex + 1) % jokes.size();
789 }
790
791 //Method: resetFocus
792 //Description: Resets selected areas when transitioning between tools
793 //Parameters: None
794 //Return: void
795 public void resetFocus() {
796 abs = 0;
797 acidLoc = 0;
798 phs = 0;
799 es = 0;
800 ps = 0;
801 }
802
803 //Method: isAmphoteric
804 //Description: Returns whether or not a substance is in a lost of amphoteric substances
805 //Parameters: String substance - The substance to test
806 //Return: boolean - Whether the substance is or isn't amphoteric
807 public static boolean isAmphoteric(String sub) {
808
809 //List of amphoteric substances
810 String[] amph = new String[] {"H2O", "HCO3", "HSO4", "HSO3", "HPO3", "H2PO3", "NH3"};
811
812 //Check if substance is in the list
813 for(String str : amph) if(sub.equals(str)) return true;
814 return false;
815 }
816
817
818 //Method: isAcid
819 //Description: Determines whether or not a substance is acidic
820 //Parameters: String sub - Substance to test
821 //Return: boolean - Whether or not the substance is acidic
822 public static boolean isAcid(String sub) {
823 return sub.equals("NH4") || sub.equals("NH3") || sub.equals("H") || (sub.length() > 1 && sub.charAt(0) == 'H' && sub.charAt(1) != 'O');
824 }
825
826
827 //Method: findProducts
828 //Description: Calculates the two products of a reaction
829 //Parameters: String acid & String base - The acid and base to use to calculate the conjugate acid and base
830 //Return: String[] - The conjugate base and acid respectively
831 public String[] findProducts(String acid, String base) {
832
833 //Create returned array
834 String[] ret = new String[2];
835
836 //Make sure acid exists
837 if(acid.length() > 1) {
838
839 //Find proton
840 int a = acid.indexOf('H');
841
842 //If one proton and only one proton exists, remove it
843 if(acid.charAt(acid.length() - 1) == 'H' || (int)acid.charAt(a + 1) >= 65) ret[1] = acid.substring(0, a) + acid.substring(a + 1);
844
845 //If multiple protons exist, simply remove one
846 else ret[1] = acid.substring(0, a + 1) + ((findNum(acid, a) == 2 ? "" : (findNum(acid, a) - 1))) + acid.substring(a + 1 + ("" + findNum(acid, a)).length());
847 }
848
849 //If the base already contains a proton
850 if(base.indexOf('H') > -1) {
851
852 //Find the proton
853 int b = base.indexOf('H');
854
855 //If it only has one, add a number two indicating it has two
856 if(base.charAt(base.length() - 1) == 'H' || (int)base.charAt(b + 1) >= 65) ret[0] = base.substring(0, b + 1) + '2' + base.substring(b + 1);
857
858 //If it already has multiple, increment the count
859 else ret[0] = base.substring(0, b + 1) + (findNum(base, b) + 1) + base.substring(b + 1 + ("" + findNum(base, b)).length());
860 }
861
862 //If it did not already have a proton, simply add one to the beginning
863 else ret[0] = "H" + base;
864
865 //Make sure no null values are being returned
866 if(ret[0] == null) ret[0] = "";
867 if(ret[1] == null) ret[1] = "";
868
869 //Rearranging common acids/bases
870 if(ret[0].equals("OH2")) ret[0] = "H2O";
871 if(ret[1].equals("OH2")) ret[1] = "H2O";
872 if(ret[0].equals("HO")) ret[0] = "OH";
873 if(ret[1].equals("HO")) ret[1] = "OH";
874
875 //Return result
876 return ret;
877 }
878
879
880 //Method: fullInput
881 //Description: Detects whether or not there is enough information to calculate the pH
882 //Parameters: None
883 //Return: boolean - Whether or not there is enough information to calculate pH
884 public boolean fullInput() {
885 if(Double.parseDouble(acidMoles) > 0 && Double.parseDouble(baseMoles) > 0 && weakAcid && weakBase) return false;
886 if(weakAcid && Double.parseDouble(pKa) <= 0) return false;
887 if(weakBase && Double.parseDouble(pKb) <= 0) return false;
888 if(Double.parseDouble(pHVolume) <= 0) return false;
889 return true;
890 }
891
892
893 //Method: findpH
894 //Description: Calculates pH using all the information entered
895 //Parameters: acidMoles and baseMoles - The number of moles of acid/base
896 // pKa and pKb - pKa of the acid, and Kb of the base
897 // weakAcid and weakBase - Whether or not the acids and bases are weak
898 //Return: String - pH of the solution rounded to the 100ths place
899 public String findpH(String acidMoles, boolean weakAcid, String pKa, String baseMoles, boolean weakBase, String pKb) {
900
901 //Creating double representations of necessary variables
902 double aM;
903 if(acidMoles.charAt(acidMoles.length() - 1) != '.') aM= Double.parseDouble(acidMoles);
904 else aM = Double.parseDouble(acidMoles.substring(0, acidMoles.length() - 1));
905 double bM;
906 if(baseMoles.charAt(baseMoles.length() - 1) != '.') bM= Double.parseDouble(baseMoles);
907 else bM = Double.parseDouble(baseMoles.substring(0, baseMoles.length() - 1));
908 double vol;
909 if(pHVolume.charAt(pHVolume.length() - 1) != '.') vol= Double.parseDouble(pHVolume);
910 else vol = Double.parseDouble(pHVolume.substring(0, pHVolume.length() - 1));
911 double PKA;
912 if(pKa.charAt(pKa.length() - 1) != '.') PKA= Double.parseDouble(pKa);
913 else PKA = Double.parseDouble(pKa.substring(0, pKa.length() - 1));
914 double PKB;
915 if(pKb.charAt(pKb.length() - 1) != '.') PKB= Double.parseDouble(pKb);
916 else PKB = Double.parseDouble(pKb.substring(0, pKb.length() - 1));
917
918 //If no acid or base exists
919 if(aM == 0 && bM == 0) return "7";
920 //If only a base exists
921 if(aM == 0) {
922
923 //If only a weak base exists
924 if(weakBase) {
925
926 //Find possible solutions
927 String[] roots = findRoots("1", BigDecimal.valueOf(Math.pow(10, -PKB)).toPlainString(), BigDecimal.valueOf(-Math.pow(10, -PKB) * (bM/vol)).toPlainString());
928
929 //If the first is valid
930 if(Double.parseDouble(roots[0]) >= 0 && Double.parseDouble(roots[0]) <= (bM/vol)) {
931
932 //If both are valid, no concrete solution
933 if(Double.parseDouble(roots[1]) >= 0 && Double.parseDouble(roots[1]) <= (bM/vol)) return null;
934
935 //If the first solution is the only valid solution
936 else {
937 if(-Math.log10(Double.parseDouble(roots[0])) <= 14 && -Math.log10(Double.parseDouble(roots[0])) >= 0)
938 return (14 + Math.log10(Double.parseDouble(roots[0])) < 7) ? "7" : new BigDecimal(14 + Math.log10(Double.parseDouble(roots[0]))).toPlainString();
939 }
940 }
941
942 //If the second solution is the only valid solution
943 else if(Double.parseDouble(roots[1]) >= 0 && Double.parseDouble(roots[1]) <= (bM/vol)) {
944 if(-Math.log10(Double.parseDouble(roots[1])) <= 14 && -Math.log10(Double.parseDouble(roots[1])) >= 0)
945 return new BigDecimal(14 + Math.log10(Double.parseDouble(roots[1]))).toPlainString();
946 }
947
948 //If there are no valid solutions
949 else return null;
950 }
951
952 //If the base is strong
953 else {
954
955 //If base is extremely dilute
956 if(bM/vol <= 0.011) {
957 String[] roots = findRoots("1", BigDecimal.valueOf(bM/vol).toPlainString(), BigDecimal.valueOf(-Math.pow(10, -14)).toPlainString());
958
959 //Invalid solutions
960 if((roots[0] == "" || (Double.parseDouble(roots[0]) < 0) && (roots[1].length() < 1 && Double.parseDouble(roots[1]) < 0)) || (Double.parseDouble(roots[0]) > 0 && Double.parseDouble(roots[1]) > 0)) return null;
961
962 //If one solution
963 if(Double.parseDouble(roots[1]) > 0) return new BigDecimal(14 + Math.log10((bM/vol) + Double.parseDouble(roots[1]))).toPlainString();
964 return new BigDecimal(14 + Math.log10((bM/vol) + Double.parseDouble(roots[0]))).toPlainString();
965 }
966
967 //If base is not dilute
968 if(14 + Math.log10(bM/vol) <= 14 && 14 + Math.log10(bM/vol) >= 0)
969 return new BigDecimal(14 + Math.log10(bM/vol)).toPlainString();
970 }
971 }
972
973 //If only an acid exists
974 else if(bM == 0) {
975
976 //If it is a weak acid
977 if(weakAcid) {
978
979 //Find possible solutions
980 String[] roots = findRoots("1", BigDecimal.valueOf(Math.pow(10, -PKA)).toPlainString(), BigDecimal.valueOf(-Math.pow(10, -PKA) * (aM/vol)).toPlainString());
981 //If the first is valid
982 if(Double.parseDouble(roots[0]) >= 0 && Double.parseDouble(roots[0]) <= (aM/vol)) {
983
984 //If both are valid, no concrete solution
985 if(Double.parseDouble(roots[1]) >= 0 && Double.parseDouble(roots[1]) <= (aM/vol)) return null;
986
987 //If the first solution is the only valid solution
988 else {
989 if(-Math.log10(Double.parseDouble(roots[0])) <= 14 && -Math.log10(Double.parseDouble(roots[0])) >= 0)
990 return (-Math.log10(Double.parseDouble(roots[0])) > 7) ? "7" : new BigDecimal(-Math.log10(Double.parseDouble(roots[0]))).toPlainString();
991 }
992 }
993
994 //If the second solution is the only valid solution
995 else if(Double.parseDouble(roots[1]) >= 0 && Double.parseDouble(roots[1]) <= (aM/vol)) {
996 if(-Math.log10(Double.parseDouble(roots[1])) <= 14 && -Math.log10(Double.parseDouble(roots[1])) >= 0)
997 return new BigDecimal(-Math.log10(Double.parseDouble(roots[1]))).toPlainString();
998 }
999
1000 //If there are no valid solutions
1001 else return null;
1002 }
1003
1004 //If it is a strong acid
1005 else {
1006
1007 //If acid is extremely dilute
1008 if(aM/vol <= 0.01) {
1009 String[] roots = findRoots("1", BigDecimal.valueOf(aM/vol).toPlainString(), BigDecimal.valueOf(-Math.pow(10, -14)).toPlainString());
1010
1011 //Invalid solutions
1012 if(roots[0] == "" || (Double.parseDouble(roots[0]) < 0 && Double.parseDouble(roots[1]) < 0) || (Double.parseDouble(roots[0]) > 0 && Double.parseDouble(roots[1]) > 0)) return null;
1013
1014 //If one solution
1015 if(Double.parseDouble(roots[1]) > 0) return new BigDecimal(-Math.log10((aM/vol) + Double.parseDouble(roots[1]))).toPlainString();
1016 return BigDecimal.valueOf(-Math.log10((aM/vol) + Double.parseDouble(roots[0]))).toPlainString();
1017 }
1018
1019 if(-Math.log10(aM/vol) <= 14 && -Math.log10(aM/vol) >= 0)
1020 return BigDecimal.valueOf(-Math.log10(aM/vol)).toPlainString();
1021 }
1022 }
1023
1024 //If both an acid/base exist
1025 else {
1026
1027 //If both are weak, invalid
1028 if(weakAcid && weakBase) return null;
1029
1030 //If both are strong
1031 else if(!weakAcid && !weakBase) {
1032 //If more acid
1033 if(aM > bM) return findpH(BigDecimal.valueOf(aM - bM).toPlainString(), false, pKa, "0", false, pKb);
1034
1035 //If more base
1036 if(bM > aM) return findpH("0", false, pKa, BigDecimal.valueOf(bM - aM).toPlainString(), false, pKb);
1037
1038 //Same of both
1039 else return "7";
1040 }
1041
1042 //Strong acid weak base
1043 else if(!weakAcid && weakBase) {
1044
1045 //If more acid
1046 if(aM > bM) return findpH(BigDecimal.valueOf(aM - bM).toPlainString(), false, pKa, "0", false, pKb);
1047
1048 //If same
1049 if(aM == bM) return findpH(acidMoles, true, BigDecimal.valueOf(Math.pow(10, -14)/PKB).toPlainString(), "0", false, pKb);
1050
1051 //If more base
1052 else if(bM > aM) {
1053
1054 //Finding raw solution
1055 double sol = 14 - PKB - Math.log10(aM / (bM - aM));
1056
1057 //Bounds
1058 if(sol >= 14) return "14";
1059 if(sol <= 0) return "0";
1060
1061 //Returning solution
1062 return BigDecimal.valueOf(sol).toPlainString();
1063 }
1064 }
1065
1066 //Strong base weak acid
1067 else if(!weakBase && weakAcid) {
1068
1069 //If more base
1070 if(bM > aM) return BigDecimal.valueOf(14 + Math.log10((bM - aM)/vol)).toPlainString();
1071
1072 //If same
1073 if(aM == bM) return findpH("0", false, pKa, baseMoles, true, BigDecimal.valueOf(Math.pow(10, -14)/PKA).toPlainString());
1074
1075 //If more acid
1076 else if(aM >= bM) {
1077
1078 //Finding raw solution
1079 double sol = PKA + Math.log10(bM / (aM - bM));
1080
1081 //Bounds
1082 if(sol >= 14) return "14";
1083 if(sol <= 0) return "0";
1084
1085 //Returning solution
1086 return BigDecimal.valueOf(sol).toPlainString();
1087 }
1088 }
1089 }
1090
1091 //In case nothing is detected
1092 return null;
1093 }
1094
1095 //Method: sigFigs
1096 //Description: Rounds a number using sig figs, and the numbers used to calculate them
1097 //Parameters: double num - The number to round
1098 // String[] figs - A list of the numbers used in calculation
1099 //Return: String - The rounded number
1100 public static String sigFigs(double num, String[] figs) {
1101
1102 //Array containing the sig fig values
1103 int[] f = new int[figs.length];
1104
1105 //Setting values
1106 for(int i = 0; i < figs.length; i++) {
1107
1108 //Find the number of significant figures of each number
1109 f[i] = findFigs(figs[i]);
1110 }
1111
1112 //Return solution
1113 return BigDecimal.valueOf(num).round(new MathContext(Arrays.stream(f).min().getAsInt())).toPlainString();
1114
1115 }
1116
1117 //Method: findFigs
1118 //Description: Calculates the number of significant figures in a number
1119 //Parameters: String str - number to calculate
1120 //Return: int - The number of figures it contains
1121 public static int findFigs(String str) {
1122 //If there is a dot
1123 if(str.indexOf(".") > -1) {
1124 double num = new BigDecimal(str).doubleValue();
1125 int counter = 1;
1126 while(Math.abs(num) < 1) {
1127 num *= 10;
1128 counter++;
1129 }
1130 return str.length() - counter;
1131 }
1132
1133 //If there is no dot
1134 else {
1135
1136 //Find total length
1137 int len = str.length();
1138
1139 //Subtract one for each trailing zero
1140 while(str.length() > 0 && str.charAt(str.length() - 1) == '0') {
1141 len--;
1142 str = str.substring(0, str.length() - 1);
1143 }
1144 return len;
1145 }
1146 }
1147
1148 //Method: findRoots
1149 //Description: Calculates the quadratic roots of a given equation
1150 //Parameters: Strings A B & C - The coefficients of the second, first and zeroth power variables respectively
1151 //Return: String[] - The two roots in String format
1152 public static String[] findRoots(String A, String B, String C) {
1153 double a = Double.parseDouble(A);
1154 double b = Double.parseDouble(B);
1155 double c = Double.parseDouble(C);
1156 if((b * b) - (4 * a * c) < 0) return new String[] {"", ""};
1157 return new String[] {new BigDecimal(((-b + Math.sqrt((b * b) - (4 * a * c))) / (2 * a))).toPlainString(), new BigDecimal(((-b - Math.sqrt((b * b) - (4 * a * c))) / (2 * a))).toPlainString()};
1158 }
1159
1160 //Method: findNum
1161 //Description: Finds the number after an index in a string
1162 //Parameters: String sub - The String to parse
1163 // int index - The index from where to start
1164 //Return: int - The number located
1165 public static int findNum(String sub, int index) {
1166 int fin = index;
1167 while(sub.length() > fin + 1 && (sub.charAt(fin + 1) >= 48 && sub.charAt(fin + 1) <= 57)) fin++;
1168 return Integer.parseInt(sub.substring(index + 1, fin + 1));
1169 }
1170
1171
1172 //Method: validAppend
1173 //Description: Attempts to add a character to a substance
1174 //Parameters: String sub - Base substance
1175 // int chr - The character to add
1176 //Return: String
1177 public static String validAppend(String sub, int chr) {
1178 if(sub.length() <= 10) {
1179
1180 //No starting zeroes so return the original string
1181 if((chr == 48 && (sub.length() == 0 || (int)sub.charAt(sub.length() - 1) >= 65)) || (chr < 65 && sub.length() == 0)) return sub;
1182
1183 //No unnecessary ones, so remove it
1184 else if(chr >= 65 && (sub.length() != 0 && sub.charAt(sub.length() - 1) == '1' && (int)sub.charAt(sub.length() - 2) >= 65)) return sub.substring(0, sub.length() - 1) + (char)chr;
1185
1186 //No solo lowercase letters, so dont append anything
1187 if(chr >= 97 && (sub.length() == 0 || (int)sub.charAt(sub.length() - 1) >= 97 || (int)sub.charAt(sub.length() - 1) < 65)) return sub;
1188
1189 //If duplicate chemical add a two
1190 if(chr >= 65 && sub.length() >= 1 && chr == sub.charAt(sub.length() - 1) && !(sub.length() >= 2 && sub.charAt(sub.length() - 2) == 'C' && sub.charAt(sub.length() - 1) == 'O')) return sub + "2";
1191
1192 //Valid way to append the character
1193 return sub + (char)chr;
1194 }
1195 return sub;
1196 }
1197
1198 //Method: appendDouble
1199 //Method: appendDouble
1200 //Description: Finds a way to add a character to a string to create a valid double
1201 //Parameters: String num - base double | char c - character to add
1202 //Return: String - new double
1203 public static String appendDouble(String num, char c) {
1204
1205 //Check if its just repeating unnecessary zeroes
1206 boolean notAllZeroes = false;
1207 for(char chr : num.toCharArray()) {
1208 if(chr != 48) notAllZeroes = true;
1209 }
1210 if(!notAllZeroes && c == 48) return num;
1211
1212 //Too long
1213 if(num.length() >= 10 && c != 8) return num;
1214
1215 //Empty string, so add character
1216 if(num.length() == 0) return "" + c;
1217
1218 //Backspace pressed on an empty string or one digit string
1219 if((int)c == KeyEvent.VK_BACK_SPACE) {
1220 if(num.length() == 1) return "0";
1221 if(num.length() == 0) return "0";
1222 }
1223
1224 //Backspace pressed, so remove a digit if it is long enough
1225 if(c == 8 && num.length() > 1) num = num.substring(0, num.length() - 1);
1226
1227 //Adding a digit
1228 if(c >= 48 && c <= 57) {
1229 while(num.length() > 0 && num.charAt(0) == '0' && (num.length() == 1 || (num.length() > 1 && num.charAt(1) != '.'))) num = num.substring(1);
1230 return num + c;
1231 }
1232
1233 //Adding a dot, if one does not already exist
1234 if(c == '.') {
1235 if(num.length() == 0) return "0.";
1236 if(num.indexOf(".") < 0) return num + c;
1237 }
1238
1239 //Returning new number
1240 return num;
1241 }
1242
1243
1244 //Method: config
1245 //Description: Finds the electron configuration
1246 //Parameters: int electrons - # of electrons
1247 //Return: String - electron configuration
1248 public static String config(int electrons) {
1249
1250 //Smaller elements
1251 if(electrons <= 18) {
1252
1253 //1S and P orbitals
1254 if(electrons % 8 != 3 && electrons % 8 != 4) {
1255
1256 //Hydrogen and Helium
1257 if(electrons <= 2) return "1s" + electrons;
1258
1259 //3P Orbital
1260 if(electrons > 10) return config(12) + " 3p" + (electrons - 12);
1261
1262 //2P Orbital
1263 return config(4) + " 2p" + (electrons - 4);
1264 }
1265
1266 //2S and 3S orbitals
1267 else {
1268
1269 //3S Orbital
1270 if(electrons > 4) return config(10) + " 3s" + (electrons - 10);
1271
1272 //2S Orbital
1273 return config(2) + " 2s" + (electrons - 2);
1274 }
1275 }
1276
1277 //Medium elements
1278 if(electrons <= 54) {
1279
1280 //S Orbitals
1281 if(electrons % 18 <= 2 && electrons % 18 != 0) return config(electrons - (electrons % 18)) + " " + (((electrons - 1)/ 18) + 3) + "s" + (electrons % 18);
1282
1283 //D Orbital exceptions (To fill 1/2 and full orbitals)
1284 if(electrons % 18 == 6 || electrons % 18 == 11) return config(electrons - (electrons % 18)) + " " + (((electrons - 1)/ 18) + 3) + "s1 " + (((electrons - 1)/ 18) + 2) + "d" + ((electrons % 18) + 1);
1285
1286 //D Orbitals
1287 if(electrons % 18 <= 12 && electrons % 18 != 0) return config(electrons - ((electrons % 18) - 2) - ((electrons % 18 == 0) ? 18 : 0)) + " " + (((electrons - 1)/ 18) + 2) + "d" + ((electrons % 18) - 2);
1288
1289 //P Orbitals
1290 return config(electrons - (electrons % 18) + 12 - ((electrons % 18 == 0) ? 18 : 0)) + " " + (((electrons - 1)/ 18) + 3) + "p" + ((electrons % 18) - 12 + ((electrons % 18 == 0) ? 18 : 0));
1291 }
1292
1293 //Larger elements
1294 else {
1295
1296 //S Orbitals
1297 if(electrons % 32 == 23 || electrons % 32 == 24) return config(electrons - ((electrons - 22) % 32)) + " " + (((electrons + 9) / 32) + 4) + "s" + ((electrons + 10) % 32);
1298
1299 //F Orbital exceptions
1300 if(electrons % 32 == 26) return config(electrons - 2) + " " + (2 + (electrons / 32)) + "f1" + " " + (3 + (electrons / 32)) + "d1";
1301 if(electrons % 32 == 25 || electrons % 32 == 0) return config(electrons - 1) + " " + (((electrons - 1) / 32) + 3) + "d1";
1302
1303 //F Orbitals
1304 if(electrons % 32 <= 6 || electrons % 32 >= 25) return config(electrons - ((electrons + 10) % 32) + 2 - (((electrons + 10) % 32) == 0 ? 32 : 0)) + " " + (((electrons + 9) / 32) + 2) + "f" + (((electrons + 10) % 32) - 2);
1305
1306 //D Orbital exceptions
1307 if(electrons % 32 == 10 || electrons % 32 == 15) return config(electrons - ((electrons + 10) % 32) - (((electrons + 10) % 32) == 0 ? 32 : 0)) + " " + (((electrons + 9) / 32) + 4) + "s1 " + (((electrons + 9) / 32) + 2) + "f14 " + (((electrons + 9) / 32) + 3) + "d" + (((electrons + 10) % 32) - 15 + (((electrons + 10) % 32) == 0 ? 32 : 0));
1308
1309 //D Orbitals
1310 if(electrons % 32 <= 16) return config(electrons - ((electrons + 10) % 32) + 16 - (((electrons + 10) % 32) == 0 ? 32 : 0)) + " " + (((electrons + 9) / 32) + 3) + "d" + (((electrons + 10) % 32) - 16 + (((electrons + 10) % 32) == 0 ? 32 : 0));
1311
1312 //P Orbitals
1313 return config(electrons - ((electrons + 10) % 32) + 26 - (((electrons + 10) % 32) == 0 ? 32 : 0)) + " " + (((electrons + 9) / 32) + 4) + "p" + (((electrons + 10) % 32) - 26 + (((electrons + 10) % 32) == 0 ? 32 : 0));
1314 }
1315 }
1316
1317
1318 //Method: shape
1319 //Description: Calculates molecular/electron geometry based on entered data
1320 //Parameters: int items - Number of bonds/electron pairs around the nucleus
1321 // int lones - The number of electron pairs around the nucleus
1322 //Return: String[] - The molecular and electron geometries of the molecule respectively
1323 public List<String> shape(int items, int lones) {
1324
1325 //Possible shapes
1326 HashMap<Integer, String> shapes = new HashMap<>();
1327 shapes.put(20, "Linear,Linear");
1328 shapes.put(30, "Trigonal Planar,Trigonal Planar");
1329 shapes.put(31, "Trigonal Planar,Bent");
1330 shapes.put(40, "Tetrahedral,Tetrahedral");
1331 shapes.put(41, "Tetrahedral,Trigonal Pyramidal");
1332 shapes.put(42, "Tetrahedral,Bent");
1333 shapes.put(50, "Trigonal Bipyramidal,Trigonal Bipyramidal");
1334 shapes.put(51, "Trigonal Bipyramidal,Seesaw");
1335 shapes.put(52, "Trigonal Bipyramidal,T-shaped");
1336 shapes.put(53, "Trigonal Bipyramidal,Linear");
1337 shapes.put(60, "Octahedral,Octahedral");
1338 shapes.put(61, "Octahedral,Square Pyramidal");
1339 shapes.put(62, "Octahedral,Square Planar");
1340 shapes.put(63, "Octahedral,T-shaped");
1341 shapes.put(64, "Octahedral,Linear");
1342
1343 //Check the validity of the input, and return the shapes
1344 if(items >= 2 && items <= 6 && lones >= 0 && lones <= (items - 2)) return Arrays.asList(shapes.get((10 * items) + lones).split(","));
1345 return Arrays.asList(new String[] {"Invalid", "Invalid"});
1346 }
1347
1348 public String PVnRT() {
1349
1350 //Converting variables to doubles and in the correct format
1351 double atm = Double.parseDouble(pres);
1352 if(presUn == 1) atm /= 760;
1353 if(presUn == 2) atm /= 101.325;
1354 double liter = Double.parseDouble(vol);
1355 if(volUn == 1) liter /= 1000;
1356 double mole = Double.parseDouble(mol);
1357 double kelvin = Double.parseDouble(temp);
1358 if(tempUn == 1) kelvin += 273.15;
1359 final double R = 0.08206;
1360
1361 //Find solution
1362 switch(solved) {
1363
1364 //Find Pressure
1365 case 1:
1366 if(liter <= 0 || mole <= 0 || kelvin <= 0) return "0";
1367 return sigFigs((mole * R * kelvin * (presUn == 1 ? 760 : (presUn == 2 ? 101.325 : 1)))/liter, new String[] {vol, mol, temp});
1368
1369 //Find Volume
1370 case 2:
1371 if(atm <= 0 || mole <= 0 || kelvin <= 0) return "0";
1372 return sigFigs((mole * R * kelvin * (volUn == 1 ? 1000 : 1))/atm, new String[] {pres, mol, temp});
1373
1374 //Find Moles
1375 case 3:
1376 if(atm <= 0 || liter <= 0 || kelvin <= 0) return "0";
1377 return sigFigs((atm * liter) / (R * kelvin), new String[] {pres, vol, temp});
1378
1379 //Find Moles
1380 case 4:
1381 if(atm <= 0 || liter <= 0 || mole <= 0) return "0";
1382 return sigFigs(((atm * liter) / (mole * R)) - (tempUn == 1 ? 273.15 : 0), new String[] {pres, vol, mol});
1383
1384 default:
1385 return "0";
1386 }
1387
1388 }
1389
1390 //Name: keyPressed
1391 //Description: Reads user input via keystrokes
1392 //Variables: e - KeyEvent
1393 //Output: void
1394 @Override
1395 public void keyPressed(KeyEvent e) {
1396
1397 //Character
1398 int code = e.getKeyChar();
1399 switch(condition) {
1400
1401 //Acid/Base reaction
1402 case "ct1":
1403
1404 //If number or letter pressed
1405 if((code >= 48 && code <= 57) || (code >= 65 && code <= 90 || (code >= 97 && code <= 122))) {
1406
1407 //Find selected area
1408 switch(abs) {
1409
1410 //First reactant
1411 case 1:
1412
1413 //Add character
1414 reac1 = validAppend(reac1, code);
1415 break;
1416
1417 //Second reactant
1418 case 2:
1419
1420 //Add character
1421 reac2 = validAppend(reac2, code);
1422 break;
1423 }
1424 }
1425
1426 //If removing a character
1427 else if(code == KeyEvent.VK_BACK_SPACE) {
1428
1429 //Find selected area
1430 switch(abs) {
1431
1432 //Reactant 1
1433 case 1:
1434
1435 //Remove from reactant 1
1436 if(reac1.length() > 0) reac1 = reac1.substring(0, reac1.length() - 1);
1437 break;
1438
1439 //Reactant 2
1440 case 2:
1441
1442 //Remove from reactant 2
1443 if(reac2.length() > 0) reac2 = reac2.substring(0, reac2.length() - 1);
1444 break;
1445 }
1446 }
1447
1448 //If switching areas
1449 else if(code == KeyEvent.VK_TAB) {
1450
1451 //Increment from 1 to 2
1452 if(abs == 1) abs = 2;
1453
1454 //Move back from 2 to 1
1455 else if(abs == 2) abs = 1;
1456
1457 //Start at 1
1458 else if(abs == 0) abs = 1;
1459 }
1460 //Find acid location
1461 if(reac1.length() > 0 && reac2.length() > 0) {
1462
1463 //Invalid
1464 if((!isAcid(reac1) && !isAcid(reac2)) || ((isAcid(reac1) && !isAmphoteric(reac1)) && (isAcid(reac2) && !isAmphoteric(reac2)))) acidLoc = 3;
1465
1466 //Slot 1
1467 else if((isAcid(reac1) && (isAmphoteric(reac2) || !isAcid(reac2))) || (reac1.equals("H") && reac2.equals("H"))) acidLoc = 1;
1468
1469 //Slot 2
1470 else if(isAcid(reac2) && (isAmphoteric(reac1) || !isAcid(reac1))) acidLoc = 2;
1471 }
1472
1473 //Bottom labels
1474 switch(acidLoc) {
1475
1476 //Not yet fully typed
1477 case 0:
1478 case 3:
1479
1480 //Dont label anything
1481 for(int i = 0; i < 4; i++) labels[i] = "";
1482 break;
1483
1484 //Acid is in slot 1
1485 case 1:
1486 labels[0] = "Acid";
1487 labels[2] = "Conjugate Base";
1488 labels[1] = "Base";
1489 labels[3] = "Conjugate Acid";
1490 break;
1491
1492 //Acid is in slot 2
1493 case 2:
1494 labels[0] = "Base";
1495 labels[2] = "Conjugate Acid";
1496 labels[1] = "Acid";
1497 labels[3] = "Conjugate Base";
1498 break;
1499
1500 }
1501 break;
1502
1503 //pH Calculator
1504 case "ct2":
1505
1506 //Switching selected area
1507 if(e.getKeyCode()==KeyEvent.VK_TAB) {
1508
1509 //Increment
1510 phs = (phs+1)%8;
1511
1512 //Start at 1
1513 if(phs == 0) phs = 1;
1514 }
1515
1516 //Check if meaning to switch a weak button
1517 else if(e.getKeyCode()==KeyEvent.VK_ENTER){
1518 if(phs == 2) weakAcid = !weakAcid;
1519 if(phs == 5) weakBase = !weakBase;
1520 }
1521
1522 //Trying to change the selected item
1523 else if(code == '.' || (code >= 48 && code <= 57) || code == 8) {
1524
1525 //Finding right item to switch
1526 switch(phs) {
1527
1528 //Moles of acid
1529 case 1:
1530 acidMoles = appendDouble(acidMoles, (char)(e.getKeyCode()));
1531 break;
1532
1533 //pKa
1534 case 3:
1535 pKa = appendDouble(pKa, (char)(e.getKeyCode()));
1536 break;
1537
1538 //Moles of base
1539 case 4:
1540 baseMoles = appendDouble(baseMoles, (char)(e.getKeyCode()));
1541 break;
1542
1543 //pKb
1544 case 6:
1545 pKb = appendDouble(pKb, (char)(e.getKeyCode()));
1546 break;
1547
1548 //Volume of solution
1549 case 7:
1550 pHVolume = appendDouble(pHVolume, (char)(e.getKeyCode()));
1551 break;
1552 }
1553 }
1554 break;
1555
1556 //Electron Configuration Calculator
1557 case "ct3":
1558
1559 //If meant to change focus
1560 if(e.getKeyCode() == KeyEvent.VK_TAB) es = (es % 2) + 1;
1561
1562 //Adding to the symbol
1563 if(es == 1) {
1564
1565 //Adding character
1566 if(e.getKeyCode() >= 65 && e.getKeyCode() <= 90) {
1567 switch(symbol.length()) {
1568
1569 case 0: symbol += (char)e.getKeyCode();
1570 break;
1571
1572 case 1: symbol += ("" + (char)e.getKeyCode()).toLowerCase();
1573 break;
1574 }
1575 }
1576
1577 //Backspace
1578 if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
1579 if(symbol.length() > 0) symbol = symbol.substring(0, symbol.length() - 1);
1580 }
1581
1582 //Changing electron count
1583 eCount = "NaN";
1584 if(Arrays.asList(elements).contains(symbol)) eCount = "" + (Arrays.asList(elements).indexOf(symbol) + 1 - charge);
1585 }
1586
1587 if(es == 2) {
1588
1589 //Adding character
1590 if(e.getKeyCode() == 48 && Integer.parseInt(eCount) > 0) eCount += "0";
1591
1592 //Non-zero digit
1593 else if(e.getKeyCode() >= 49 && e.getKeyCode() <= 57) {
1594 if(Integer.parseInt(eCount) == 0) eCount = "" + (char)e.getKeyCode();
1595 else if(Integer.parseInt(eCount) >= 100) eCount = "999";
1596 else eCount += (char)e.getKeyCode();
1597 }
1598 else if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
1599 if(eCount.length() == 1) eCount = "0";
1600 else eCount = eCount.substring(0, eCount.length() - 1);
1601 }
1602
1603 //Setting charge and symbol
1604 charge = 0;
1605 if(!eCount.equals("NaN") && Integer.parseInt(eCount) <= 118 && Integer.parseInt(eCount) > 0) symbol = elements[Integer.parseInt(eCount) - 1];
1606 else symbol = "N/A";
1607 }
1608 break;
1609
1610 //PVnRT Calculator
1611 case "ct5":
1612
1613 //Shift focus
1614 if(KeyEvent.VK_TAB == e.getKeyCode()) ps = (ps % 4) + 1;
1615
1616 //Changing a double
1617 if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE || e.getKeyCode() == KeyEvent.VK_PERIOD || (e.getKeyCode() >= 48 && e.getKeyCode() <= 57)) switch(ps) {
1618
1619 case 1:
1620 pres = appendDouble(pres, (char)e.getKeyCode());
1621 break;
1622 case 2:
1623 vol = appendDouble(vol, (char)e.getKeyCode());
1624 break;
1625 case 3:
1626 mol = appendDouble(mol, (char)e.getKeyCode());
1627 break;
1628 case 4:
1629 temp = appendDouble(temp, (char)e.getKeyCode());
1630 break;
1631 }
1632
1633 //Negative temperature
1634 if(ps == 4 && e.getKeyCode() == KeyEvent.VK_SUBTRACT && tempUn == 1) negTemp = !negTemp;
1635
1636 //Temperature negative bound
1637 if(Double.parseDouble(temp) >= 273.15 && negTemp) temp = "273.15";
1638
1639 }
1640 }
1641
1642 @Override
1643 public void keyTyped(KeyEvent e) {
1644 }
1645
1646 @Override
1647 public void keyReleased(KeyEvent e) {
1648 }
1649
1650 //Name: mouseClicked
1651 //Description: Detects mouse clicks, and acts on them
1652 //Parameters: e - mouse event
1653 //Output: void
1654 @Override
1655 public void mouseClicked(MouseEvent e) {
1656
1657 //Find the current display
1658 switch(condition) {
1659
1660 //Acid/base reaction
1661 case "ct1":
1662
1663 //Locate click
1664 if(e.getX() < 320) abs = 1;
1665 else if(e.getX() < 640) abs = 2;
1666 else abs = 0;
1667 break;
1668
1669 //pH Calculator
1670 case "ct2":
1671
1672 //Locate click
1673 phs = 1;
1674 if(e.getX() >= 320) phs = 4;
1675 if(e.getY() >= 600) phs++;
1676 if(e.getY() >= 450) phs++;
1677 if(e.getX() >= 640 || e.getY() < 300 || e.getY() > 750) phs = 0;
1678
1679 //Check if switching a button as well
1680 if(phs == 2) weakAcid = !weakAcid;
1681 if(phs == 5) weakBase = !weakBase;
1682
1683 //Check if it is the volume button
1684 if(((e.getY() < 750) && (e.getY() > 600)) && ((e.getX() > 840) && (e.getX() < 1080))) phs = 7;
1685 break;
1686
1687 //Electron Configuration Calculator
1688 case "ct3":
1689
1690 //Locating mouse click
1691 if(e.getY() < 475 && e.getY() >= 225) {
1692
1693 //Select and reset left side
1694 if(e.getX() >= 150 && e.getX() < 470) {
1695 es = 1;
1696 if(symbol.equals("N/A")) symbol = "";
1697 }
1698
1699 //Select and reset right side
1700 else if(e.getX() >= 790 && e.getX() < 1130) {
1701 es = 2;
1702 if(eCount.equals("NaN")) eCount = "0";
1703 }
1704 else es = 0;
1705 }
1706 else es = 0;
1707
1708 //Incrementing or decrementing the electron charge
1709 if(e.getY() >= 515 && e.getY() < 565) {
1710 if(e.getX() >= 200 && e.getX() < 250 && charge != -9) charge--;
1711 if(e.getX() >= 390 && e.getX() < 440 && charge != 9) charge ++;
1712
1713 //Recalculating number of electrons
1714 if(!symbol.equals("N/A") && Arrays.asList(elements).contains(symbol)) eCount = "" + (Arrays.asList(elements).indexOf(symbol) + 1 - charge);
1715 }
1716 break;
1717
1718 //Shape Calculator
1719 case "ct4":
1720
1721 //Incrementing/decrementing the two variables
1722 if(e.getY() >= 400 && e.getY() < 450) {
1723 if(e.getX() >= 200 && e.getX() <250 && items >= 3) {
1724 items--;
1725 if(lones == items - 1) lones--;
1726 }
1727 if(e.getX() >= 390 && e.getX() < 440 && items <= 5) items++;
1728 if(e.getX() >= 840 && e.getX() < 890 && lones >= 1) lones--;
1729 if(e.getX() >= 1030 && e.getX() < 1080 && lones <= (items - 3)) lones++;
1730 }
1731 break;
1732
1733 //PVnRT
1734 case "ct5":
1735
1736 //Selecting
1737 if(e.getY() >= 325 && e.getY() < 475) {
1738 solved = 0;
1739 ps = 0;
1740 for(int i = 960; i >= 0; i -= 320) if(e.getX() >= i) ps++;
1741 }
1742
1743 //Changing units
1744 if(e.getY() >= 600 && e.getY() < 650) {
1745 if(e.getX() >= 40 && e.getX() < 280) {
1746 presUn = (presUn + 1) % 3;
1747 solved = 0;
1748 }
1749 else if(e.getX() >= 360 && e.getX() < 600) {
1750 volUn = (volUn + 1) % 2;
1751 solved = 0;
1752 }
1753 else if(e.getX() >= 1000 && e.getX() < 1240) {
1754 tempUn = (tempUn + 1) % 2;
1755 solved = 0;
1756 }
1757 }
1758
1759 //Calculating
1760 if(e.getY() >= 700 && e.getY() < 750) {
1761 if(e.getX() >= 40 && e.getX() < 280) {
1762 ps = 0;
1763 solved = 1;
1764 pres = PVnRT();
1765 }
1766 else if(e.getX() >= 360 && e.getX() < 600) {
1767 ps = 0;
1768 solved = 2;
1769 vol = PVnRT();
1770 }
1771 else if(e.getX() >= 680 && e.getX() < 920) {
1772 ps = 0;
1773 solved = 3;
1774 mol = PVnRT();
1775 }
1776 else if(e.getX() >= 1000 && e.getX() < 1240) {
1777 ps = 0;
1778 solved = 4;
1779 temp = PVnRT();
1780 if(temp.charAt(0) == '-') {
1781 negTemp = true;
1782 temp = temp.substring(1);
1783 }
1784 }
1785 }
1786 }
1787 }
1788
1789 @Override
1790 public void mousePressed(MouseEvent e) {
1791
1792 }
1793
1794 @Override
1795 public void mouseReleased(MouseEvent e) {
1796
1797 }
1798
1799 @Override
1800 public void mouseEntered(MouseEvent e) {
1801
1802 }
1803
1804 @Override
1805 public void mouseExited(MouseEvent e) {
1806
1807 }
1808}