View Javadoc
1   /******************************************************************************
2    * BFProperties.java - Manage user configuration
3    * $Id$
4    * 
5    * BuckoFIBS - Backgammon by BuckoSoft
6    * Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.
7    * 
8    * $Log$
9    * Revision 1.14  2011/09/23 02:53:26  dick
10   * Default is animate on.
11   *
12   * Revision 1.13  2011/07/21 03:13:35  dick
13   * Need defaults for mWidth.
14   *
15   * Revision 1.12  2011/06/22 05:52:59  dick
16   * Add changeTabOnNewMsg and dontChangeTabOnShout.
17   *
18   * Revision 1.11  2011/06/13 04:39:42  dick
19   * Use Version in a static manner.
20   *
21   * Revision 1.10  2011/05/31 19:34:58  dick
22   * The default server is fibs.com, not buckosoft.com.
23   *
24   * Revision 1.9  2011/05/13 14:18:36  dick
25   * Add animateType and Speed.
26   *
27   * Revision 1.8  2011/05/11 19:15:55  dick
28   * Add AnimateMoves and DEBUGshowAnimatePath.
29   *
30   * Revision 1.7  2011/05/10 05:45:48  dick
31   * Property defaults becomes an array key/values.
32   *
33   * Revision 1.6  2010/12/29 07:43:20  dick
34   * Add rightDieType and highDieLeft.
35   *
36   * Revision 1.5  2010/09/05 04:08:08  dick
37   * Version has to be a instantiated class.
38   *
39   * Revision 1.4  2010/03/03 13:12:21  inim
40   * Replaced (c) sign in comment mangled by CVS default encoding back to UTF-8
41   *
42   * Revision 1.3  2010/03/03 12:19:49  inim
43   * Moved source to UTF8 encoding from CP1252 encoding. To this end all source files' (c) message was updated to "Copyright© 2009,2010 - Dick Balaska - BuckoSoft, Corp.". This replaces the (c) sign to UTF8, and adds the new year 2010.
44   *
45   * Revision 1.2  2010/02/08 09:14:13  dick
46   * Add support for autoGreedyBearoff.  When the game turns to a race, enable greedy bearoffs.
47   *
48   * Revision 1.1  2010/02/04 05:57:53  inim
49   * Mavenized project folder layout
50   *
51   * Revision 1.33  2010/01/29 22:53:40  dick
52   * RatingGraphConfig.
53   *
54   * Revision 1.32  2009/03/12 15:27:34  dick
55   * Javadoc.
56   *
57   * Revision 1.31  2009/02/24 05:20:24  dick
58   * add the Ready, Online, Playing property.
59   *
60   * Revision 1.30  2009/02/22 07:05:17  dick
61   * Save the props to the correct place.
62   *
63   * Revision 1.29  2009/02/21 17:34:33  dick
64   * BuckoFIBS.properties becomes BuckoFIBS.cfg.  *.properties is an hsqldb file and  this causes confusion and delay.
65   *
66   * Revision 1.28  2009/02/14 12:38:13  dick
67   * BuckoFIBS is released under the GNU license.
68   *
69   * Revision 1.27  2009/02/13 07:06:29  dick
70   * Return the correct version in the appSignature.
71   *
72   * Revision 1.26  2009/02/12 06:06:12  dick
73   * Add audioCues property.
74   *
75   * Revision 1.25  2009/02/03 09:43:29  dick
76   * Default server is fibs, not buckosoft.
77   *
78   * Revision 1.24  2009/02/02 08:36:43  dick
79   * Add getAppSignature().
80   *
81   * Revision 1.23  2009/01/28 19:10:37  dick
82   * Add hoverHelpers.
83   *
84   * Revision 1.22  2009/01/18 06:39:20  dick
85   * Javadoc.
86   *
87   * Revision 1.21  2009/01/18 06:37:04  dick
88   * Javadoc.
89   *
90   * Revision 1.20  2009/01/18 06:16:39  dick
91   * Javadoc.
92   *
93   * Revision 1.19  2009/01/18 04:44:50  dick
94   * Add showPointNumbers.
95   * Reduce the code for boolean gets.
96   *
97   * Revision 1.18  2009/01/13 18:27:39  dick
98   * Handle Ready To Play
99   *
100  * Revision 1.17  2009/01/12 20:07:14  dick
101  * Implement FIBSAttributes as part of the new ClientConnection decoupling.
102  *
103  * Revision 1.16  2009/01/10 05:32:08  dick
104  * Nicer default sizes for those without a properties file (jnlp helper).
105  *
106  * Revision 1.15  2009/01/10 05:21:02  dick
107  * Defaults for some messages is ON.
108  *
109  * Revision 1.14  2009/01/09 06:57:12  dick
110  * Add message routing properties.
111  *
112  * Revision 1.13  2009/01/07 19:54:21  dick
113  * Turn off DEBUG.
114  *
115  * Revision 1.12  2009/01/07 08:27:37  dick
116  * Fix the save timer.
117  *
118  * Revision 1.11  2009/01/05 07:07:49  dick
119  * Add support more multiple profiles.
120  *
121  * Revision 1.10  2009/01/04 21:31:08  dick
122  * Add allowMultiplePersonalities
123  *
124  * Revision 1.9  2009/01/04 19:57:01  dick
125  * Default the username and password to blanks, not null.
126  *
127  * Revision 1.8  2008/12/13 06:16:14  dick
128  * Add NotReady and ShowUnhandledCookies.
129  *
130  * Revision 1.7  2008/12/12 23:23:02  dick
131  * Default values for DispXmit and Recv
132  *
133  * Revision 1.6  2008/12/11 09:58:08  dick
134  * ROT13 the password on the disk.  tee hee.
135  *
136  * Revision 1.5  2008/12/11 08:45:36  dick
137  * Add 3 user prefs, autoConnect, dispXmit and dispRecv.
138  *
139  * Revision 1.4  2008/12/07 22:52:48  dick
140  * Wrap the time in a try block.
141  *
142  * Revision 1.3  2008/04/01 03:45:48  dick
143  * Load/save the window location and position and the splitter's positions.
144  *
145  * Revision 1.2  2008/03/31 07:07:15  dick
146  * Save the properties.
147  *
148  * Revision 1.1  2008/03/30 05:39:15  dick
149  * Manage user configuration.
150  */
151 
152 /* 
153  * This program is free software: you can redistribute it and/or modify
154  * it under the terms of the GNU General Public License as published by
155  * the Free Software Foundation, either version 3 of the License, or
156  * (at your option) any later version.
157  *
158  * This program is distributed in the hope that it will be useful,
159  * but WITHOUT ANY WARRANTY; without even the implied warranty of
160  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161  * GNU General Public License for more details.
162  *
163  * You should have received a copy of the GNU General Public License
164  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
165  *
166  * The Original Code is BuckoFIBS, <http://www.buckosoft.com/BuckoFIBS/>.
167  * The Initial Developer of the Original Code is Dick Balaska and BuckoSoft, Corp.
168  * 
169  */
170 package com.buckosoft.fibs.BuckoFIBS;
171 
172 import java.io.File;
173 import java.io.FileInputStream;
174 import java.io.FileOutputStream;
175 import java.util.Properties;
176 import java.util.Timer;
177 import java.util.TimerTask;
178 
179 import com.buckosoft.fibs.domain.config.RatingGraphConfig;
180 import com.buckosoft.fibs.net.FIBSAttributes;
181 
182 /** user configuration with persistence.
183  * The client just gets and sets attributes.  This object ensures persistence on its own. 
184  * @author Dick Balaska
185  * @since 2008/03/30
186  * @version $Revision$ <br> $Date$
187  * @see <a href="http://cvs.buckosoft.com/Projects/BuckoFIBS/BuckoFIBS/src/main/java/com/buckosoft/fibs/BuckoFIBS/BFProperties.java">cvs BFProperties.java</a>
188  */
189 public class BFProperties extends Properties implements FIBSAttributes {
190 	private	final static boolean DEBUG = false;
191 
192 	private static final long serialVersionUID = 1L;
193 	final static String	propFile		= "BuckoFIBS.cfg";
194 
195 	public final static int RIGHT_DIE_PLAYS = 0;
196 	public final static int RIGHT_DIE_SWAPS = 1;
197 
198 	final static String	s_selectedProfile	= "selectedProfile";
199 	final static String s_profileName		= "profileName";
200 	final static String s_userName			= "userName";
201 	final static String s_password			= "password";
202 	final static String s_serverName		= "serverName";
203 	final static String	s_serverPort		= "serverPort";
204 	
205 	final static String s_mHeight			= "mainHeight";
206 	final static String s_mWidth			= "mainWidth";
207 	final static String s_mX				= "mainX";
208 	final static String s_mY				= "mainY";
209 	final static String s_mTopBottomSplit	= "mainTBSplit";
210 	final static String s_mTopLRSplit		= "mainTLRSplit";
211 	final static String s_mBotLRSplit		= "mainBLRSplit";
212 	final static String s_showPointNumbers	= "showPointNumbers";
213 	final static String s_autoConnect		= "autoConnect";
214 	final static String s_dispXmit			= "displayXmit";
215 	final static String s_dispRecv			= "displayRecv";
216 	final static String	s_allowMultiPerson	= "multiplePerson";
217 	final static String	s_hoverHelpers		= "hoverHelpers";
218 	final static String	s_audioCues			= "audioCues";
219 	final static String s_ratingGraphType	= "ratingGraphType";
220 	final static String s_ratingGraphAmt	= "ratingGraphAmt";
221 
222 	final static String s_msgIgnoreShouts	= "msgIgnoreShouts";
223 	final static String s_msgShowGameMoves	= "msgShowGameMoves";
224 	final static String s_msgOtherMatchInfo	= "msgOtherMatchInfo";
225 	final static String s_msgLoginsAndOuts	= "msgLoginsAndOuts";
226 	final static String s_fibsReadyToPlay	= "fibsReadyToPlay";
227 	final static String s_rop				= "rop";
228 	final static String s_autoGreedyBearOff	= "autoGreedyBearOff";
229 	final static String	s_animateMoves		= "animateMoves";
230 	final static String	s_animateType		= "animateType";
231 	final static String	s_animateSpeed		= "animateSpeed";
232 	final static String	s_changeTabOnNewMsg	= "changeTabOnMessage";
233 	final static String s_dontChangeTabOnShout = "dontChangeTabOnShout";
234 	
235 	final static String s_rightDieType		= "rightDieType";
236 	final static String s_highDieLeft		= "highDieLeft";
237 
238 	final static String s_DEBUG_NotReady	= "NotReady";
239 	final static String s_DEBUG_ShowUnhandledCookies = "ShowUnhandledCookies";
240 	final static String s_DEBUG_StdoutNetworkMessages = "stdoutNetMessages";
241 	final static String s_DEBUG_ShowAnimatePath = "showAnimatePath";
242 
243 
244 	/** If there are no props saved, then this is our first time running BuckoFIBS */
245 	private  boolean newbie = false;
246 
247 	private	RatingGraphConfig	ratingGraphConfig = new RatingGraphConfig();
248 	
249 	private class BFProp {
250 		String	key;
251 		String	value;
252 		BFProp(String key, String value) {
253 
254 			this.key = key;
255 			this.value = value;
256 		}
257 	}
258 	private BFProp[] bfProps = {
259 		new BFProp(s_selectedProfile, "0"),
260 		new BFProp(s_serverName + 0, "fibs.com"),
261 //		new BFProp(s_serverName + 0, "localhost"),
262 		new BFProp(s_serverPort + 0, "4321"),
263 		new BFProp(s_userName + 0, ""),
264 		new BFProp(s_password + 0, ""),
265 		new BFProp(s_mWidth, "1000"),
266 		new BFProp(s_mHeight, "846"),
267 		new BFProp(s_mX, "10"),
268 		new BFProp(s_mY, "10"),
269 		new BFProp(s_mTopBottomSplit, "482"),
270 		new BFProp(s_mTopLRSplit, "532"),
271 		new BFProp(s_mBotLRSplit, "123"),
272 		new BFProp(s_autoConnect, "0"),
273 		new BFProp(s_autoGreedyBearOff, "1"),
274 		new BFProp(s_rightDieType, "" + RIGHT_DIE_PLAYS),
275 		new BFProp(s_highDieLeft, "1"),
276 		new BFProp(s_showPointNumbers, "1"),
277 		new BFProp(s_dispXmit, "0"),
278 		new BFProp(s_dispRecv, "0"),
279 		new BFProp(s_allowMultiPerson, "0"),
280 		new BFProp(s_hoverHelpers, "1"),
281 		new BFProp(s_audioCues, "1"),
282 		new BFProp(s_rop, "111"),
283 		new BFProp(s_ratingGraphType, "0"),
284 		new BFProp(s_ratingGraphAmt, "50"),
285 		new BFProp(s_msgIgnoreShouts, "0"),
286 		new BFProp(s_msgShowGameMoves, "1"),
287 		new BFProp(s_msgOtherMatchInfo, "1"),
288 		new BFProp(s_msgLoginsAndOuts, "1"),
289 		new BFProp(s_fibsReadyToPlay, "1"),
290 		new BFProp(s_animateMoves, "1"),
291 		new BFProp(s_animateType, "1"),
292 		new BFProp(s_animateSpeed, "2.0"),
293 		new BFProp(s_changeTabOnNewMsg, "1"),
294 		new BFProp(s_dontChangeTabOnShout, "1"),
295 		new BFProp(s_DEBUG_NotReady, "0"),
296 		new BFProp(s_DEBUG_ShowUnhandledCookies, "0"),
297 		new BFProp(s_DEBUG_StdoutNetworkMessages, "0"),
298 		new BFProp(s_DEBUG_ShowAnimatePath, "0"),
299 	};
300 
301 	/** constructor for TEST
302 	 * @param TEST true for test mode
303 	 */
304 	public BFProperties(boolean TEST) {
305 		_BFProperties(null);
306 		
307 	}
308 	/** Create a new BFProperties. <br>
309 	 * File reading and parsing is done in this constructor.
310 	 */
311 	public BFProperties() {
312 		_BFProperties(System.getProperty("user.home") 
313 		    		+ File.separator + "BuckoFIBS" + File.separator + propFile);
314 	}
315 	
316 	private void _BFProperties(String filename) {
317 		try {
318 		    FileInputStream fip = new FileInputStream(filename);
319 		    load(fip);
320 		}
321 		catch (Exception e) {
322 		    System.out.println("Exception while loading props:" + e);
323 		    newbie = true;
324 		}
325 		
326 		for (BFProp bfProp : bfProps) {
327 			if (getProperty(bfProp.key) == null)
328 				setProperty(bfProp.key, bfProp.value);
329 		}
330 	}
331 
332 	private	Timer	myTimer = null;
333 	private	TimerTask	myTimerTask = new MyTimerTask(this);
334 	private	void	propsChanged() {
335 		if (myTimer != null) {
336 			return;
337 		}
338 		myTimer = new Timer();
339 		try {
340 			myTimerTask = new MyTimerTask(this);
341 			myTimer.schedule(myTimerTask, 1000);
342 		} catch (IllegalStateException e) {
343 			e.printStackTrace();
344 		}
345 	}
346 
347 	private class MyTimerTask extends TimerTask {
348 		private	BFProperties props;
349 
350 		MyTimerTask(BFProperties props) {
351 			super();
352 			this.props = props;
353 		}
354 		/* (non-Javadoc)
355 		 * @see java.util.TimerTask#run()
356 		 */
357 		@Override
358 		public void run() {
359 			this.props.save();
360 			this.props.myTimer.cancel();
361 			this.props.myTimer = null;
362 		}
363 	}
364 	
365 	/* (non-Javadoc)
366 	 * @see com.buckosoft.fibs.net.FIBSAttributes#getAppSignature()
367 	 */
368 	@Override
369 	public String getAppSignature() {
370 		return("BuckoFIBS-" + Version.getVersion());
371 	}
372 
373 	/** Is this user a newbie?
374 	 * @return the newbie
375 	 */
376 	public boolean isNewbie() {
377 		return newbie;
378 	}
379 
380 	/** Get the id of the currently selected profile.
381 	 * @return The selected profile id
382 	 */
383 	public int getSelectedProfile() {
384 		return(Integer.parseInt(getProperty(s_selectedProfile)));
385 	}
386 
387 	/** Set the id of the currently selected profile.
388 	 * @param profileId The id of the profile that the user selected.
389 	 */
390 	public void setSelectedProfile(int profileId) {
391 		if (getSelectedProfile() != profileId)
392 			propsChanged();
393 		setProperty(s_selectedProfile, "" + profileId);
394 	}
395 
396 	/** Get the number of profiles that we are keeping track of
397 	 * @return The number of profiles
398 	 */
399 	public int getProfileCount() {
400 		int profileCount = 0;
401 		while (true) {
402 			if (getProperty(s_profileName + profileCount) == null)
403 				return(profileCount);
404 			profileCount++;
405 		}
406 	}
407 
408 	/** Get the name of this profile (not neccessarily the login name)
409 	 * @param profileId The profile to query
410 	 * @return The name of the profile
411 	 */ 
412 	public String	getProfileName(int profileId) {
413 		return(getProperty(s_profileName + profileId));
414 	}
415 
416 	/** Set the name of this profile (not neccessarily the login name)
417 	 * @param profileId The profile to set
418 	 * @param s The name of the profile
419 	 */
420 	public void setProfileName(int profileId, String s) {
421 		if (!s.equals(getProfileName(profileId)))
422 			propsChanged();
423 		setProperty(s_profileName + profileId, s);
424 	}
425 
426 	/** Get the user's login name for the currently selected profile.
427 	 * @return The user name
428 	 */
429 	public String getUserName() {
430 		return(this.getUserName(this.getSelectedProfile()));
431 	}
432 
433 	/** Get the user's login name for this profile
434 	 * @param profileId The profile id to query
435 	 * @return The user name or an empty string if not found.
436 	 */ 
437 	public String	getUserName(int profileId) {
438 		String s = getProperty(s_userName + profileId);
439 		if (s == null)
440 			s = "";
441 		return(s);
442 	}
443 	
444 	/** Set the user's login name for this profile.
445 	 * @param profileId The profile id to query.
446 	 * @param s The username
447 	 */ 
448 	public void setUserName(int profileId, String s) {
449 		if (!s.equals(getUserName(profileId)))
450 			propsChanged();
451 		setProperty(s_userName + profileId, s);
452 	}
453 
454 	/** Get the clear text password of the user in the currently selected profile
455 	 * @return The password
456 	 */
457 	public String getUserPassword() {
458 		return(this.getPassword(this.getSelectedProfile()));
459 	}
460 
461 	/** Get the clear text password of the user in this profile.
462 	 * @param profileId The profile id to query.
463 	 * @return The password
464 	 */
465 	public String	getPassword(int profileId) {
466 		String t = getProperty(s_password + profileId);
467 		if (t == null)
468 			return("");
469 		t = ROT13.doConvert(t);
470 		
471 		if (DEBUG)
472 			System.out.println("get password = " + t);
473 		return(t);
474 	}
475 	
476 	/** Set the clear text password of the user for this profile.
477 	 * @param profileId The profile id to query.
478 	 * @param s The clear text password
479 	 */
480 	public void setPassword(int profileId, String s) {
481 		if (!s.equals(getPassword(profileId)))
482 			propsChanged();
483 		String t = ROT13.doConvert(s);
484 		setProperty(s_password + profileId, t);
485 		if (DEBUG)
486 			System.out.println("set password = " + getProperty(s_password));
487 	}
488 
489 	/** Get the name of the server to connect to for the currently selected profile
490 	 * @return The server name 
491 	 */
492 	public String getServerName() {
493 		return(this.getServerName(this.getSelectedProfile()));
494 	}
495 
496 	/** get the name of the server we connect to
497 	 * @return The name of the server
498 	 */
499 	public String	getServerName(int profileId) {
500 		String s = getProperty(s_serverName + profileId);
501 		if (s == null)
502 			s = "fibs.com";
503 		return(s);
504 	}
505 
506 	/** Set the name of the server that we connect to in this profile
507 	 * @param profileId The profile id to set
508 	 * @param s The server name.
509 	 */
510 	public void setServerName(int profileId, String s) {
511 		if (!s.equals(getServerName(profileId)))
512 			propsChanged();
513 		setProperty(s_serverName + profileId, s);
514 	}
515 
516 	/** Get the IP port number to connect to for the currently selected profile.
517 	 * @return The port (typically 4321)
518 	 */
519 	public int getServerPort() {
520 		return(this.getServerPort(this.getSelectedProfile()));
521 	}
522 
523 	/** Get the IP port number to connect to for this profile
524 	 * @param profileId The profile id to query
525 	 * @return The port (typically 4321)
526 	 */ 
527 	public int getServerPort(int profileId) {
528 		String s = getProperty(s_serverPort + profileId);
529 		if (s == null)
530 			return(4321);
531 		return(Integer.parseInt(s));
532 	}
533 	
534 	/** Set the IP port number to connect to for this profile
535 	 * @param profileId The profile id to query
536 	 * @param port The port number (if it's not 4321, then uh oh)
537 	 */
538 	public void setServerPort(int profileId, int port) {
539 		if (port != getServerPort(profileId))
540 			propsChanged();
541 		setProperty(s_serverPort + profileId, new Integer(port).toString());
542 	}
543 
544 	/** Get the width for the MainDialog
545 	 * @return The width in pixels
546 	 */
547 	public int		getMainWidth() {
548 		String s = getProperty(s_mWidth);
549 		return(Integer.parseInt(s));
550 	}
551 	
552 	/** Set the width of the MainDialog
553 	 * @param width The width in pixels
554 	 */
555 	public void setMainWidth(int width) {
556 		if (width != getMainWidth())
557 			propsChanged();
558 		setProperty(s_mWidth, new Integer(width).toString());
559 	}
560 
561 	public int getRightDieType() {
562 		String s = getProperty(s_rightDieType);
563 		return(Integer.parseInt(s));
564 	}
565 	
566 	public void setRightDieType(int rightDieType) {
567 		if (rightDieType != getRightDieType())
568 			propsChanged();
569 		setProperty(s_rightDieType, "" + rightDieType);
570 	}
571 
572 	public boolean isHighDieLeft() {
573 		String s = getProperty(s_highDieLeft);
574 		return(Integer.parseInt(s) == 1 ? true : false);
575 	}
576 	
577 	public void setHighDieLeft(boolean highDieLeft) {
578 		if (highDieLeft != isHighDieLeft())
579 			propsChanged();
580 		setProperty(s_highDieLeft, highDieLeft ? "1" : "0");
581 	}
582 
583 	/** Get the height for the MainDialog
584 	 * @return The height in pixels
585 	 */
586 	public int		getMainHeight() {
587 		String s = getProperty(s_mHeight);
588 		return(Integer.parseInt(s));
589 	}
590 
591 	/** Set the height for the MainDialog
592 	 * @param height The height in pixels.
593 	 */ 
594 	public void setMainHeight(int height) {
595 		if (height != getMainHeight())
596 			propsChanged();
597 		setProperty(s_mHeight, new Integer(height).toString());
598 	}
599 
600 	/** Get the X position for the MainDialog. <br>
601 	 * This is where to place the dialog on the screen during creation
602 	 * @return The X position
603 	 */
604 	public int		getMainX() {
605 		String s = getProperty(s_mX);
606 		return(Integer.parseInt(s));
607 	}
608 	
609 	/** Set the X position of the MainDialog on the screen.
610 	 * @param x The X position
611 	 */
612 	public void setMainX(int x) {
613 		if (x != getMainX())
614 			propsChanged();
615 		setProperty(s_mX, new Integer(x).toString());
616 	}
617 
618 	/** Get the Y position for the MainDialog. <br>
619 	 * This is where to place the dialog on the screen during creation
620 	 * @return The Y position
621 	 */
622 	public int		getMainY() {
623 		String s = getProperty(s_mY);
624 		return(Integer.parseInt(s));
625 	}
626 
627 	/** Set the Y position of the MainDialog on the screen.
628 	 * @param y The Y position
629 	 */
630 	public void setMainY(int y) {
631 		if (y != getMainY())
632 			propsChanged();
633 		setProperty(s_mY, new Integer(y).toString());
634 	}
635 
636 	/** Get the position of the split for the main top/bottom split in the MainDialog
637 	 * @return The position to set the splitter at.
638 	 */ 
639 	public int		getMainTopBottomSplit() {
640 		String s = getProperty(s_mTopBottomSplit);
641 		return(Integer.parseInt(s));
642 	}
643 
644 	/** Set the position of the split for the main top/bottom split in the MainDialog
645 	 * @param sp The position to set the splitter at.
646 	 */ 
647 	public void setMainTopBottomSplit(int sp) {
648 		if (sp != getMainTopBottomSplit())
649 			propsChanged();
650 		setProperty(s_mTopBottomSplit, new Integer(sp).toString());
651 	}
652 
653 	/** Get the position of the Left/Right split in the top half of the MainDialog
654 	 * @return The position of the split
655 	 */ 
656 	public int		getMainTopLRSplit() {
657 		String s = getProperty(s_mTopLRSplit);
658 		return(Integer.parseInt(s));
659 	}
660 
661 	/** Set the position of the Left/Right split in the top half of the MainDialog
662 	 * @param sp The position of the split
663 	 */ 
664 	public void setMainTopLRSplit(int sp) {
665 		if (sp != getMainTopLRSplit())
666 			propsChanged();
667 		setProperty(s_mTopLRSplit, new Integer(sp).toString());
668 	}
669 	
670 	/** Get the position of the Left/Right split in the bottom half of the MainDialog
671 	 * @return The position of the split
672 	 */ 
673 	public int		getMainBotLRSplit() {
674 		String s = getProperty(s_mBotLRSplit);
675 		return(Integer.parseInt(s));
676 	}
677 
678 	/** Set the position of the Left/Right split in the bottom half of the MainDialog
679 	 * @param sp The position of the split
680 	 */ 
681 	public void setMainBotLRSplit(int sp) {
682 		if (sp != getMainBotLRSplit())
683 			propsChanged();
684 		setProperty(s_mBotLRSplit, new Integer(sp).toString());
685 	}
686 	
687 	/** Should we display the numbers on the points on the board?
688 	 * @return true == yes
689 	 */
690 	public boolean isShowPointNumbers() {
691 		String s = getProperty(s_showPointNumbers);
692 		return(s.equals("1"));
693 	}
694 	
695 	/** Set whether to display the numbers on the points on the board.
696 	 * @param b true == yes
697 	 */
698 	public void setShowPointNumbers(boolean b) {
699 		if (b != isShowPointNumbers())
700 			propsChanged();
701 		setProperty(s_showPointNumbers, b ? "1" : "0");
702 	}
703 
704 	/** Should we automatically connect to the server when the app starts up?
705 	 * @return true == yes
706 	 */
707 	public boolean isAutoConnect() {
708 		String s = getProperty(s_autoConnect);
709 		return(s.equals("1"));
710 	}
711 	
712 	/** Set the auto connect value
713 	 * @param b true == yes
714 	 */
715 	public void setAutoConnect(boolean b) {
716 		if (b != isAutoConnect())
717 			propsChanged();
718 		setProperty(s_autoConnect, b ? "1" : "0");
719 	}
720 
721 	/** Should we automatically turn on Greedy Bear Offs when the game turns to a race?
722 	 * @return true == yes
723 	 */
724 	public boolean isAutoGreedyBearOff() {
725 		String s = getProperty(s_autoGreedyBearOff);
726 		return(s.equals("1"));
727 	}
728 	
729 	/** Set the auto Greedy Bear Off
730 	 * @param b true == yes
731 	 */
732 	public void setAutoGreedyBearOff(boolean b) {
733 		if (b != isAutoGreedyBearOff())
734 			propsChanged();
735 		setProperty(s_autoGreedyBearOff, b ? "1" : "0");
736 	}
737 
738 	/** Should we display messages that we transmit to the fibs server?
739 	 * @return true == display them
740 	 */
741 	public boolean isDisplayXmit() {
742 		String s = getProperty(s_dispXmit);
743 		return(s.equals("1"));
744 	}
745 
746 	/** Set whether to display messages that we transmit to the fibs server.
747 	 * @param b true == display them
748 	 */
749 	public void setDisplayXmit(boolean b) {
750 		if (b != isDisplayXmit())
751 			propsChanged();
752 		setProperty(s_dispXmit, b ? "1" : "0");
753 	}
754 
755 	/** Should we display messages that we transmit to the fibs server?
756 	 * @return true == display them
757 	 */
758 	public boolean isAnimateMoves() {
759 		String s = getProperty(s_animateMoves);
760 		return(s.equals("1"));
761 	}
762 
763 	/** Set whether to display messages that we transmit to the fibs server.
764 	 * @param b true == display them
765 	 */
766 	public void setAnimateMoves(boolean b) {
767 		if (b != isAnimateMoves())
768 			propsChanged();
769 		setProperty(s_animateMoves, b ? "1" : "0");
770 	}
771 
772 	public int	getAnimateType() {
773 		String s = getProperty(s_animateType);
774 		return(Integer.parseInt(s));		
775 	}
776 
777 	public void setAnimateType(int type) {
778 		if (type != getAnimateType())
779 			propsChanged();
780 		setProperty(s_animateType, new Integer(type).toString());
781 	}
782 
783 	public double	getAnimateSpeed() {
784 		String s = getProperty(s_animateSpeed);
785 		return(Double.parseDouble(s));		
786 	}
787 
788 	public void setAnimateSpeed(double speed) {
789 		if (speed != getAnimateSpeed())
790 			propsChanged();
791 		setProperty(s_animateSpeed, new Double(speed).toString());
792 	}
793 
794 
795 	/** OBSOLETE::
796 	 * @return OBSOLETE
797 	 */
798 	public boolean isDisplayRecv() {
799 		String s = getProperty(s_dispRecv);
800 		return(s.equals("1"));
801 	}
802 
803 	/** OBSOLETE:
804 	 * @param b
805 	 */
806 	public void setDisplayRecv(boolean b) {
807 		if (b != isDisplayRecv())
808 			propsChanged();
809 		setProperty(s_dispRecv, b ? "1" : "0");
810 	}
811 
812 	/** Should we display received network messages on stdout?
813 	 * @return true == yes
814 	 */ 
815 	public boolean isStdoutNetworkMessages() {
816 		String s = getProperty(s_DEBUG_StdoutNetworkMessages);
817 		return(s.equals("1"));
818 	}
819 
820 	/** Set whether to display received network messages on stdout.
821 	 * @param b true == display 'em
822 	 */
823 	public void setStdoutNetworkMessages(boolean b) {
824 		if (b != isStdoutNetworkMessages())
825 			propsChanged();
826 		setProperty(s_DEBUG_StdoutNetworkMessages, b ? "1" : "0");
827 	}
828 
829 	/** Should we allow the user to have multiple personalities?
830 	 * The default is no, this is really only a development feature so that i
831 	 * can connect to fibs.com or buckosoft.com
832 	 * @return true == yes
833 	 */
834 	public boolean isAllowMultiplePersonalities() {
835 		String s = getProperty(s_allowMultiPerson);
836 		return(s.equals("1"));
837 	}
838 
839 	/** Set the value for allow multiple personalities
840 	 * @param b true == yes
841 	 */
842 	public void setAllowMultiplePersonalities(boolean b) {
843 		if (b != isAllowMultiplePersonalities())
844 			propsChanged();
845 		setProperty(s_allowMultiPerson, b ? "1" : "0");
846 	}
847 
848 	/** Should we show the hover helpers during a player's move
849 	 * The default is yes, max eye candy is on.
850 	 * @return true == yes
851 	 */
852 	public boolean isHoverHelpers() {
853 		String s = getProperty(s_hoverHelpers);
854 		return(s.equals("1"));
855 	}
856 
857 	/** Should we show the hover helpers during a player's move
858 	 * @param b true == yes
859 	 */
860 	public void setHoverHelpers(boolean b) {
861 		if (b != isHoverHelpers())
862 			propsChanged();
863 		setProperty(s_hoverHelpers, b ? "1" : "0");
864 	}
865 
866 	/** Should we play the beeps and boops?
867 	 * @return true = make noise
868 	 */
869 	public boolean isAudioCues() {
870 		String s = getProperty(s_audioCues);
871 		return(s.equals("1"));		
872 	}
873 
874 	/** Set whether to play the audio cues
875 	 * @param b false = don't make noise
876 	 */
877 	public void setAudioCues(boolean b) {
878 		if (b != isAudioCues())
879 			propsChanged();
880 		setProperty(s_audioCues, b ? "1" : "0");
881 	}
882 
883 	/** Should we ignore people shouting? (global chat messages)
884 	 * @return true == ignore them
885 	 */
886 	public boolean isMsgIgnoreShouts() {
887 		String s = getProperty(s_msgIgnoreShouts);
888 		return(s.equals("1"));
889 	}
890 	
891 	/** Set whether to ignore shouts or not
892 	 * @param b true == ignore them
893 	 */
894 	public void setMsgIgnoreShouts(boolean b) {
895 		if (b != isMsgIgnoreShouts())
896 			propsChanged();
897 		setProperty(s_msgIgnoreShouts, b ? "1" : "0");
898 	}
899 
900 	/** Should we display game move messages (in its own window)
901 	 * @return true == yup
902 	 */
903 	public boolean isMsgShowGameMoves() {
904 		String s = getProperty(s_msgShowGameMoves);
905 		return(s.equals("1"));
906 	}
907 
908 	/** Set whether to display game move messages
909 	 * @param b true == display them
910 	 */
911 	public void setMsgShowGameMoves(boolean b) {
912 		if (b != isMsgShowGameMoves())
913 			propsChanged();
914 		setProperty(s_msgShowGameMoves, b ? "1" : "0");
915 	}
916 
917 	/** Should we display messages about other matches?
918 	 * @return true == display them
919 	 */
920 	public boolean isMsgOtherMatchInfo() {
921 		String s = getProperty(s_msgOtherMatchInfo);
922 		return(s.equals("1"));
923 	}
924 	
925 	/** Set whether to display messages about other messages
926 	 * @param b true == display them
927 	 */
928 	public void setMsgOtherMatchInfo(boolean b) {
929 		if (b != isMsgOtherMatchInfo())
930 			propsChanged();
931 		setProperty(s_msgOtherMatchInfo, b ? "1" : "0");
932 	}
933 
934 	/** Should we switch to the tab that just received a chat message?
935 	 * @return true == yup
936 	 */
937 	public boolean isChangeTabOnNewMsg() {
938 		String s = getProperty(s_changeTabOnNewMsg);
939 		return(s.equals("1"));
940 	}
941 
942 	/** Set whether to switch to the tab that just received a chat message
943 	 * @param b true == display them
944 	 */
945 	public void setChangeTabOnNewMsg(boolean b) {
946 		if (b != isChangeTabOnNewMsg())
947 			propsChanged();
948 		setProperty(s_changeTabOnNewMsg, b ? "1" : "0");
949 	}
950 
951 	/** Should we switch to the tab that just received a chat message?
952 	 * @return true == yup
953 	 */
954 	public boolean isDontChangeTabOnShout() {
955 		String s = getProperty(s_dontChangeTabOnShout);
956 		return(s.equals("1"));
957 	}
958 
959 	/** Set whether to switch to the tab that just received a chat message
960 	 * @param b true == display them
961 	 */
962 	public void setDontChangeTabOnShout(boolean b) {
963 		if (b != isDontChangeTabOnShout())
964 			propsChanged();
965 		setProperty(s_dontChangeTabOnShout, b ? "1" : "0");
966 	}
967 
968 	/** Should we display messages about other people logging in and out?
969 	 * @return true == display them
970 	 */
971 	public boolean isMsgLoginsAndOuts() {
972 		String s = getProperty(s_msgLoginsAndOuts);
973 		return(s.equals("1"));
974 	}
975 	
976 	/** Set whether to display messages about other people logging in and out
977 	 * @param b true == display them
978 	 */
979 	public void setMsgLoginsAndOuts(boolean b) {
980 		if (b != isMsgLoginsAndOuts())
981 			propsChanged();
982 		setProperty(s_msgLoginsAndOuts, b ? "1" : "0");
983 	}
984 
985 	/** Has the user marked himself as ready to play?
986 	 * @return true == ja
987 	 */
988 	public boolean isFibsReadyToPlay() {
989 		String s = getProperty(s_fibsReadyToPlay);
990 		return(s.equals("1"));
991 	}
992 	
993 	/** Set whether we are ready to play
994 	 * @param b true == yes
995 	 */
996 	public void setFibsReadyToPlay(boolean b) {
997 		if (b != isFibsReadyToPlay())
998 			propsChanged();
999 		setProperty(s_fibsReadyToPlay, b ? "1" : "0");
1000 	}
1001 
1002 	/** Set the state of the Ready, Online, Playing triad.
1003 	 * @param rop rop[0] = the Ready state, rop[1] = the Online state, rop[2] = the Playing state.
1004 	 */
1005 	public void setROP(boolean[] rop) {
1006 		if (rop != getROP())
1007 			propsChanged();
1008 		String s = (rop[0] ? "1" : "0")
1009 				 + (rop[1] ? "1" : "0")
1010 				 + (rop[2] ? "1" : "0");
1011 		setProperty(s_rop, s);
1012 		
1013 	}
1014 	
1015 	/** Get the state of the Ready, Online, Playing triad.
1016 	 * @return b[0] = the Ready state, b[1] = the Online state, b[2] = the Playing state.
1017 	 */
1018 	public boolean[] getROP() {
1019 		boolean[] b = new boolean[3];
1020 		String s = getProperty(s_rop);
1021 		b[0] = s.charAt(0) == '1' ? true : false;
1022 		b[1] = s.charAt(1) == '1' ? true : false;
1023 		b[2] = s.charAt(2) == '1' ? true : false;
1024 		return(b);
1025 	}
1026 
1027 	public RatingGraphConfig	getRatingGraphConfig() {
1028 		String s = getProperty(s_ratingGraphType);
1029 		ratingGraphConfig.setTypeAsInt(Integer.parseInt(s));
1030 		s = getProperty(s_ratingGraphAmt);
1031 		ratingGraphConfig.setMatchCount(Integer.parseInt(s));
1032 		return(ratingGraphConfig);
1033 	}
1034 
1035 	public void setRatingGraphConfig(RatingGraphConfig ratingGraphConfig) {
1036 		this.ratingGraphConfig = ratingGraphConfig;
1037 		setProperty(s_ratingGraphType, "" + this.ratingGraphConfig.getTypeAsInt());
1038 		setProperty(s_ratingGraphAmt, "" + this.ratingGraphConfig.getMatchCount());		
1039 		propsChanged();
1040 	}
1041 
1042 	/** Should we display unhandled cookies as an error?
1043 	 * @return true == yes
1044 	 */
1045 	public boolean isDEBUG_ShowUnhandledCookies() {
1046 		String s = getProperty(s_DEBUG_ShowUnhandledCookies);
1047 		return(s.equals("1"));
1048 	}
1049 
1050 	/** Set whether we should display unhandled cookies
1051 	 * @param b true == oui
1052 	 */
1053 	public void setDEBUG_ShowUnhandledCookies(boolean b) {
1054 		if (b != isDEBUG_ShowUnhandledCookies())
1055 			propsChanged();
1056 		setProperty(s_DEBUG_ShowUnhandledCookies, b ? "1" : "0");
1057 	}
1058 
1059 	/** Should we display a line showing the path the checker will animate along?
1060 	 * @return true == yes
1061 	 */
1062 	public boolean isDEBUG_ShowAnimatePath() {
1063 		String s = getProperty(s_DEBUG_ShowAnimatePath);
1064 		return(s.equals("1"));
1065 	}
1066 
1067 	/** Set whether we should display a line showing the path the checker will animate along
1068 	 * @param b true == oui
1069 	 */
1070 	public void setDEBUG_ShowAnimatePath(boolean b) {
1071 		if (b != isDEBUG_ShowAnimatePath())
1072 			propsChanged();
1073 		setProperty(s_DEBUG_ShowAnimatePath, b ? "1" : "0");
1074 	}
1075 
1076 	///////////////////////////////////////////////////////////////////////////
1077 	static class ROT13 {
1078 
1079 	    static private int abyte = 0;
1080 
1081 	    public static String doConvert(String in) {
1082 
1083 	        StringBuffer tempReturn = new StringBuffer();
1084 
1085 
1086 	        for (int i=0; i<in.length(); i++) {
1087 
1088 	            abyte = in.charAt(i);
1089 	            int cap = abyte & 32;
1090 	            abyte &= ~cap;
1091 	            abyte = ( (abyte >= 'A') && (abyte <= 'Z') ? ((abyte - 'A' + 13) % 26 + 'A') : abyte) | cap;
1092 	            tempReturn.append((char)abyte);
1093 	        }
1094 	        return tempReturn.toString();
1095 	        
1096 	    }
1097 	}
1098 	
1099 	/** Save the properties file
1100 	 */
1101 	private void save() {
1102 		if (DEBUG)
1103 			System.out.println("Saving properties");
1104 		try {
1105 			FileOutputStream fos = new FileOutputStream(System.getProperty("user.home")
1106 					+ File.separator + "BuckoFIBS" + File.separator + propFile);
1107 			store(fos, "BuckoFIBS properties");
1108 		} catch (Exception e) {
1109 			System.out.println("Exception while saving props:" + e);
1110 		}
1111 	}
1112 
1113 
1114 }