Scid  4.6.5
crosstab.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////
2 //
3 // FILE: crosstab.cpp
4 // Crosstable class methods
5 //
6 // Part of: Scid (Shane's Chess Information Database)
7 // Version: 3.3
8 //
9 // Notice: Copyright (c) 2001 Shane Hudson. All rights reserved.
10 //
11 // Author: Shane Hudson (sgh@users.sourceforge.net)
12 //
13 //////////////////////////////////////////////////////////////////////
14 
15 #ifndef WINCE
16 
17 #include "crosstab.h"
18 #include "dstring.h"
19 
20 // Expected differences in rating according to performance
21 // from 50% to 100%:
22 const uint perf_elodiff [51] = {
23  /* 50 - 59 */ 0, 7, 14, 21, 29, 36, 43, 50, 57, 65,
24  /* 60 - 69 */ 72, 80, 87, 95, 102, 110, 117, 125, 133, 141,
25  /* 70 - 79 */ 149, 158, 166, 175, 184, 193, 202, 211, 220, 230,
26  /* 80 - 89 */ 240, 251, 262, 273, 284, 296, 309, 322, 336, 351,
27  /* 90 - 99 */ 366, 383, 401, 422, 444, 470, 501, 538, 589, 677,
28  /* 100 */ 999
29 };
30 
31 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 // Crosstable::Performance():
33 // Given an average of opponents ratings and a percentage score,
34 // returns the performance rating.
35 uint
36 Crosstable::Performance (uint oppAvg, uint percentage)
37 {
38  if (percentage > 100) { percentage = 100; }
39  uint performance = oppAvg;
40  if (percentage < 50) {
41  performance -= perf_elodiff [50 - percentage];
42  } else {
43  performance += perf_elodiff [percentage - 50];
44  }
45  return performance;
46 }
47 
48 
49 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50 // Crosstable::RatingChange():
51 // Calculates rating change, given current rating, average rating
52 // and score
53 int
54 Crosstable::RatingChange (eloT player, uint oppAvg, uint percentage, uint games)
55 {
56  uint diff = (player > oppAvg) ? player - oppAvg : oppAvg - player;
57  int i;
58  for (i=0; i<50 ; i++)
59  if (diff <= perf_elodiff[i])
60  break;
61  uint expected = i;
62  if (player > oppAvg)
63  expected += 50;
64  else
65  expected = 50 - expected;
66  int cutoff = (percentage > expected) ? 5 : -5;
67  return (((int)percentage - (int)expected) * (int)games + cutoff) / 10;
68 }
69 
70 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71 // Crosstable::FideCategory()
72 // Given an average Elo rating for an all-play-all tournament,
73 // returns the FIDE Category of the tournament.
74 // Ratings under 2251 have no category.
75 // 2251-2275 = Cat. 1, 2276-2300 = Cat. 2, etc in blocks of 25.
76 uint
78 {
79  if (rating <= 2250) { return 0; }
80  return 1 + ((rating - 2251) / 25);
81 }
82 
83 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84 // Crosstable::OpponentElo():
85 // Strips ELO rating if difference is bigger than 350
86 eloT
87 Crosstable::OpponentElo (eloT player, eloT opponent)
88 {
89  const eloT Margin = 350;
90  if (!player)
91  return opponent;
92  else if (player - opponent > Margin)
93  return player - Margin;
94  else if (opponent - player > Margin)
95  return player + Margin;
96  else
97  return opponent;
98 }
99 
100 
101 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102 // comparePlayerData():
103 // Compares two playerDataT structs based on their tournament score.
104 int
106 {
107  int result = 0;
108  switch (option) {
109  case CROSSTABLE_SortScore: // Sort by highest score, then fewest games:
110  result = p2->score - p1->score;
111  if (result == 0) { result = p1->gameCount - p2->gameCount; }
112  if (result == 0) { result = p2->tiebreak - p1->tiebreak; }
113  break;
114 
115  case CROSSTABLE_SortName:
116  result = strCompare(p1->name, p2->name);
117  break;
118 
119  case CROSSTABLE_SortElo:
120  result = p2->elo - p1->elo;
121  break;
122 
124  result = strCompare(p1->country, p2->country);
125  break;
126  }
127  return result;
128 }
129 
130 
131 void
132 Crosstable::Init ()
133 {
134  for (uint pcount=0; pcount < CROSSTABLE_MaxPlayers; pcount++) {
135  PlayerData[pcount] = NULL;
136  }
137  GameCount = 0;
138  PlayerCount = 0;
139  MaxClashes = 0;
140  MaxRound = 0;
141  FirstDate = ZERO_DATE;
142  for (resultT r = 0; r < NUM_RESULT_TYPES; r++) { ResultCount[r] = 0; }
143  ShowTitles = ShowElos = ShowCountries = ShowTallies = SwissColors = ShowAges = true;
144  ShowTiebreaks = false;
145  SortOption = CROSSTABLE_SortScore;
146  OutputFormat = CROSSTABLE_Plain;
147  DecimalPointChar = '.';
148  APAColumnNums = false;
149 }
150 
151 void
152 Crosstable::Destroy ()
153 {
154  for (uint player=0; player < PlayerCount; player++) {
155  playerDataT * pdata = PlayerData[player];
156  ASSERT (pdata != NULL);
157 #ifdef WINCE
158  my_Tcl_Free((char*)pdata->name);
159 #else
160  delete[] pdata->name;
161 #endif
162  for (uint opp = 0; opp < PlayerCount; opp++) {
163  clashT * clash = pdata->firstClash[opp];
164  while (clash != NULL) {
165  clashT * temp = clash->next;
166 #ifdef WINCE
167  my_Tcl_Free((char*)clash);
168 #else
169  delete clash;
170 #endif
171  clash = temp;
172  }
173  }
174 
175 #ifdef WINCE
176  my_Tcl_Free((char*)pdata);
177 #else
178  delete pdata;
179 #endif
180  }
181 }
182 
183 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184 // Crosstable::AddPlayer()
185 // Adds a player to the crosstable, if that player is not
186 // already listed.
187 errorT
188 Crosstable::AddPlayer (idNumberT id, const char * name, eloT elo, const SpellChecker* SpellCheck)
189 {
190  for (uint i = 0; i < PlayerCount; i++) {
191  if (PlayerData[i]->id == id) {
192  // The player already exists in the crosstable, but
193  // check the elo rating and keep the largest value:
194  if (elo > PlayerData[i]->elo) { PlayerData[i]->elo = elo; }
195  return OK;
196  }
197  }
198  if (PlayerCount == CROSSTABLE_MaxPlayers) { return ERROR_Full; }
199  playerDataT * pdata = new playerDataT;
200 
201  PlayerData[PlayerCount] = pdata;
202  pdata->id = id;
203  pdata->name = strDuplicate (name);
204  pdata->elo = elo;
205  pdata->score = 0;
206  pdata->gameCount = 0;
207  pdata->tiebreak = 0;
208  pdata->oppEloCount = 0;
209  pdata->oppEloTotal = 0;
210  pdata->oppEloScore = 0;
211  pdata->title[0] = 0;
212  pdata->country[0] = 0;
213  pdata->birthdate = ZERO_DATE;
214  pdata->ageInYears = 0;
215  for (uint opp = 0; opp < CROSSTABLE_MaxPlayers; opp++) {
216  pdata->firstClash[opp] = pdata->lastClash[opp] = NULL;
217  pdata->clashCount[opp] = 0;
218  }
219  for (uint round = 1; round < CROSSTABLE_MaxRounds; round++) {
220  pdata->roundClash[round] = NULL;
221  }
222 
223  if (SpellCheck != NULL ) {
224  const PlayerInfo* pInfo = SpellCheck->getPlayerInfo(name);
225  if (pInfo != NULL) {
226  strCopy (pdata->title, pInfo->getTitle());
227  strCopy (pdata->country, pInfo->getLastCountry());
228  pdata->birthdate = pInfo->getBirthdate();
229  if (strEqual (pdata->title, "w")) { strCopy (pdata->title, "w "); }
230  }
231  }
232  PlayerCount++;
233  return OK;
234 }
235 
236 
237 uint max(int a, int b) {return a<b ? b : a;}
238 
239 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
240 // Crosstable::AddResult()
241 // Adds a game result to the crosstable.
242 errorT
243 Crosstable::AddResult (uint gameNumber, idNumberT white, idNumberT black,
244  resultT result, uint round, dateT date)
245 {
246  // Find the two players in the player data:
247  int whiteIdx = -1;
248  int blackIdx = -1;
249  uint i;
250  for (i=0; i < PlayerCount; i++) {
251  if (PlayerData[i]->id == white) { whiteIdx = i; break; }
252  }
253  for (i=0; i < PlayerCount; i++) {
254  if (PlayerData[i]->id == black) { blackIdx = i; break; }
255  }
256 
257  // Both players must exist in the crosstable:
258  if (whiteIdx < 0 || blackIdx < 0) { return ERROR_NotFound; }
259 
260  // The two players must actually be different:
261  if (whiteIdx == blackIdx) { return ERROR_Corrupt; }
262 
263  playerDataT * pwhite = PlayerData[whiteIdx];
264  playerDataT * pblack = PlayerData[blackIdx];
265 
266  // The number of prior encounters must be consistent:
267  ASSERT (pwhite->clashCount[blackIdx] == pblack->clashCount[whiteIdx]);
268  clashT * whiteClash = new clashT;
269 
270  if (pwhite->firstClash[blackIdx] == NULL) { // New head of list:
271  pwhite->firstClash[blackIdx] = whiteClash;
272  } else {
273  pwhite->lastClash[blackIdx]->next = whiteClash;
274  }
275  whiteClash->next = NULL;
276  pwhite->lastClash[blackIdx] = whiteClash;
277 
278  clashT * blackClash = new clashT;
279  if (pblack->firstClash[whiteIdx] == NULL) { // New head of list:
280  pblack->firstClash[whiteIdx] = blackClash;
281  } else {
282  pblack->lastClash[whiteIdx]->next = blackClash;
283  }
284  blackClash->next = NULL;
285  pblack->lastClash[whiteIdx] = blackClash;
286 
287  whiteClash->result = result;
288  blackClash->result = RESULT_OPPOSITE[result];
289  whiteClash->gameNum = gameNumber;
290  blackClash->gameNum = gameNumber;
291  whiteClash->opponent = blackIdx;
292  blackClash->opponent = whiteIdx;
293  whiteClash->color = WHITE;
294  blackClash->color = BLACK;
295  whiteClash->round = round;
296  blackClash->round = round;
297  if (round > 0 && round < CROSSTABLE_MaxRounds) {
298  pwhite->roundClash[round] = whiteClash;
299  pblack->roundClash[round] = blackClash;
300  if (round > MaxRound) { MaxRound = round; }
301  }
302  pwhite->clashCount[blackIdx]++;
303  pblack->clashCount[whiteIdx]++;
304  if (pwhite->clashCount[blackIdx] > MaxClashes) {
305  MaxClashes = pwhite->clashCount[blackIdx];
306  }
307  pwhite->gameCount++;
308  pblack->gameCount++;
309 
310  // Update averages of opponents ratings for performance stats:
311  if (result && pblack->elo > 0) {
312  pwhite->oppEloCount++;
313  pwhite->oppEloTotal += OpponentElo(pwhite->elo, pblack->elo);
314  }
315  if (result && pwhite->elo > 0) {
316  pblack->oppEloCount++;
317  pblack->oppEloTotal += OpponentElo(pblack->elo, pwhite->elo);
318  }
319 
320  if (FirstDate == ZERO_DATE) { FirstDate = date; }
321  if (date != ZERO_DATE && date < FirstDate) {
322  FirstDate = date;
323  }
324 
325  switch (result) {
326  case RESULT_White:
327  pwhite->score += (ThreeWin ? 6 : 2);
328  if (pblack->elo > 0) {
329  pwhite->oppEloScore += 2;
330  }
331  break;
332  case RESULT_Black:
333  pblack->score += (ThreeWin ? 6 : 2);
334  if (pwhite->elo > 0) {
335  pblack->oppEloScore += 2;
336  }
337  break;
338  case RESULT_Draw:
339  pwhite->score += (ThreeWin ? 2 : 1);
340  pblack->score += (ThreeWin ? 2 : 1);
341  if (pblack->elo > 0) {
342  pwhite->oppEloScore ++;
343  }
344  if (pwhite->elo > 0) {
345  pblack->oppEloScore ++;
346  }
347  break;
348  default:
349  break; // Nothing.
350  }
351  ResultCount[result]++;
352  GameCount++;
353  return OK;
354 }
355 
356 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
357 // Crosstable::Tiebreaks()
358 // Computes the tiebreak score for all players.
359 void
360 Crosstable::Tiebreaks (crosstableModeT mode)
361 {
362  uint player;
363  for (player = 0; player < PlayerCount; player++) {
364  playerDataT * pd = PlayerData[player];
365  pd->tiebreak = 0;
366  uint tb = 0;
367  // Tiebreaks are meaningless for Knockout tables:
368  if (mode == CROSSTABLE_Knockout) { continue; }
369 
370  for (uint opp = 0; opp < PlayerCount; opp++) {
371  if (opp == player) { continue; }
372  clashT * clash = pd->firstClash[opp];
373  while (clash != NULL) {
374  uint oppScore = PlayerData[opp]->score;
375  if (mode == CROSSTABLE_Swiss) {
376  // For Swiss, just do sum of opponent scores:
377  tb += PlayerData[opp]->score;
378  } else {
379  // AllPlayAll mode: do Sonneborn-Berger:
380  if (clash->result == RESULT_White) {
381  tb += oppScore + oppScore;
382  } else if (clash->result == RESULT_Draw) {
383  tb += oppScore;
384  }
385  }
386  clash = clash->next;
387  }
388  }
389  pd->tiebreak = tb;
390  }
391 }
392 
393 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
394 // Crosstable::BestMode():
395 // Returns the best mode of table to use for this tournament:
396 // All-play-all, Swiss or Knockout.
397 // XXX Currently never chooses Knockout, fix this sometime...
400 {
401  // If 12 players of less, use all-play-all:
402  if (PlayerCount <= 12) { return CROSSTABLE_AllPlayAll; }
403  // If more than 30 players, use Swiss:
404  if (PlayerCount > 30) { return CROSSTABLE_Swiss; }
405  // If less than 5 games per player on average, use Swiss:
406  if ((GameCount / PlayerCount) < 5) { return CROSSTABLE_Swiss; }
407  // If less than half the number of games in a complete all-play-all
408  // tournament, use Swiss:
409  uint completeAllPlayAll = (PlayerCount * (PlayerCount - 1)) / 2;
410  if (GameCount < completeAllPlayAll / 2) { return CROSSTABLE_Swiss; }
411  // Otherwise, use all-play-all:
412  return CROSSTABLE_AllPlayAll;
413 }
414 
415 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
416 // Crosstable::AvgRating()
417 // Returns the average Elo rating of all players in the
418 // tournament who have a rating. Players with no rating
419 // are ignored.
420 eloT
422 {
423  uint count = 0;
424  uint total = 0;
425  for (uint i=0; i < PlayerCount; i++) {
426  if (PlayerData[i]->elo > 0) { total += PlayerData[i]->elo; count++; }
427  }
428  if (count == 0) { return 0; }
429  return (eloT) (total / count);
430 }
431 
432 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
433 // Crosstable::PrintTable()
434 // Prints the crosstable to a self-extending DString.
435 // The format can be plain text or hypertext with player and game tags,
436 // depending on the value of the OutputFormat member variable.
437 void
438 Crosstable::PrintTable (DString * dstr, crosstableModeT mode, uint playerLimit, int currentGame)
439 {
440  CurrentGame = currentGame;
441  if (playerLimit == 0 || playerLimit > PlayerCount) {
442  playerLimit = PlayerCount;
443  }
444  if (playerLimit < 2) { return; }
445 
446  if (mode == CROSSTABLE_Auto) { mode = BestMode(); }
447 
448  // Sort the players by score, name or rating:
449  Tiebreaks (mode);
450  uint player;
451  for (player=0; player < PlayerCount; player++) {
452  SortedIndex[player] = player;
453  InvertedIndex[player] = player;
454  }
455  for (uint first=0; first < PlayerCount-1; first++) {
456  for (uint second = first+1; second < PlayerCount; second++) {
457  if (comparePlayerData (PlayerData[SortedIndex[first]],
458  PlayerData[SortedIndex[second]],
459  SortOption) > 0) {
460  uint temp = SortedIndex[first];
461  SortedIndex[first] = SortedIndex[second];
462  SortedIndex[second] = temp;
463  }
464  }
465  }
466  for (player=0; player < PlayerCount; player++) {
467  InvertedIndex[SortedIndex[player]] = player;
468  }
469 
470  PlayerNumWidth = 2;
471  if (playerLimit > 99) { PlayerNumWidth = 3; }
472 
473  // Determine the longest player name:
474  LongestNameLen = 0;
475  for (player = 0; player < PlayerCount; player++) {
476  uint len = strLength (PlayerData[player]->name);
477  if (len > LongestNameLen) { LongestNameLen = len; }
478  }
479 
480  // Determine if any players have elo rating, title, country:
481  PrintRatings = false;
482  PrintTitles = false;
483  PrintCountries = false;
484  PrintAges = false;
485  PrintTiebreaks = true;
486  PrintTallies = true;
487  for (player = 0; player < PlayerCount; player++) {
488  playerDataT * pd = PlayerData[player];
489  if (pd->elo > 0) { PrintRatings = true; }
490  if (pd->title[0] != 0) { PrintTitles = true; }
491  if (pd->country[0] != 0) { PrintCountries = true; }
492  if (pd->birthdate != ZERO_DATE) {
493  PrintAges = true;
494  int age = (int) date_GetYear(FirstDate);
495  age -= (int) date_GetYear (pd->birthdate);
496  if (date_GetMonth(pd->birthdate) > date_GetMonth(FirstDate)) {
497  age--;
498  }
499  pd->ageInYears = age;
500  }
501  }
502  if (! ShowElos) { PrintRatings = false; }
503  if (! ShowTitles) { PrintTitles = false; }
504  if (! ShowCountries) { PrintCountries = false; }
505  if (! ShowTallies) { PrintTallies = false; }
506  if (! ShowAges) { PrintAges = false; }
507  if (! ShowTiebreaks) { PrintTiebreaks = false; }
508  if (mode == CROSSTABLE_Knockout) { PrintTiebreaks = false; }
509 
510  // Print the table header:
511  StartTable = "";
512  EndTable = "";
513  StartRow = "";
514  EndRow = "";
515  NewLine = "\n";
516  BlankRowLine = "\n";
517  StartCol = "";
518  EndCol = "";
519  StartRightCol = "";
520  EndRightCol = "";
521  StartBoldCol = "";
522  EndBoldCol = "";
523 
524  if (OutputFormat == CROSSTABLE_Hypertext) {
525  NewLine = BlankRowLine = "<br>";
526  }
527  if (OutputFormat == CROSSTABLE_Html) {
528  StartTable = "\n<p><table border=1 cellspacing=0 cellpadding=4>\n";
529  EndTable = "</table></p>\n";
530  StartRow = "<tr>";
531  EndRow = "</tr>";
532  NewLine = "\n";
533  BlankRowLine = "<tr></tr>\n";
534  StartCol = "<td>";
535  EndCol = "</td>";
536  StartRightCol = "<td align=right>";
537  EndRightCol = "</td>";
538  StartBoldCol = "<th>";
539  EndBoldCol = "</th>";
540  }
541  if (OutputFormat == CROSSTABLE_LaTeX) {
542  StartTable = "";
543  EndTable = "\\end{tabular}\n\n";
544  StartRow = "";
545  EndRow = " \\\\";
546  NewLine = "\n";
547  BlankRowLine = "\\\\\n";
548  StartCol = "";
549  EndCol = " &";
550  StartRightCol = "";
551  EndRightCol = " &";
552  StartBoldCol = "\\bf ";
553  EndBoldCol = " &";
554  }
555 
556  // LineWidth is used to determine length of line of dashes to print.
557  LineWidth = LongestNameLen;
558  if (PrintRatings) { LineWidth += 16; }
559  if (PrintTitles) { LineWidth += 4; }
560  if (PrintCountries) { LineWidth += 4; }
561  if (PrintAges) { LineWidth += 4; }
562 
563  if (mode == CROSSTABLE_Swiss) {
564  LineWidth += 16 + PlayerNumWidth;
565  LineWidth += (PlayerNumWidth + (SwissColors ? 3 : 2)) * MaxRound;
566  if (PrintTiebreaks) { LineWidth += 5; }
567  } else if (mode == CROSSTABLE_AllPlayAll) {
568  LineWidth += 16 + PlayerNumWidth;
569  if (playerLimit == 2) {
570  LineWidth += (MaxClashes + 1);
571  } else {
572  LineWidth += (playerLimit * (MaxClashes + 1));
573  }
574  if (PrintTiebreaks) { LineWidth += 7; }
575  } else { // Knockout
576  LineWidth = (LongestNameLen * 2) + 17 + MaxClashes;
577  if (PrintRatings) { LineWidth += 10; }
578  if (PrintTitles) { LineWidth += 8; }
579  if (PrintCountries) { LineWidth += 8; }
580  if (PrintAges) { LineWidth += 8; }
581  }
582 
583  switch (mode) {
585  PrintAllPlayAll (dstr, playerLimit);
586  break;
587  case CROSSTABLE_Knockout:
588  PrintKnockout (dstr, playerLimit);
589  break;
590  case CROSSTABLE_Swiss:
591  case CROSSTABLE_Auto:
592  PrintSwiss (dstr, playerLimit);
593  break;
594  }
595 
596  char stemp [100];
597  if (GameCount > 1) {
598  sprintf (stemp, "%u game%s: %s%u %s%u %s%u",
599  GameCount, strPlural (GameCount),
600  OutputFormat == CROSSTABLE_LaTeX ? "{\\tt +}" : "+",
601  ResultCount[RESULT_White],
602  OutputFormat == CROSSTABLE_LaTeX ? "{\\tt =}" : "=",
603  ResultCount[RESULT_Draw],
604  OutputFormat == CROSSTABLE_LaTeX ? "{\\tt -}" : "-",
605  ResultCount[RESULT_Black]);
606  dstr->Append (stemp);
607  if (ResultCount[RESULT_None] > 0) {
608  sprintf (stemp, " %s%u",
609  OutputFormat == CROSSTABLE_LaTeX ? "{\\tt *}" : "*",
610  ResultCount[RESULT_None]);
611  dstr->Append (stemp);
612  }
613  dstr->Append (NewLine);
614  }
615  return;
616 }
617 
618 void
619 Crosstable::PrintDashesLine (DString * dstr)
620 {
621  // Print line of dashes, if not in HTML or LaTeX:
622  if (OutputFormat == CROSSTABLE_LaTeX) {
623  dstr->Append ("\\hline\n");
624  return;
625  }
626  if (OutputFormat == CROSSTABLE_Html) {
627  return;
628  }
629  for (uint i=0; i < LineWidth; i++) {
630  dstr->AddChar ('-');
631  }
632  dstr->Append (NewLine);
633 }
634 
635 void
636 Crosstable::PrintPlayer (DString * dstr, playerDataT * pdata)
637 {
638  char stemp[1000];
639  if (OutputFormat == CROSSTABLE_Hypertext) {
640  sprintf (stemp, "<pi %s>", pdata->name);
641  dstr->Append (stemp);
642  }
643  sprintf (stemp, "%-*s ", LongestNameLen, pdata->name);
644  dstr->Append (StartCol, stemp, EndCol);
645 
646  if (PrintRatings) {
647  if (pdata->elo) {
648  sprintf (stemp, "%4u ", pdata->elo);
649  } else {
650  if (OutputFormat == CROSSTABLE_Html) {
651  strcpy (stemp, " - ");
652  } else {
653  strcpy (stemp, " ");
654  }
655  }
656  dstr->Append (StartRightCol, stemp, EndRightCol);
657  }
658 
659  // if exporting to html, don't print blank fields
660  // as firefox doesn't make a grid box for blanks S.A.
661 
662  if (PrintTitles) {
663  if (OutputFormat == CROSSTABLE_Html && !strCompare(pdata->title,"")) {
664  sprintf (stemp, " - ");
665  } else {
666  sprintf (stemp, "%3s ", pdata->title);
667  }
668  dstr->Append (StartCol, stemp, EndCol);
669  }
670  if (PrintAges) {
671  if (pdata->ageInYears == 0) {
672  if (OutputFormat == CROSSTABLE_Html) {
673  sprintf (stemp, " - ");
674  } else {
675  strCopy (stemp, " ");
676  }
677  } else {
678  sprintf (stemp, "%3d ", pdata->ageInYears);
679  }
680  dstr->Append (StartCol, stemp, EndCol);
681  }
682  if (PrintCountries) {
683  if (OutputFormat == CROSSTABLE_Html && !strCompare(pdata->country,"")) {
684  sprintf (stemp, " - ");
685  } else {
686  sprintf (stemp, "%-3s ", pdata->country);
687  }
688  dstr->Append (StartCol, stemp, EndCol);
689  }
690  if (OutputFormat == CROSSTABLE_Hypertext) { dstr->Append ("</pi>"); }
691 }
692 
693 void
694 Crosstable::PrintPerformance (DString * dstr, playerDataT * pdata)
695 {
696  if (!PrintRatings) { return; }
697  if (!pdata->oppEloCount) { return; }
698 
699  int oppAvgRating = pdata->oppEloTotal / pdata->oppEloCount;
700  int percentage = pdata->oppEloScore * 50 + pdata->oppEloCount/2;
701  percentage = percentage / pdata->oppEloCount;
702  int performance = Performance(oppAvgRating, percentage);
703  if (performance > 0 && performance < 5000) {
704  char stemp [20];
705  if (pdata->elo) {
706  int change = RatingChange (pdata->elo, oppAvgRating,
707  percentage, pdata->oppEloCount);
708  sprintf (stemp, "%4d %+3d", performance, change);
709  } else {
710  sprintf (stemp, "%4d ", performance);
711  }
712  dstr->Append (" ", StartRightCol, stemp, EndRightCol);
713  }
714 }
715 
716 void
717 Crosstable::PrintAllPlayAll (DString * dstr, uint playerLimit)
718 {
719  char stemp [1000];
720  uint player;
721 
722  dstr->Append (StartTable);
723  if (OutputFormat == CROSSTABLE_LaTeX) {
724  dstr->Append ("\\begin{tabular}{rl");
725  if (PrintRatings) { dstr->Append ("r"); }
726  if (PrintTitles) { dstr->Append ("r"); }
727  if (PrintAges) { dstr->Append ("r"); }
728  if (PrintCountries) { dstr->Append ("l"); }
729  dstr->Append ("r@{ / }r");
730  if (PrintTiebreaks) { dstr->Append ("r"); }
731  for (uint i=0; i < playerLimit; i++) {
732  dstr->Append ("c");
733  if (i < playerLimit-1) { dstr->Append ("@{ }"); }
734  }
735  if (PrintRatings) { dstr->Append ("r"); }
736  dstr->Append ("r}\n");
737  }
738  dstr->Append (StartRow);
739  if (OutputFormat == CROSSTABLE_Html) {
740  dstr->Append ("<th></th> <th>Player</th> ");
741  } else if (OutputFormat == CROSSTABLE_LaTeX) {
742  dstr->Append (" & \\bf Player & ");
743  } else {
744  strPad (stemp, "", LongestNameLen + 2 + PlayerNumWidth, ' ');
745  dstr->Append (stemp);
746  }
747  if (PrintRatings) {
748  dstr->Append (StartBoldCol, " Rtng", EndBoldCol);
749  }
750  if (PrintTitles) {
751  dstr->Append (StartBoldCol, " Ti", EndBoldCol);
752  }
753  if (PrintAges) {
754  dstr->Append (StartBoldCol, " Age", EndBoldCol);
755  }
756  if (PrintCountries) {
757  dstr->Append (StartBoldCol, " Nat", EndBoldCol);
758  }
759  if (OutputFormat == CROSSTABLE_LaTeX) {
760  // Todo : fix LateX Score column alignment with 3 points for win.
761  dstr->Append (" \\multicolumn{2}{c}{\\bf Score} & ");
762  } else {
763  if (ThreeWin)
764  dstr->Append (" ", StartBoldCol, "Score", EndBoldCol, " ");
765  else
766  dstr->Append (" ", StartBoldCol, " Score ", EndBoldCol, " ");
767  }
768  if (PrintTiebreaks) {
769  dstr->Append (StartBoldCol, " (Tie) ", EndBoldCol);
770  }
771 
772  for (player = 0; player < playerLimit; player++) {
773  strPad (stemp, PlayerData[SortedIndex[player]]->name, MaxClashes, ' ');
774  if (APAColumnNums) {
775  // Print numbers instead of names over columns:
776  strPad (stemp, "", MaxClashes, ' ');
777  uint pnum = player + 1;
778  stemp[MaxClashes-1] = (pnum % 10) + '0';
779  if (MaxClashes >= 2 && pnum >= 10) {
780  stemp[MaxClashes-2] = ((pnum / 10) % 10) + '0';
781  }
782  if (MaxClashes >= 3 && pnum >= 100) {
783  stemp[MaxClashes-3] = ((pnum / 10) % 10) + '0';
784  }
785  }
786  if (playerLimit == 2) {
787  // Make two-player crosstable look better:
788  player = 1;
789  strPad (stemp,
790  "12345678901234567890123456789012345678901234567890",
791  MaxClashes, ' ');
792  }
793  if (OutputFormat == CROSSTABLE_LaTeX) {
794  dstr->Append (" \\tt ", stemp, " &");
795  } else {
796  dstr->Append (" ", StartBoldCol, stemp, EndBoldCol);
797  }
798  }
799  if (PrintRatings) {
800  dstr->Append (" ", StartBoldCol, "Perf Chg", EndBoldCol);
801  }
802  if (PrintTallies && OutputFormat == CROSSTABLE_Html) {
803  dstr->Append (" ", StartBoldCol, "+/-/=", EndBoldCol);
804  }
805  dstr->Append (EndRow, NewLine);
806 
807  PrintDashesLine (dstr);
808 
809  // Print the rows of players and results:
810  uint previousScore = 0;
811  for (player = 0; player < playerLimit; player++) {
812  uint index = SortedIndex[player];
813  playerDataT * pdata = PlayerData[index];
814 
815  // Print a blank line if we are at a new score group:
816  if (SeparateScoreGroups && SortOption == CROSSTABLE_SortScore) {
817  if (player > 0 && pdata->score != previousScore) {
818  dstr->Append (BlankRowLine);
819  }
820  }
821  previousScore = pdata->score;
822 
823  sprintf (stemp, "%*u: ", PlayerNumWidth, player+1);
824  dstr->Append (StartRow, StartRightCol, stemp, EndRightCol);
825 
826  PrintPlayer (dstr, pdata);
827 
828  if (OutputFormat == CROSSTABLE_LaTeX) {
829  sprintf (stemp, " %2u%c%c ", pdata->score / 2, DecimalPointChar,
830  (pdata->score & 1 ? '5' : '0'));
831  dstr->Append (StartRightCol, stemp, EndRightCol);
832  sprintf (stemp, " %2u ", pdata->gameCount);
833  dstr->Append (StartRightCol, stemp, EndRightCol);
834  } else {
835  if (ThreeWin) {
836  sprintf (stemp, " %2u%c%c ",
837  pdata->score / 2, DecimalPointChar,
838  (pdata->score & 1 ? '5' : '0'));
839  } else {
840  sprintf (stemp, " %2u%c%c / %2u ",
841  pdata->score / 2, DecimalPointChar,
842  (pdata->score & 1 ? '5' : '0'), pdata->gameCount);
843  }
844  dstr->Append (StartRightCol, stemp, EndRightCol);
845  }
846  if (PrintTiebreaks) {
847  sprintf (stemp, "%3u%c%02u ", pdata->tiebreak / 4,
848  DecimalPointChar, (pdata->tiebreak % 4) * 25);
849  dstr->Append (StartRightCol, stemp, EndRightCol);
850  }
851 
852  uint r_won = 0, r_loss = 0, r_draw = 0;
853  for (uint oppCount = 0; oppCount < playerLimit; oppCount++) {
854  if (playerLimit == 2 && oppCount == player) { continue; }
855  uint opp = SortedIndex[oppCount];
856  dstr->AddChar (' ');
857  dstr->Append (StartRightCol);
858  clashT * clash = pdata->firstClash[opp];
859 
860  for (uint count = 0; count < MaxClashes; count++) {
861  if (clash != NULL) {
862  if (OutputFormat == CROSSTABLE_Hypertext) {
863  if (CurrentGame == clash->gameNum)
864  sprintf(stemp, "<green><g_%u>%c</g></green>",
865  clash->gameNum, RESULT_CHAR[clash->result]);
866  else
867  sprintf(stemp, "<blue><g_%u>%c</g></blue>",
868  clash->gameNum, RESULT_CHAR[clash->result]);
869  dstr->Append (stemp);
870  } else {
871  dstr->AddChar (RESULT_CHAR[clash->result]);
872  }
873  switch (clash->result) {
874  case 1:
875  r_won++;
876  break;
877  case 2:
878  r_loss++;
879  break;
880  case 3:
881  r_draw++;
882  break;
883  }
884  clash = clash->next;
885  } else {
886  dstr->AddChar (index == opp ? 'X' : '.');
887  }
888  }
889  dstr->Append (EndCol);
890  }
891 
892  PrintPerformance (dstr, pdata);
893 
894  if (PrintTallies) {
895  dstr->Append (StartCol);
896  sprintf (stemp, " (+%u -%u =%u)", r_won, r_loss, r_draw);
897  dstr->Append (stemp);
898  dstr->Append (EndCol);
899  }
900 
901  dstr->Append (EndRow, NewLine);
902  }
903  PrintDashesLine (dstr);
904  dstr->Append (EndTable);
905 }
906 
907 void
908 Crosstable::PrintSwiss (DString * dstr, uint playerLimit)
909 {
910  char stemp [1000];
911  uint player;
912 
913  const char * resultStr [NUM_RESULT_TYPES];
914  if (OutputFormat == CROSSTABLE_LaTeX) {
915  resultStr[RESULT_White] = "{\\tt +}";
916  resultStr[RESULT_Draw] = "{\\tt =}";
917  resultStr[RESULT_Black] = "{\\tt -}";
918  resultStr[RESULT_None] = "{\\tt *}";
919  } else {
920  resultStr[RESULT_White] = "+";
921  resultStr[RESULT_Draw] = "=";
922  resultStr[RESULT_Black] = "-";
923  resultStr[RESULT_None] = "*";
924  }
925 
926  dstr->Append (StartTable);
927  if (OutputFormat == CROSSTABLE_LaTeX) {
928  dstr->Append ("\\begin{tabular}{rl");
929  if (PrintRatings) { dstr->Append ("r"); }
930  if (PrintTitles) { dstr->Append ("r"); }
931  if (PrintAges) { dstr->Append ("r"); }
932  if (PrintCountries) { dstr->Append ("l"); }
933  dstr->Append ("r@{ / }r");
934  if (PrintTiebreaks) { dstr->Append ("r"); }
935  for (uint i=0; i < MaxRound; i++) {
936  dstr->Append ("r");
937  if (i < MaxRound-1) { dstr->Append ("@{ }"); }
938  }
939  if (PrintRatings) { dstr->Append ("r"); }
940  dstr->Append ("r}\n");
941  }
942  dstr->Append (StartRow);
943  if (OutputFormat == CROSSTABLE_Html) {
944  dstr->Append ("<th></th> <th>Player</th> ");
945  } else if (OutputFormat == CROSSTABLE_LaTeX) {
946  dstr->Append (" & \\bf Player & ");
947  } else {
948  strPad (stemp, "", LongestNameLen + 2 + PlayerNumWidth, ' ');
949  dstr->Append (stemp);
950  }
951  if (PrintRatings) {
952  dstr->Append (StartBoldCol, " Rtng", EndBoldCol);
953  }
954  if (PrintTitles) {
955  dstr->Append (StartBoldCol, " Ti", EndBoldCol);
956  }
957  if (PrintAges) {
958  dstr->Append (StartBoldCol, " Age", EndBoldCol);
959  }
960  if (PrintCountries) {
961  dstr->Append (StartBoldCol, " Nat", EndBoldCol);
962  }
963  if (OutputFormat == CROSSTABLE_LaTeX) {
964  dstr->Append (" \\multicolumn{2}{c}{\\bf Score} & ");
965  } else {
966  if (ThreeWin)
967  dstr->Append (" ", StartBoldCol, "Score", EndBoldCol, " ");
968  else
969  dstr->Append (" ", StartBoldCol, " Score ", EndBoldCol, " ");
970  }
971  if (PrintTiebreaks) {
972  dstr->Append (StartBoldCol, "(Tie)", EndBoldCol);
973  }
974 
975  for (uint round = 1; round <= MaxRound; round++) {
976  if (OutputFormat == CROSSTABLE_LaTeX) {
977  dstr->Append (" \\multicolumn{1}{c}{\\bf ", round, "} & ");
978  } else {
979  sprintf (stemp, " %s%*d ", SwissColors ? " " : "",
980  PlayerNumWidth, round);
981  dstr->Append (StartBoldCol, stemp, EndBoldCol);
982  }
983  }
984  if (PrintRatings) {
985  dstr->Append (" ", StartBoldCol, "Perf Chg", EndBoldCol);
986  }
987  if (PrintTallies && OutputFormat == CROSSTABLE_Html) {
988  dstr->Append (" ", StartBoldCol, "+/-/=", EndBoldCol);
989  }
990  dstr->Append (EndRow, NewLine);
991 
992  PrintDashesLine (dstr);
993 
994  // Print the rows of players and results:
995  uint previousScore = 0;
996  for (player = 0; player < playerLimit; player++) {
997  uint index = SortedIndex[player];
998  playerDataT * pdata = PlayerData[index];
999 
1000  // Print a blank line if we are at a new score group:
1001  if (SeparateScoreGroups && SortOption == CROSSTABLE_SortScore) {
1002  if (player > 0 && pdata->score != previousScore) {
1003  dstr->Append (BlankRowLine);
1004  }
1005  }
1006  previousScore = pdata->score;
1007 
1008  sprintf (stemp, "%*u: ", PlayerNumWidth, player+1);
1009  dstr->Append (StartRow, StartRightCol, stemp, EndRightCol);
1010 
1011  PrintPlayer (dstr, pdata);
1012 
1013  if (OutputFormat == CROSSTABLE_LaTeX) {
1014  sprintf (stemp, " %2u%c%c ", pdata->score / 2, DecimalPointChar,
1015  (pdata->score & 1 ? '5' : '0'));
1016  dstr->Append (StartRightCol, stemp, EndRightCol);
1017  sprintf (stemp, " %2u ", pdata->gameCount);
1018  dstr->Append (StartRightCol, stemp, EndRightCol);
1019  } else {
1020  if (ThreeWin) {
1021  sprintf (stemp, " %2u%c%c ",
1022  pdata->score / 2, DecimalPointChar,
1023  (pdata->score & 1 ? '5' : '0'));
1024  } else {
1025  sprintf (stemp, " %2u%c%c / %2u ",
1026  pdata->score / 2, DecimalPointChar,
1027  (pdata->score & 1 ? '5' : '0'), pdata->gameCount);
1028  }
1029  dstr->Append (StartRightCol, stemp, EndRightCol);
1030  }
1031  if (PrintTiebreaks) {
1032  sprintf (stemp, "%2u%c%c ", pdata->tiebreak / 2,
1033  DecimalPointChar, (pdata->tiebreak & 1 ? '5' : '0'));
1034  dstr->Append (StartRightCol, stemp, EndRightCol);
1035  }
1036 
1037  uint r_won = 0, r_loss = 0, r_draw = 0;
1038  for (uint round = 1; round <= MaxRound; round++) {
1039  clashT * clash = pdata->roundClash[round];
1040  dstr->AddChar (' ');
1041  dstr->Append (StartRightCol);
1042  if (clash == NULL) {
1043  dstr->Append ("...");
1044  if (PlayerNumWidth == 3) { dstr->AddChar ('.'); }
1045  if (SwissColors) { dstr->AddChar ('.'); }
1046  } else {
1047  if (OutputFormat == CROSSTABLE_Hypertext) {
1048  if (CurrentGame == clash->gameNum)
1049  sprintf (stemp, "<green><g_%u>", clash->gameNum);
1050  else
1051  sprintf (stemp, "<blue><g_%u>", clash->gameNum);
1052  dstr->Append (stemp);
1053  }
1054  if (SwissColors) {
1055  sprintf (stemp, "%*d%c%s", PlayerNumWidth,
1056  InvertedIndex[clash->opponent] + 1,
1057  clash->color == WHITE ? 'w' : 'b',
1058  resultStr[clash->result]);
1059  } else {
1060  sprintf (stemp, "%*d%s", PlayerNumWidth,
1061  InvertedIndex[clash->opponent] + 1,
1062  resultStr[clash->result]);
1063  }
1064  dstr->Append (stemp);
1065  if (OutputFormat == CROSSTABLE_Hypertext) {
1066  if (CurrentGame == clash->gameNum)
1067  dstr->Append ("</g></green>");
1068  else
1069  dstr->Append ("</g></blue>");
1070  }
1071  switch (clash->result) {
1072  case 1:
1073  r_won++; break;
1074  case 2:
1075  r_loss++; break;
1076  case 3:
1077  r_draw++; break;
1078  }
1079  }
1080  dstr->Append (EndCol);
1081  }
1082  PrintPerformance (dstr, pdata);
1083 
1084  if (PrintTallies) {
1085  dstr->Append (StartCol);
1086  sprintf (stemp, " (+%u -%u =%u)", r_won, r_loss, r_draw);
1087  dstr->Append (stemp);
1088  dstr->Append (EndCol);
1089  }
1090 
1091  dstr->Append (EndRow, NewLine);
1092  }
1093 
1094  PrintDashesLine (dstr);
1095  dstr->Append (EndTable);
1096 }
1097 
1098 
1099 void
1100 Crosstable::PrintKnockout (DString * dstr, uint playerLimit)
1101 {
1102  char stemp [1000];
1103  uint player;
1104 
1105  for (uint round = 1; round <= MaxRound; round++) {
1106  if (OutputFormat == CROSSTABLE_LaTeX) {
1107  dstr->Append ("\n\n", round, ":\n\n");
1108  } else {
1109  dstr->Append (round, ":", NewLine);
1110  }
1111  dstr->Append (StartTable);
1112  if (OutputFormat == CROSSTABLE_LaTeX) {
1113  dstr->Append ("\\begin{tabular}{l");
1114  if (PrintRatings) { dstr->Append ("r"); }
1115  if (PrintTitles) { dstr->Append ("r"); }
1116  if (PrintAges) { dstr->Append ("r"); }
1117  if (PrintCountries) { dstr->Append ("l"); }
1118  dstr->Append ("@{\\hspace{4ex}}lr@{ / }r@{\\hspace{4ex}}l");
1119  if (PrintRatings) { dstr->Append ("r"); }
1120  if (PrintTitles) { dstr->Append ("r"); }
1121  if (PrintAges) { dstr->Append ("r"); }
1122  if (PrintCountries) { dstr->Append ("l"); }
1123  dstr->Append ("r}\n");
1124  }
1125  PrintDashesLine (dstr);
1126  for (player = 0; player < playerLimit; player++) {
1127  PlayerData[player]->printed = false;
1128  }
1129  for (player = 0; player < playerLimit; player++) {
1130  uint index = SortedIndex[player];
1131  playerDataT * pdata = PlayerData[index];
1132  clashT * clash = pdata->roundClash[round];
1133  if (clash == NULL) { continue; }
1134  if (pdata->printed) { continue; }
1135  uint opponent = clash->opponent;
1136  // if black first, skip this game till white is first
1137  if (pdata->firstClash[opponent]->color == 1) { continue; }
1138  uint score = 0;
1139  uint nGames = 0;
1140  clash = pdata->firstClash[opponent];
1141  while (clash != 0) {
1142  if (clash->round == round) {
1143  score += RESULT_SCORE[clash->result];
1144  nGames++;
1145  }
1146  clash = clash->next;
1147  }
1148  // Skip this to allow white to be shown first
1149  // if (score < nGames) { continue; }
1150  dstr->Append (StartRow);
1151  PrintPlayer (dstr, pdata);
1152 
1153  dstr->Append (StartCol, " ");
1154  if (OutputFormat == CROSSTABLE_LaTeX) { dstr->Append ("{\\tt "); }
1155  clash = pdata->firstClash[opponent];
1156  for (uint count = 0; count < MaxClashes; count++) {
1157  while (clash != NULL && clash->round != round) {
1158  clash = clash->next;
1159  }
1160  if (clash != NULL) {
1161  if (OutputFormat == CROSSTABLE_Hypertext) {
1162  if (CurrentGame == clash->gameNum)
1163  sprintf (stemp, "<green><g_%u>%c</g></green>",
1164  clash->gameNum,
1165  RESULT_CHAR[clash->result]);
1166  else
1167  sprintf (stemp, "<blue><g_%u>%c</g></blue>",
1168  clash->gameNum,
1169  RESULT_CHAR[clash->result]);
1170  dstr->Append (stemp);
1171  } else {
1172  dstr->AddChar (RESULT_CHAR[clash->result]);
1173  }
1174  clash = clash->next;
1175  } else {
1176  dstr->AddChar (' ');
1177  }
1178  }
1179  if (OutputFormat == CROSSTABLE_LaTeX) { dstr->Append ("}"); }
1180  dstr->Append (" ", EndCol);
1181 
1182  if (OutputFormat == CROSSTABLE_LaTeX) {
1183  sprintf (stemp, " %2u%c%c ", score / 2, DecimalPointChar,
1184  (score & 1 ? '5' : '0'));
1185  dstr->Append (StartRightCol, stemp, EndRightCol);
1186  sprintf (stemp, " %2u ", nGames);
1187  dstr->Append (StartRightCol, stemp, EndRightCol);
1188  } else {
1189  sprintf (stemp, "%2u%c%c / %2u ",
1190  score / 2, DecimalPointChar,
1191  (score & 1 ? '5' : '0'), nGames);
1192  dstr->Append (StartRightCol, stemp, EndRightCol);
1193  }
1194  PrintPlayer (dstr, PlayerData[opponent]);
1195  dstr->Append (EndRow, NewLine);
1196  pdata->printed = true;
1197  PlayerData[opponent]->printed = true;
1198  }
1199  PrintDashesLine (dstr);
1200  dstr->Append (EndTable, NewLine);
1201  }
1202 }
1203 
1204 #endif // WINCE
1205 //////////////////////////////////////////////////////////////////////
1206 // EOF: crosstab.cpp
1207 //////////////////////////////////////////////////////////////////////
uint date_GetYear(dateT date)
Definition: date.h:55
const errorT ERROR_Full
Definition: error.h:49
const uint CROSSTABLE_MaxPlayers
Definition: crosstab.h:26
clashT * lastClash[CROSSTABLE_MaxPlayers]
Definition: crosstab.h:68
uint oppEloScore
Definition: crosstab.h:66
byte resultT
Definition: common.h:183
const char * getLastCountry() const
Definition: spellchk.cpp:416
crosstableModeT BestMode(void)
Definition: crosstab.cpp:399
uint strLength(const char *str)
Definition: misc.h:492
const colorT WHITE
Definition: common.h:203
eloT AvgRating()
Definition: crosstab.cpp:421
uint idNumberT
Definition: namebase.h:39
idNumberT id
Definition: crosstab.h:57
bool strEqual(const char *str1, const char *str2)
Definition: misc.h:305
const errorT OK
Definition: error.h:23
const uint CROSSTABLE_MaxRounds
Definition: crosstab.h:27
const uint NUM_RESULT_TYPES
Definition: common.h:182
char * strDuplicate(const char *original)
Definition: misc.cpp:239
uint max(int a, int b)
Definition: crosstab.cpp:237
clashT * roundClash[CROSSTABLE_MaxRounds]
Definition: crosstab.h:70
colorT color
Definition: crosstab.h:34
uint dateT
Definition: common.h:155
#define ASSERT(f)
Definition: common.h:67
crosstableModeT
Definition: crosstab.h:49
const resultT RESULT_Black
Definition: common.h:187
names
Definition: tablebase.tcl:260
clashT * next
Definition: crosstab.h:36
const colorT BLACK
Definition: common.h:204
const resultT RESULT_OPPOSITE[4]
Definition: common.h:194
uint gameCount
Definition: crosstab.h:61
eloT elo
Definition: crosstab.h:59
class SpellChecker - name spelling
Definition: spellchk.h:257
uint score
Definition: crosstab.h:60
dateT getBirthdate() const
Definition: spellchk.cpp:462
const resultT RESULT_Draw
Definition: common.h:188
const dateT ZERO_DATE
Definition: date.h:34
uint oppEloTotal
Definition: crosstab.h:65
const char * getTitle() const
Definition: spellchk.cpp:389
uint clashCount[CROSSTABLE_MaxPlayers]
Definition: crosstab.h:69
const PlayerInfo * getPlayerInfo(const char *name, std::vector< const char * > *bio=0) const
Definition: spellchk.h:349
int ageInYears
Definition: crosstab.h:74
uint strPad(char *target, const char *original, int width, char padding)
Definition: misc.cpp:268
void AddChar(char ch)
Definition: dstring.h:32
const resultT RESULT_White
Definition: common.h:186
uint32_t uint
Definition: common.h:99
bool printed
Definition: crosstab.h:75
static uint Performance(uint oppAvg, uint percentage)
Definition: crosstab.cpp:36
static eloT OpponentElo(eloT player, eloT opponent)
Definition: crosstab.cpp:87
const char RESULT_CHAR[4]
Definition: common.h:191
int comparePlayerData(playerDataT *p1, playerDataT *p2, crosstableSortT option)
Definition: crosstab.cpp:105
char title[8]
Definition: crosstab.h:71
ushort eloT
Definition: common.h:160
uint gameNum
Definition: crosstab.h:32
const uint perf_elodiff[51]
Definition: crosstab.cpp:22
dateT birthdate
Definition: crosstab.h:73
char * name
Definition: crosstab.h:58
unsigned short errorT
Definition: error.h:20
uint tiebreak
Definition: crosstab.h:62
void Append(uint i)
Definition: dstring.h:46
static int RatingChange(eloT player, uint oppAvg, uint percentage, uint count)
Definition: crosstab.cpp:54
const uint RESULT_SCORE[4]
Definition: common.h:190
clashT * firstClash[CROSSTABLE_MaxPlayers]
Definition: crosstab.h:67
Definition: tablebase.tcl:15
crosstableSortT
Definition: crosstab.h:39
void strCopy(char *target, const char *original)
Definition: misc.h:379
void PrintTable(DString *dstr, crosstableModeT mode, uint playerLimit, int currentGame)
Definition: crosstab.cpp:438
const errorT ERROR_Corrupt
Definition: error.h:46
uint round
Definition: crosstab.h:35
errorT AddPlayer(idNumberT id, const char *name, eloT elo, const SpellChecker *)
Definition: crosstab.cpp:188
uint oppEloCount
Definition: crosstab.h:64
const char * strPlural(uint x)
Definition: misc.h:248
uint opponent
Definition: crosstab.h:33
const resultT RESULT_None
Definition: common.h:185
static uint FideCategory(eloT rating)
Definition: crosstab.cpp:77
char country[8]
Definition: crosstab.h:72
const errorT ERROR_NotFound
Definition: error.h:50
int strCompare(const char *s1, const char *s2)
Definition: misc.h:361
uint date_GetMonth(dateT date)
Definition: date.h:64
resultT result
Definition: crosstab.h:31
class PlayerInfo - player informations
Definition: spellchk.h:231
errorT AddResult(uint gameNumber, idNumberT white, idNumberT black, resultT result, uint round, dateT date)
Definition: crosstab.cpp:243