1 /**
2  * The freechess.org connection library.
3  * More information is available at http://www.jinchess.com/.
4  * Copyright (C) 2002 Alexander Maryanovsky.
5  * All rights reserved.
6  *
7  * The freechess.org connection library is free software; you can redistribute
8  * it and/or modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * The freechess.org connection library is distributed in the hope that it will
13  * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with the freechess.org connection library; if not, write to the Free
19  * Software Foundation, Inc.,
20  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 package free.freechess;
24 
25 import free.util.Struct;
26 import java.util.StringTokenizer;
27 
28 
29 /**
30  * A structure holding parsed information from a seekinfo line. More information
31  * about the format is available in the "help iv_seekinfo" file on the Free
32  * Internet Chess Server (http://www.freechess.org).
33  */
34 
35 public class SeekInfoStruct extends Struct{
36 
37 
38 
39   /**
40    * The bit mask for an unregistered player.
41    */
42 
43   public static final int UNREGISTERED = 0x1;
44 
45 
46 
47 
48   /**
49    * The bit mask for a computer player.
50    */
51 
52   public static final int COMPUTER = 0x2;
53 
54 
55 
56 
57   /**
58    * The bit mask for a GM.
59    */
60 
61   public static final int GM = 0x4;
62 
63 
64 
65 
66   /**
67    * The bit mask for an IM.
68    */
69 
70   public static final int IM = 0x8;
71 
72 
73 
74 
75   /**
76    * The bit mask for an FM.
77    */
78 
79   public static final int FM = 0x10;
80 
81 
82 
83 
84   /**
85    * The bit mask for a WGM.
86    */
87 
88   public static final int WGM = 0x20;
89 
90 
91 
92 
93   /**
94    * The bit mask for a WIM.
95    */
96 
97   public static final int WIM = 0x40;
98 
99 
100 
101 
102   /**
103    * The bit mask for a WFM.
104    */
105 
106   public static final int WFM = 0x80;
107 
108 
109 
110 
111   /**
112    * Creates a new SeekInfoStruct with the specified arguments.
113    *
114    * @param canAcceptSeek <code>true</code> if the user can accept the seek,
115    * <code>false</code> otherwise.
116    * @param index The seek index.
117    * @param name The handle of the seeking player.
118    * @param titles The titles of the player, ORed into an int.
119    * @param rating The rating of the player.
120    * @param provShow The seeker's rating provshow character, 'E' is estimated,
121    * 'P' if provisional and ' ' if neither.
122    * @param time The time of the sought game, in minutes.
123    * @param inc The increment of the sought game, in seconds.
124    * @param isRated The ratedness of the sought game.
125    * @param matchType The type of the match (either variant or rating type -
126    * "suicide", "lightning", "blitz" etc.).
127    * @param color The requested color. 'W' if white, 'B' if black and '?' if
128    * doesn't care.
129    * @param minRating The minimum rating of the sought opponent.
130    * @param maxRating The maximum rating of the sought opponent.
131    * @param isAutomaticAccept <code>true</code> if the acceptance of the seek is
132    * automatic, <code>false</code> if manual.
133    * @param isFormulaUsed <code>true</code> if the you must pass the seeker's
134    * formula to accept the offer.
135    */
136 
SeekInfoStruct(boolean canAcceptSeek, int index, String name, int titles, int rating, char provshow, int time, int inc, boolean isRated, String matchType, char color, int minRating, int maxRating, boolean isAutomaticAccept, boolean isFormulaUsed)137   public SeekInfoStruct(boolean canAcceptSeek, int index, String name, int titles, int rating,
138       char provshow, int time, int inc, boolean isRated, String matchType, char color,
139       int minRating, int maxRating, boolean isAutomaticAccept, boolean isFormulaUsed){
140 
141     if (time < 0)
142       throw new IllegalArgumentException("The game's initial time ("+time+") may not be negative");
143 
144     if (inc < 0)
145       throw new IllegalArgumentException("The game's increment ("+inc+") may not be negative");
146 
147     switch (color){
148       case '?':
149       case 'W':
150       case 'B':
151         break;
152       default:
153         throw new IllegalArgumentException("Bad color character: "+color);
154     }
155 
156     setBooleanProperty("CanAcceptSeek", canAcceptSeek);
157     setIntegerProperty("Index", index);
158     setStringProperty("Name", name);
159     setIntegerProperty("Titles", titles);
160     setIntegerProperty("Rating", rating);
161     setCharProperty("ProvShow", provshow);
162     setIntegerProperty("Time", time);
163     setIntegerProperty("Increment", inc);
164     setBooleanProperty("IsRated", isRated);
165     setStringProperty("MatchType", matchType);
166     setCharProperty("RequestedColor", color);
167     setIntegerProperty("MinRating", minRating);
168     setIntegerProperty("MaxRating", maxRating);
169     setBooleanProperty("IsAutomaticAccept", isAutomaticAccept);
170     setBooleanProperty("IsFormulaUsed", isFormulaUsed);
171   }
172 
173 
174 
175 
176   /**
177    * Parses the given seekinfo line and returns a corresponding SeekInfoStruct
178    * object. Here's an example seekinfo line:<PRE>
179    * <s> 29 w=Snaps ti=02 rt=1532  t=1 i=0 r=r tp=lightning c=? rr=0-9999 a=t f=t
180    * </PRE>
181    * If the seek cannot be accepted by the user, the line identifier is "<sn>"
182    * and not "<s>".
183    * More information about the format is available in the FICS iv_seekinfo
184    * help file.
185    */
186 
parseSeekInfoLine(String line)187   public static SeekInfoStruct parseSeekInfoLine(String line){
188     StringTokenizer tokens = new StringTokenizer(line, " -=");
189 
190     boolean canAcceptSeek;
191     String identifier = tokens.nextToken();
192     if (identifier.equals("<s>")) // Skip the <s> identifier
193       canAcceptSeek = true;
194     else if (identifier.equals("<sn>"))
195       canAcceptSeek = false;
196     else
197       throw new IllegalArgumentException("Missing \"<s>\" or \"<sn>\" identifier");
198 
199     int index = Integer.parseInt(tokens.nextToken());
200 
201     assertToken(tokens, "w"); // w=
202     String name = tokens.nextToken();
203 
204     assertToken(tokens, "ti"); // ti=
205     int titles = Integer.parseInt(tokens.nextToken(), 16);
206 
207     assertToken(tokens, "rt"); // rt=
208     String ratingString = tokens.nextToken();
209     char provShow = ' ';
210     if (!Character.isDigit(ratingString.charAt(ratingString.length() - 1))){
211       provShow = ratingString.charAt(ratingString.length() - 1);
212       ratingString = ratingString.substring(0, ratingString.length() - 1);
213     }
214     int rating = Integer.parseInt(ratingString);
215 
216     assertToken(tokens, "t"); // t=
217     int time = Integer.parseInt(tokens.nextToken());
218 
219     assertToken(tokens, "i"); // i=
220     int inc = Integer.parseInt(tokens.nextToken());
221 
222     assertToken(tokens, "r"); // r=
223     boolean isRated = tokens.nextToken().equals("r");
224 
225     assertToken(tokens, "tp"); // tp=
226     String matchType = tokens.nextToken();
227 
228     assertToken(tokens, "c"); // c=
229     char requestedColor = tokens.nextToken().charAt(0);
230 
231     assertToken(tokens, "rr"); // rr=
232     int minRating = Integer.parseInt(tokens.nextToken());
233     int maxRating = Integer.parseInt(tokens.nextToken());
234 
235     assertToken(tokens, "a"); // a=
236     boolean isAutomaticAccept = tokens.nextToken().equals("t");
237 
238     assertToken(tokens, "f"); // f=
239     boolean isFormulaUsed = tokens.nextToken().equals("t");
240 
241     return new SeekInfoStruct(canAcceptSeek, index, name, titles, rating, provShow,
242       time, inc, isRated, matchType, requestedColor, minRating, maxRating,
243       isAutomaticAccept, isFormulaUsed);
244   }
245 
246 
247 
248 
249   /**
250    * Checks that the next token for the given StringTokenizer is the specified
251    * String. Throws an IllegalArgumentException if it isn't.
252    */
253 
assertToken(StringTokenizer tokenizer, String token)254   private static void assertToken(StringTokenizer tokenizer, String token){
255    String realToken = tokenizer.nextToken();
256    if (!realToken.equals(token))
257      throw new IllegalArgumentException("Bad token \""+realToken+"\", expected \""+token+"\" instead");
258   }
259 
260 
261 
262 
263   /**
264    * Returns <code>true</code> if the user account can accept the seek, returns
265    * <code>false</code> otherwise.
266    */
267 
canAcceptSeek()268   public boolean canAcceptSeek(){
269     return getBooleanProperty("CanAcceptSeek");
270   }
271 
272 
273 
274 
275   /**
276    * Returns the index of the seek.
277    */
278 
getSeekIndex()279   public int getSeekIndex(){
280     return getIntegerProperty("Index");
281   }
282 
283 
284 
285 
286   /**
287    * Returns the handle of the seeking player.
288    */
289 
getSeekerHandle()290   public String getSeekerHandle(){
291     return getStringProperty("Name");
292   }
293 
294 
295 
296 
297   /**
298    * Returns the titles of the seeking player, ORed into an int. To find whether
299    * the player is GM, for example, use
300    * <code>(getSeekerTitles() & SeekInfoStruct.GM) != 0</code>.
301    */
302 
getSeekerTitles()303   public int getSeekerTitles(){
304     return getIntegerProperty("Titles");
305   }
306 
307 
308 
309 
310   /**
311    * Returns the seeker's rating.
312    */
313 
getSeekerRating()314   public int getSeekerRating(){
315     return getIntegerProperty("Rating");
316   }
317 
318 
319 
320 
321   /**
322    * Returns the seeker rating's provshow character. 'E' if the rating is
323    * estimated, 'P' if provisional, and ' ' if neither.
324    */
325 
getSeekerProvShow()326   public char getSeekerProvShow(){
327     return getCharProperty("ProvShow");
328   }
329 
330 
331 
332 
333   /**
334    * Returns the initial time of the sought match, in minutes.
335    */
336 
getMatchTime()337   public int getMatchTime(){
338     return getIntegerProperty("Time");
339   }
340 
341 
342 
343 
344   /**
345    * Returns the increment of the sought match, in seconds.
346    */
347 
getMatchIncrement()348   public int getMatchIncrement(){
349     return getIntegerProperty("Increment");
350   }
351 
352 
353 
354 
355   /**
356    * Returns <code>true</code> if the sought match is rated, <code>false</code>
357    * otherwise.
358    */
359 
isMatchRated()360   public boolean isMatchRated(){
361     return getBooleanProperty("IsRated");
362   }
363 
364 
365 
366 
367   /**
368    * Returns the sought game type. Either the name of the wild variant, or the
369    * rating type, if the variant is chess. For example - "suicide", "lightning",
370    * "blitz" etc.
371    */
372 
getMatchType()373   public String getMatchType(){
374     return getStringProperty("MatchType");
375   }
376 
377 
378 
379 
380   /**
381    * Returns a character specifying the desired color for the seeker. 'W' if
382    * white, 'B' if black, and '?' if the seeker doesn't care.
383    */
384 
getSeekerColor()385   public char getSeekerColor(){
386     return getCharProperty("RequestedColor");
387   }
388 
389 
390 
391 
392   /**
393    * Returns the minimum rating of the desired opponent.
394    */
395 
getOpponentMinRating()396   public int getOpponentMinRating(){
397     return getIntegerProperty("MinRating");
398   }
399 
400 
401 
402 
403   /**
404    * Returns the maximum rating of the desired opponent.
405    */
406 
getOpponentMaxRating()407   public int getOpponentMaxRating(){
408     return getIntegerProperty("MaxRating");
409   }
410 
411 
412 
413 
414   /**
415    * Returns <code>true</code> if the match will be accepted automatically,
416    * <code>false</code> if the seeker must confirm it manually.
417    */
418 
isAutomaticAccept()419   public boolean isAutomaticAccept(){
420     return getBooleanProperty("IsAutomaticAccept");
421   }
422 
423 
424 
425 
426   /**
427    * Returns <code>true</code> if in order to accept the seek, one must pass
428    * the formula of the seeker. Returns <code>false</code> otherwise.
429    */
430 
isFormulaUsed()431   public boolean isFormulaUsed(){
432     return getBooleanProperty("IsFormulaUsed");
433   }
434 
435 
436 }
437