//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_AddMonths: // Returns the date incremented by the specified number of months. // dateT date_AddMonths (dateT date, int numMonths) { uint year = date_GetYear (date); uint month = date_GetMonth (date); uint day = date_GetDay (date); while (numMonths < 0) { if (month == 0 || month == 1) { year--; month = 12; } else { month--; } numMonths++; } while (numMonths > 0) { month++; if (month > 12) { year++; month = 1; } numMonths--; } return ((year << YEAR_SHIFT) | (month << MONTH_SHIFT) | day); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_DecodeToString(): convert date to PGN tag string. void date_DecodeToString (dateT date, char * str) { ASSERT(str != NULL); uint year, month, day; year = date_GetYear (date); month = date_GetMonth (date); day = date_GetDay (date); if (year == 0) { *str++ = '?'; *str++ = '?'; *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (year / 1000); *str++ = '0' + (year % 1000) / 100; *str++ = '0' + (year % 100) / 10; *str++ = '0' + (year % 10); } *str++ = '.'; if (month == 0) { *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (month / 10); *str++ = '0' + (month % 10); } *str++ = '.'; if (day == 0) { *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (day / 10); *str++ = '0' + (day % 10); } *str = 0; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Crosstable::PrintTable() // Prints the crosstable to a self-extending DString. // The format can be plain text or hypertext with player and game tags, // depending on the value of the OutputFormat member variable. void Crosstable::PrintTable (DString * dstr, crosstableModeT mode, uint playerLimit, int currentGame) { CurrentGame = currentGame; if (playerLimit == 0 || playerLimit > PlayerCount) { playerLimit = PlayerCount; } if (playerLimit < 2) { return; } if (mode == CROSSTABLE_Auto) { mode = BestMode(); } // Sort the players by score, name or rating: Tiebreaks (mode); uint player; for (player=0; player < PlayerCount; player++) { SortedIndex[player] = player; InvertedIndex[player] = player; } for (uint first=0; first < PlayerCount-1; first++) { for (uint second = first+1; second < PlayerCount; second++) { if (comparePlayerData (PlayerData[SortedIndex[first]], PlayerData[SortedIndex[second]], SortOption) > 0) { uint temp = SortedIndex[first]; SortedIndex[first] = SortedIndex[second]; SortedIndex[second] = temp; } } } for (player=0; player < PlayerCount; player++) { InvertedIndex[SortedIndex[player]] = player; } PlayerNumWidth = 2; if (playerLimit > 99) { PlayerNumWidth = 3; } // Determine the longest player name: LongestNameLen = 0; for (player = 0; player < PlayerCount; player++) { uint len = strLength (PlayerData[player]->name); if (len > LongestNameLen) { LongestNameLen = len; } } // Determine if any players have elo rating, title, country: PrintRatings = false; PrintTitles = false; PrintCountries = false; PrintAges = false; PrintTiebreaks = true; PrintTallies = true; for (player = 0; player < PlayerCount; player++) { playerDataT * pd = PlayerData[player]; if (pd->elo > 0) { PrintRatings = true; } if (pd->title[0] != 0) { PrintTitles = true; } if (pd->country[0] != 0) { PrintCountries = true; } if (pd->birthdate != ZERO_DATE) { PrintAges = true; int age = (int) date_GetYear(FirstDate); age -= (int) date_GetYear (pd->birthdate); if (date_GetMonth(pd->birthdate) > date_GetMonth(FirstDate)) { age--; } pd->ageInYears = age; } } if (! ShowElos) { PrintRatings = false; } if (! ShowTitles) { PrintTitles = false; } if (! ShowCountries) { PrintCountries = false; } if (! ShowTallies) { PrintTallies = false; } if (! ShowAges) { PrintAges = false; } if (! ShowTiebreaks) { PrintTiebreaks = false; } if (mode == CROSSTABLE_Knockout) { PrintTiebreaks = false; } // Print the table header: StartTable = ""; EndTable = ""; StartRow = ""; EndRow = ""; NewLine = "\n"; BlankRowLine = "\n"; StartCol = ""; EndCol = ""; StartRightCol = ""; EndRightCol = ""; StartBoldCol = ""; EndBoldCol = ""; if (OutputFormat == CROSSTABLE_Hypertext) { NewLine = BlankRowLine = "<br>"; } if (OutputFormat == CROSSTABLE_Html) { StartTable = "\n<p><table border=1 cellspacing=0 cellpadding=4>\n"; EndTable = "</table></p>\n"; StartRow = "<tr>"; EndRow = "</tr>"; NewLine = "\n"; BlankRowLine = "<tr></tr>\n"; StartCol = "<td>"; EndCol = "</td>"; StartRightCol = "<td align=right>"; EndRightCol = "</td>"; StartBoldCol = "<th>"; EndBoldCol = "</th>"; } if (OutputFormat == CROSSTABLE_LaTeX) { StartTable = ""; EndTable = "\\end{tabular}\n\n"; StartRow = ""; EndRow = " \\\\"; NewLine = "\n"; BlankRowLine = "\\\\\n"; StartCol = ""; EndCol = " &"; StartRightCol = ""; EndRightCol = " &"; StartBoldCol = "\\bf "; EndBoldCol = " &"; } // LineWidth is used to determine length of line of dashes to print. LineWidth = LongestNameLen; if (PrintRatings) { LineWidth += 16; } if (PrintTitles) { LineWidth += 4; } if (PrintCountries) { LineWidth += 4; } if (PrintAges) { LineWidth += 4; } if (mode == CROSSTABLE_Swiss) { LineWidth += 16 + PlayerNumWidth; LineWidth += (PlayerNumWidth + (SwissColors ? 3 : 2)) * MaxRound; if (PrintTiebreaks) { LineWidth += 5; } } else if (mode == CROSSTABLE_AllPlayAll) { LineWidth += 16 + PlayerNumWidth; if (playerLimit == 2) { LineWidth += (MaxClashes + 1); } else { LineWidth += (playerLimit * (MaxClashes + 1)); } if (PrintTiebreaks) { LineWidth += 7; } } else { // Knockout LineWidth = (LongestNameLen * 2) + 17 + MaxClashes; if (PrintRatings) { LineWidth += 10; } if (PrintTitles) { LineWidth += 8; } if (PrintCountries) { LineWidth += 8; } if (PrintAges) { LineWidth += 8; } } switch (mode) { case CROSSTABLE_AllPlayAll: PrintAllPlayAll (dstr, playerLimit); break; case CROSSTABLE_Knockout: PrintKnockout (dstr, playerLimit); break; case CROSSTABLE_Swiss: case CROSSTABLE_Auto: PrintSwiss (dstr, playerLimit); break; } char stemp [100]; if (GameCount > 1) { sprintf (stemp, "%u game%s: %s%u %s%u %s%u", GameCount, strPlural (GameCount), OutputFormat == CROSSTABLE_LaTeX ? "{\\tt +}" : "+", ResultCount[RESULT_White], OutputFormat == CROSSTABLE_LaTeX ? "{\\tt =}" : "=", ResultCount[RESULT_Draw], OutputFormat == CROSSTABLE_LaTeX ? "{\\tt -}" : "-", ResultCount[RESULT_Black]); dstr->Append (stemp); if (ResultCount[RESULT_None] > 0) { sprintf (stemp, " %s%u", OutputFormat == CROSSTABLE_LaTeX ? "{\\tt *}" : "*", ResultCount[RESULT_None]); dstr->Append (stemp); } dstr->Append (NewLine); } return; }