ultimatepp/uppdev/VegaTeam5/RoundSwiss.cpp
cxl 3cd394812c Merge continued
git-svn-id: svn://ultimatepp.org/upp/trunk@10263 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-10-04 08:34:39 +00:00

935 lines
34 KiB
C++

#include "VegaMain.h"
#include "Tournament.h"
int RoundData::MakeNextPairing()
{ extern void SortPairs(int round);
return 10;
}
void RoundData::SaveRound(int flag)
//
// save the round file
// flag = 0, save the file at the current round
// flag = 1, save a backup file at current round
//
{ int i, j, npair, numPlayers = NPlayer;
int round = currentRound;
String filename, s;
if (flag==0) filename = PATHDIR + FILETORNEO + ".rnd";
else filename = PATHDIR + FILETORNEO + AsString(TD.currentRound) + ".rnd";
FileOut out(filename);
out.PutLine( NFormat("%2d # current round", currentRound ) );
out.PutLine( " 1 # not used" );
out.PutLine( " 1 # not used" );
out.PutLine( " 1 # not used" );
out.PutLine( NFormat("%2d # STATUS_ROUND", STATUS_ROUND) );
out.PutLine( " 1 # not used" );
out.PutLine( " 1 # not used" );
out.PutLine( "# players color" );
for (i=1; i<=NPlayer; i++)
{ String s = NFormat("%3d ", i);
for (j=1; j<=round; j++)
{ s << NFormat("%3d ", playerColor[i][j]);
}
out.PutLine( s );
}
out.PutLine("# players opponent" );
for (i=1; i<=NPlayer; i++)
{ String s = NFormat("%3d ", i);
for (j=1; j<=round; j++) s << NFormat("%3d ", playerOpponent[i][j]);
out.PutLine( s );
}
out.PutLine( "# players floater");
for (i=1; i<=NPlayer; i++)
{ String s = NFormat("%3d ", i);
for (j=1; j<=round; j++) s << NFormat("%d ", playerFloater[i][j]);
out.PutLine( s );
}
out.PutLine( "# round results");
for (i=1; i<=NPlayer; i++)
{ String s = NFormat("%3d ", i);
for (j=1; j<=round; j++) s << NFormat("%d ", roundResult[i][j]);
out.PutLine( s );
}
out.PutLine( "# code pairing");
if (NPlayer & 1) npair = (NPlayer-1)/2 + 1;
else npair = NPlayer/2;
for (i=0; i<=npair; i++)
{ String s = "";
for (j=1; j<=round; j++) s << NFormat("%7d ", pairing[i][j]);
out.PutLine( s );
}
if (out.IsError()) Exclamation(t_("Error while writing .rnd file"));
out.Close();
}
void RoundData::LoadRound(String filename)
{ FileIn in(filename);
int i, j, npair, numPlayers = NPlayer;
/* if ((in=fopen(filename, "r"))==NULL)
{ WarningMessage(sss[S_NOREADR], sss[S_CLOSE]);
return;
}
*/
TD.currentRound = StrIntValue( in.GetLine() );
in.GetLine(); //skip this line
in.GetLine(); //skip this line
in.GetLine(); //skip this line
STATUS_ROUND = StrIntValue( in.GetLine() );
in.GetLine(); //skip this line
in.GetLine(); //skip this line
in.GetLine(); //skip this line // "# players color\n"
for (i=1; i<=numPlayers; i++)
{ Vector<String> field = Split(in.GetLine(), ' ');
//field.GetCount() coincide with currentRound
for (j=1; j<field.GetCount(); j++) playerColor[i][j] = StrIntValue( field[j] );
}
in.GetLine(); //skip this line // "# players opponent\n"
for (i=1; i<=numPlayers; i++)
{ Vector<String> field = Split(in.GetLine(), ' ');
//field.GetCount() coincide with currentRound
for (j=1; j<field.GetCount(); j++) playerOpponent[i][j] = StrIntValue( field[j] );
}
in.GetLine(); //skip this line // "# players opponent\n"
for (i=1; i<=numPlayers; i++)
{ Vector<String> field = Split(in.GetLine(), ' ');
//field.GetCount() coincide with currentRound
for (j=1; j<field.GetCount(); j++) playerFloater[i][j] = StrIntValue( field[j] );
}
in.GetLine(); //skip this line // "# players result\n"
for (i=1; i<=numPlayers; i++)
{ Vector<String> field = Split(in.GetLine(), ' ');
//field.GetCount() coincide with currentRound
for (j=1; j<field.GetCount(); j++) roundResult[i][j] = StrIntValue( field[j] );
}
// now reads the pairing
in.GetLine(); //skip this line // "# code pairing\n"
if (numPlayers & 1) npair = (numPlayers-1)/2 + 1;
else npair = numPlayers/2;
for (i=0; i<=npair; i++)
{ Vector<String> field = Split(in.GetLine(), ' ');
for (j=1; j<=field.GetCount(); j++) pairing[i][j] = StrIntValue( field[j-1] );
}
in.Close();
}
void RoundData::AdjournPlayerState(int round)
//
// NOTE: it is called by MakeNextPairing and determine the state
// of each player at round 'round' necessary to calculate the next pairing
//
{ int id, j, np, maxcol;
int diffcolor, jopp, jump, maxjump;
int countblack, countwhite;
double score, aro, buc;
maxjump = 3; if (NRounds>9) maxjump=4; //set the maximum number of upfloating
maxcol = 2 + PERMIT3COLOR; // PERMIT3COLOR = 0, 1
if (round==NRounds-1 && PLAY_SYSTEM==LIM) maxcol = 3; // last round exception
for (id=1; id<=NPlayer; id++)
{
//determine the due color
diffcolor = 0;
for (j=1; j<=round; j++) diffcolor += playerColor[id][j];
player[id].colorDiff = diffcolor; // useful to assign color in case of equalization
if (diffcolor>0) player[id].duecolor = BLACK;
else if (diffcolor<0) player[id].duecolor = WHITE;
else { //equal black & white games
j=round;
while (playerColor[id][j] == NO_COLOR) j--; // go back in history
if (playerColor[id][j] == WHITE) player[id].duecolor = BLACK;
else player[id].duecolor = WHITE;
// useful for player that got the BYE
if (round==1 && playerColor[id][round]==NO_COLOR) player[id].duecolor = -1;
// WARNING!!!! the previous player should be in the color group with less players
}
//set the currentDuecolor equal to the duecolor
player[id].currentDuecolor = player[id].duecolor;
//set flag canChangeDuecolor to met 2.3 and 2.4
player[id].canChangeDuecolor = true; //default
if ( (diffcolor == maxcol) || (diffcolor == -maxcol)) player[id].canChangeDuecolor=false;
else player[id].canChangeDuecolor = true;
countblack = countwhite = 0;
if (player[id].duecolor==WHITE) {
for (j=round; j>=1; j--) {//check for consecutive black to met 2.4
if (playerColor[id][j]==BLACK_COLOR) countblack++;
else if (playerColor[id][j]==WHITE_COLOR) break;
}
if (countblack==maxcol) player[id].canChangeDuecolor = false;
if ( countblack==maxcol && currentRound==NRounds && !PERMIT3COLOR //permit3color is gia' contato in maxcol o si rischia 4 color
&& PLAY_SYSTEM==USCF) player[id].canChangeDuecolor = true;
}
if (player[id].duecolor==BLACK) {
for (j=round; j>=1; j--) {//check for consecutive white to met 2.4
if (playerColor[id][j]==WHITE_COLOR) countwhite++;
else if (playerColor[id][j]==BLACK_COLOR) break;
}
if (countwhite==maxcol) player[id].canChangeDuecolor=false;
else if (countwhite==maxcol && currentRound==NRounds && !PERMIT3COLOR //permit3color is gia' contato in maxcol o si rischia 4 color
&& PLAY_SYSTEM==USCF) player[id].canChangeDuecolor = true;
}
if (PLAY_SYSTEM==USCF) {
countblack = countwhite = 0;
for (j=round; j>=1; j--) {//check for consecutive black
if (playerColor[id][j]==BLACK_COLOR) countblack++;
else if (playerColor[id][j]==WHITE_COLOR) break;
}
for (j=round; j>=1; j--) {//check for consecutive white
if (playerColor[id][j]==WHITE_COLOR) countwhite++;
else if (playerColor[id][j]==BLACK_COLOR) break;
}
// duecolor = 1 for white
// duecolor = 0 for black
// duecolor = -1 for neutral
if ( countblack == 0 && countwhite == 0) player[id].duecolor = -1;
else if ( countblack > 0 ) player[id].colorCons = countblack;
else if ( countwhite > 0 ) player[id].colorCons = countwhite;
}
//set ARO
aro = 0.;
np = 0;
for (j=1; j<=round; j++) {
jopp = playerOpponent[id][j];
if (jopp != 0 && (roundResult[id][j] < 3)) // no BYE o game won for forfait
{ aro += (double) player[jopp].RATING; np++;}
}
if (np != 0) player[id].tiebreak[ARO] = player[id].aro = (float) (aro/np);
else player[id].tiebreak[ARO] = player[id].aro = (float) 0.;
//set score
score = 0.;
for (j=1; j<=round; j++) {
if (roundResult[id][j]==1 || roundResult[id][j]==3) score += WON;
else if (roundResult[id][j]==2 || roundResult[id][j]==6 || roundResult[id][j]==8) score += DRAW;
}
player[id].tiebreak[SCORE] = (float) score;
if (NAccRound && NAccRound>currentRound && id<=NPlayer/2)
player[id].tiebreak[SCORE] += WON; //accelerated rounds
//set flag canUpfloat
jump = 0;
if (PLAY_SYSTEM == DUBOV) {
for (j=1; j<=round; j++) if (playerFloater[id][j]) jump++;
if (jump >= maxjump) player[id].canUpfloat = false;
else if ( (jump < maxjump) && (playerFloater[id][round]) && (round<NRounds-1))
player[id].canUpfloat = false;
else if ( (jump < maxjump) && (playerFloater[id][round]) && (round==NRounds-1))
player[id].canUpfloat = true;
else player[id].canUpfloat = true;
}
if (PLAY_SYSTEM == LIM) { // downfloat
// if ( playerFloater[id][round]==1 ) playerState[id].canDownfloat = NO;
// else playerState[id].canDownfloat = YES;
if ( playerFloater[id][round]==1 ) player[id].canUpfloat = false;
else player[id].canUpfloat = true;
}
//set flag canGetBYE: who got 1 point without to play will not get the bye
// who got 1/2 point can get the bye if there are not player with flag 1
player[id].canGetBYE = 1;
for (j=1; j<=round; j++)
{ if (roundResult[id][j]==3) // won for forfeit
{ player[id].canGetBYE = 0;
break;
}
else if (roundResult[id][j]==6 || roundResult[id][j]==8)
player[id].canGetBYE = 2;
}
//set remaining flags
player[id].isAlreadyTested = false;
//set bucholz for pairing
if (PLAY_SYSTEM == VEGA) {
//calculate Buccholz
buc = 0.;
for (j=1; j<=round; j++)
{ jopp = playerOpponent[id][j];
if ( (jopp != 0) && (roundResult[id][j]<3) ) // no BYE, no forfait
{ buc += player[jopp].tiebreak[SCORE];
}
else if (roundResult[id][j]>2 && (roundResult[id][j] != 8)) // BYE, forfait but NOT draw without bucholz
buc += player[id].tiebreak[SCORE]; // sum his score to the bucholz
}
player[id].rating = (int) (buc*10);
player[id].aro = buc*10.;
}
/* else if (PLAY_SYSTEM == BURST) {
//calculate Extended Buccholz
buc = 0.;
for (j=1; j<=round; j++)
{ jopp = playerOpponent[id][j];
if ( (jopp != 0) && (roundResult[id][j]<3) ) // no BYE, no forfait
{ buc += playerResult[jopp][SCORE];
}
else if (roundResult[id][j]>2 && (roundResult[id][j] != 8)) // BYE, forfait but NOT draw without bucholz
buc += playerResult[id][SCORE]; // sum his score to the bucholz
}
player[id].aro = buc+playerResult[id][SCORE]; // Extende Buccholz
player[id].rating = player[id].RATING;
}
*/
else player[id].rating = player[id].RATING;
}
// set the _BYE_
player[0].duecolor = -1; // nessun colore
player[0].canChangeDuecolor = true;
}
void RoundData::AdjournCrossTableSwiss(int round)
//
// NOTE: it is called just after the iserting the result of the round
// so at round N, the state refer to the previous N-1 rounds
//
{ int id, j, np;
int jopp;
double score, aro, buc, min, max, sb;
double totscore, sumtotscore, modifiedscore[N_PLAYER_MAX+1];
for (id=1; id<=NPlayer; id++)
{
//set ARO
aro = 0.;
np = 0;
for (j=1; j<=round; j++)
{ jopp = playerOpponent[id][j];
if (jopp != 0 && roundResult[id][j] < 3) // no BYE o game won for forfait
{ aro += (double) player[jopp].RATING;
np++;
}
}
if (np != 0) player[id].tiebreak[ARO] = (float) aro/np;
else player[id].tiebreak[ARO] = (float) 0.;
score = 0.; //set score, cumulative points and most blacks
totscore=0.; //progressive score : 1, 2, 2.5, ...
sumtotscore = 0.; //cumulative points 1, 3, 5.5, ...
player[id].tiebreak[MOST_BLACKS] = modifiedscore[id] = 0.;
player[id].tiebreak[MOST_WINS] = 0.;
// calculate modified score useful for bucholz
for (j=1; j<=round; j++) {
switch (roundResult[id][j])
{ case 1:
totscore += WON; sumtotscore += totscore;
score += WON; player[id].tiebreak[MOST_WINS] += 1.;
modifiedscore[id] += WON;
break;
case 3: // win to forfeit
totscore += DRAW; sumtotscore += totscore;
score += WON; // playerResult[id][MOST_WINS] += 1; // forfeit count as draw
modifiedscore[id] += DRAW; // forfeit count as draw
break;
case 2: // draw
totscore += DRAW; sumtotscore += totscore;
score += DRAW;
modifiedscore[id] += DRAW; // forfeit count as draw
break;
case 6: // draw to forfeit
totscore += DRAW; sumtotscore += totscore;
score += DRAW;
modifiedscore[id] += DRAW; // forfeit count as draw
break;
case 0:
if (playerOpponent[id][j] !=0 ) sumtotscore += totscore;
else {
sumtotscore += totscore;
modifiedscore[id] += DRAW; // forfeit count as draw
}
break;
case 4: // lost to forfeit
sumtotscore += totscore + DRAW;
modifiedscore[id] += DRAW; // forfeit count as draw
break;
case 8:
sumtotscore += totscore;
score += DRAW;
modifiedscore[id] += DRAW;
break;
}
if (roundResult[id][j]==1 && playerColor[id][j]==-1)
player[id].tiebreak[MOST_BLACKS] += (float) 1.;
}
player[id].tiebreak[SCORE] = score;
if (NAccRound && NAccRound>currentRound && id<=NPlayer/2)
player[id].tiebreak[SCORE] += (float) WON; //accelerated rounds
player[id].tiebreak[CUMUL] = (float) sumtotscore;
}
for (id=1; id<=NPlayer; id++)
{ //set Buccholz
buc = 0.;
min = 10000.;
max = 0.;
for (j=1; j<=round; j++)
{ jopp = playerOpponent[id][j];
if ( (jopp != 0) && (roundResult[id][j]<3) ) // no BYE, no forfait
{ // buc += playerResult[jopp][SCORE];
buc += modifiedscore[jopp];
if (modifiedscore[jopp]<min) min = modifiedscore[jopp];
if (modifiedscore[jopp]>max) max = modifiedscore[jopp];
}
else if ( (roundResult[id][j]>2 && (roundResult[id][j] < 8)) || playerOpponent[id][j] ==0 ) // BYE, forfait but NOT draw without bucholz
{ buc += modifiedscore[id]; // sum his score to the bucholz
if (modifiedscore[id]<min) min = modifiedscore[id];
if (modifiedscore[id]>max) max = modifiedscore[id];
}
else if ( roundResult[id][j] == 8 ) // without bucholz
{
min = 0;
}
}
if (buc > min) player[id].tiebreak[BUC_CUT1] = (float) buc-min;
else player[id].tiebreak[BUC_CUT1] = 0.;
if (buc - min > max ) player[id].tiebreak[BUC_MED] = (float) (buc - min - max);
else player[id].tiebreak[BUC_MED] = 0.;
player[id].tiebreak[BUC_TOT] = (float) buc;
}
for (id=1; id<=NPlayer; id++)
{ //set Sonneborg-Berger
sb = 0.;
for (j=1; j<=round; j++)
{ jopp = playerOpponent[id][j];
if ( jopp != 0 && roundResult[id][j]==1 ) // win, no forfait
sb += modifiedscore[jopp];
else if ( (jopp != 0) && (roundResult[id][j]==2) ) // draw, no forfait
sb += modifiedscore[jopp]/2.;
else if ( ((jopp == 0) || (roundResult[id][j]>2)) && (roundResult[id][j] < 8) ) // draw with himself (forfait)
sb += modifiedscore[id]/2.; // sum his half score to the bucholz
}
player[id].tiebreak[SONN_BERG] = (float) sb;
}
// adjourn the rest of cross table
CalcVarElo(NPlayer);
//ShowClassificationByname(numberPlayer);
// PrepareHTMLindex();
NationalPlayerCard(NPlayer); // here is calculated the performance rating
setAPRO(round, NPlayer);
ShowTableScore(NPlayer);
CrossTableSwiss();
ShowTableCategoryScore(NPlayer);
}
void RoundData::CrossTableSwiss()
{ int i, j, index;
String stringa, str, strname;
int *roundRes;
int *playerCol;
int *playerOpp;
if (IS_SWISS) {
playerOpp = &playerOpponent[0][0];
roundRes = &roundResult[0][0];
playerCol = &playerColor[0][0];
}
FileOut save(PATHDIR + "crosstbl.txt");
FileOut savehtml (PATHDIRWWW + "crosstbl.html");
save << NAMETORNEO << "\n";
save << PLACETORNEO << " - " << DATATORNEO_B <<", "<<DATATORNEO_E << "\n\n";
save << t_(" Cross Table at round ")<< currentRound << "\n\n";
save << " ID NAME Rtg Tit Fed Scr |";
// produce HTML files
savehtml << TD.HTMLCommonHeader();
savehtml << HTMLNavBar();
savehtml << "<h2>" << NAMETORNEO << "</h2>\n";
savehtml << "<h2>" << PLACETORNEO << " - " << DATATORNEO_B <<", "<<DATATORNEO_E << "</h2>\n";
savehtml << "<h3> " << t_(" Cross Table at round ") << currentRound<< "</h3>\n";
savehtml << "<table bgcolor=#efefef cellpadding=4 cellspacing=0 border=0> \n";
savehtml << "<tbody>\n";
savehtml << "<tr>";
savehtml << "<th>ID</th> <th >NAME</th> <th>Rat</th> <th>PRat</th> <th>Nat</th> <th>Scr</th>\n";
for(j=1; j<=currentRound; j++) {
str = NFormat( " %3d ", j);
save << str;
savehtml << "<th>" << str << "</th>";
}
save << "\n";
savehtml << "</tr> \n";
save << "--------------------------------------------";
for(j=1; j<=currentRound; j++) save << "------";
save << "\n";
for (i=1; i<=NPlayer; i++)
{ if (player[i].isAvailable != "0") strname = NFormat("%-20.20s", player[i].name);
else strname = NFormat("%-17.17s(W)", player[i].name);
stringa = NFormat("%3d %-20.20s %4d %3.3s %3.3s %4.1f | ",
i, strname, player[i].RATING, player[i].codetitle, player[i].country, player[i].tiebreak[SCORE]);
save << stringa;
stringa = NFormat("<td> %3d </td> <td> <a href=\"playercard.html#%d\"> %s %s </a> </td> <td>%4d</td> <td align=center bgcolor=#EEEEEE>%4d</td> <td align=center>%3.3s</td> <td>%4.1f</td>",
i, i, player[i].codetitle, strname, player[i].RATING,
(int) player[i].tiebreak[PER_RAT], player[i].country, player[i].tiebreak[SCORE]);
if (i&1) savehtml <<"<tr bgcolor=#e2e2f8> ";
else savehtml << "<tr bgcolor=#ffffff> ";
savehtml << stringa;
for(j=1; j<=currentRound; j++)
{ if (PLAY_SYSTEM != ROUND_ROBIN && PLAY_SYSTEM != ROUND_ROBIN2) index = i*(N_ROUND_MAX+1) + j;
else index = i*(N_ROUND_MAX_RR+1) + j;
if (playerOpp[index]==0 && roundRes[index]==0) { //for late-comer - not played
stringa = " -- ";
save<< stringa;
savehtml << "<td>" << stringa << "</td>";
}
else if (playerOpp[index]==0 && roundRes[index]==3) { //for BYE: 1F - 0
stringa = "+BYE ";
save << stringa;
savehtml << "<td>" << stringa << "</td>";
}
else if (playerOpp[index]==0 && roundRes[index]==4) { //for BYE: 1F - 0
stringa = "-BYE ";
save << stringa;
savehtml << "<td>" << stringa << "</td>";
}
else if (playerOpp[index]==0 && (roundRes[index]==6 || roundRes[index]==8)) { //for BYE: XF
stringa = "=BYE ";
save<< stringa;
savehtml << "<td>" << stringa << "</td>";
}
else
{ savehtml << "<td>";
if (roundRes[index]==0 || roundRes[index]==4) {save<<"-"; savehtml << "-";}
else if (roundRes[index]==1 || roundRes[index]==3) {save<<"+"; savehtml << "+";}
else if (roundRes[index]==2 || roundRes[index]==6 || roundRes[index]==8) {save<<"="; savehtml << "=";}
if (playerCol[index]==-1) {save<<"B";savehtml << "B";}
else if (playerCol[index]==1) {save<<"W";savehtml << "W";}
else if (playerCol[index]==0) {save<<"N";savehtml << "N";}
stringa = NFormat("%-3d ", playerOpp[index]);
save << stringa;
savehtml << stringa << "</td>";
}
}
save << "\n";
savehtml << "</tr>\n";
}
save.Close();
savehtml << "</tbody>\n";
savehtml << "</table>\n";
savehtml << "<br> <a href=\"http://www.vegachess.com\"> Generated by Vega </a> \n";
savehtml << "</DIV></body>\n</html>\n";
savehtml.Close();
}
int RoundData::AssignColorLIM(int id1, int id2, int round)
//
// PURPOSE: determine the color for the players id1 and id2
//
// INPUT VARIABLE
// id1 = player1 with his duecolor
// id2 = player2 with his duecolor
// round = current round
//
// OUTPUT VARIABLE
// 1 to confirm the duecolor of id1 and change that of id2
// 0 to confirm both duecolor
// -1 to confirm the duecolor of id2 and change that of id1
// >1 flag of special operation when color history is the same
//
{ int j=0;
int id1due, id2due, diffcolor1, diffcolor2;
double maxscore = TD.WON*(round-1)/2.;
//char str[30];
// sprintf(str, "median = %4.1f", maxscore);
// WarningMessage(str, sss[S_CLOSE]);
if (id2==0) return TD.CodifyResult(id1, id2, 3); //return the BYE and the result
if (id1==0) return TD.CodifyResult(id1, id2, 4); //return the BYE and the result
id1due = player[id1].duecolor;
id2due = player[id2].duecolor;
if (id1due != id2due) return 0; // confirm their duecolor
// here both have the same duecolor one must change... who?
// 1. let's see if only one can change duecolor
else if ((player[id1].canChangeDuecolor) &&
(!player[id2].canChangeDuecolor) ) return -1;
else if ((!player[id1].canChangeDuecolor) &&
(player[id2].canChangeDuecolor) ) return 1;
// 2. both have same duecolor and can change it,
// let's see the biggest diffcolor to equalize the color
diffcolor1 = 0;
for (j=1; j<=round; j++) diffcolor1 += playerColor[id1][j];
diffcolor2 = 0;
for (j=1; j<=round; j++) diffcolor2 += playerColor[id2][j];
if ( abs(diffcolor1) > abs(diffcolor2) ) return 1;
else if ( abs(diffcolor1) < abs(diffcolor2) ) return -1;
// 3. both have same duecolor and can change it and same diff: see history
else {
j = round;
while (playerColor[id1][j]==playerColor[id2][j] && j>0) j--;
if (j==0) {
// median group or above: duecolor to the higher ranked
if (player[id1].tiebreak[SCORE] > player[id2].tiebreak[SCORE]
&& player[id1].tiebreak[SCORE] >= maxscore) {
return 1;
}
else if (player[id2].tiebreak[SCORE] > player[id1].tiebreak[SCORE]
&& player[id2].tiebreak[SCORE] >= maxscore) {
return -1;
}
// below the median group: duecolor to the lower ranked
else if (player[id1].tiebreak[SCORE] > player[id2].tiebreak[SCORE]
&& player[id1].tiebreak[SCORE] < maxscore) {
return -1;
}
else if (player[id2].tiebreak[SCORE] > player[id1].tiebreak[SCORE]
&& player[id2].tiebreak[SCORE] < maxscore) {
return 1;
}
//same score: will decide the rating as before
// above or median group
if (player[id1].rating > player[id2].rating
&& player[id1].tiebreak[SCORE] >= maxscore ) {
return 1;
}
else if (player[id2].rating > player[id1].rating
&& player [id2].tiebreak[SCORE] >= maxscore ) {
return -1;
}
//same score: below median group
else if (player[id1].rating > player[id2].rating
&& player[id1].tiebreak[SCORE] < maxscore ) {
return -1;
}
else if (player[id2].rating > player[id1].rating
&& player[id2].tiebreak[SCORE] < maxscore ) {
return 1;
}
// same rating, see alphabetical order!
// above or median group
if ( strcmp(player[id1].name,player[id2].name) < 0
&& player[id1].tiebreak[SCORE] >= maxscore ) {
return 1;
}
else if ( strcmp(player[id2].name,player[id1].name) < 0
&& player[id2].tiebreak[SCORE] >= maxscore ) {
return -1;
}
// below median group
else if ( strcmp(player[id1].name,player[id2].name) < 0
&& player[id1].tiebreak[SCORE] < maxscore ) {
return -1;
}
else if ( strcmp(player[id2].name,player[id1].name) < 0
&& player[id2].tiebreak[SCORE] < maxscore ) {
return 1;
}
}
// il primo a cambiare gli viene confermato il proprio duecolor
else if ( player[id1].duecolor && (playerColor[id1][j] == BLACK_COLOR)) return 1;
else if ( (!player[id1].duecolor) && (playerColor[id1][j] == WHITE_COLOR)) return 1;
else return -1;
}
return 0; // fictitious return to remove a silly warning message
}
int RoundData::AssignColor(int id1, int id2, int round)
//
// PURPOSE: determine the color for the players id1 and id2
//
// INPUT VARIABLE
// id1 = player1 with his duecolor
// id2 = player2 with his duecolor
// round = current round
//
// OUTPUT VARIABLE
// 1 to confirm the duecolor of id1 and change that of id2
// 0 to confirm both duecolor
// -1 to confirm the duecolor of id2 and change that of id1
// >1 flag of special operation when color history is the same
//
{ int j=0;
int id1due, id2due;
if (id2==0) return TD.CodifyResult(id1, id2, 3); //return the BYE and the result
if (id1==0) return TD.CodifyResult(id2, id1, 3); //return the BYE and the result
id1due = player[id1].duecolor;
id2due = player[id2].duecolor;
if (id1due != id2due) return 0; // confirm their duecolor
// here both have the same duecolor one must change... who?
// 1. let's see if only one can change duecolor
else if ((player[id1].canChangeDuecolor) &&
(!player[id2].canChangeDuecolor) ) return -1;
else if ((!player[id1].canChangeDuecolor) &&
(player[id2].canChangeDuecolor) ) return 1;
// 2. both have same duecolor and can change it, let's see the diffcolor to equalize
/* diffcolor1 = 0;
for (j=1; j<=round; j++) diffcolor1 += playerColor[id1][j];
diffcolor2 = 0;
for (j=1; j<=round; j++) diffcolor2 += playerColor[id2][j];
if ( abs(diffcolor1) > abs(diffcolor2) ) return 1;
else if ( abs(diffcolor1) < abs(diffcolor2) ) return -1;
*/
if ( abs(player[id1].colorDiff) > abs(player[id2].colorDiff) ) return 1;
else if ( abs(player[id1].colorDiff) < abs(player[id2].colorDiff) ) return -1;
// 3. same diffcolor, let's test the alternation
else { //
j = round;
while (TD.playerColor[id1][j]==TD.playerColor[id2][j] && j>0) j--;
if (j==0) { // same history, let's see highest ARO, rating, etc
if (TD.PLAY_SYSTEM==USCF) {
if (player[id1].tiebreak[SCORE] > player[id2].tiebreak[SCORE]) {
//return CodifyResult(id1, id2, 9);
return 1;
}
else if (player[id2].tiebreak[SCORE] > player[id1].tiebreak[SCORE]) {
//return CodifyResult(id2, id1, 9);
return -1;
}
// same SCORE, let's see max rating
else if (player[id2].rating > player[id1].rating) {
//return CodifyResult(id2, id1, 9);
return -1;
}
else if (player[id1].rating > player[id2].rating) {
//return CodifyResult(id1, id2, 9);
return 1;
}
// same rating, see alphabetical order!
else if ( strcmp(player[id1].name,player[id2].name) < 0 ) {
//return CodifyResult(id1, id2, 9);
return 1;
}
else if ( strcmp(player[id1].name,player[id2].name) > 0 ) {
//return CodifyResult(id2, id1, 9);
return -1;
}
}
else { // dubov, vega
if (player[id1].aro > player[id2].aro) {
return TD.CodifyResult(id1, id2, 9);
}
else if (player[id2].aro > player[id1].aro) {
return TD.CodifyResult(id2, id1, 9);
}
// same ARO, let's see min rating
else if (player[id1].rating < player[id2].rating) {
return TD.CodifyResult(id1, id2, 9);
}
else if (player[id2].rating < player[id1].rating) {
return TD.CodifyResult(id2, id1, 9);
}
// same rating, see alphabetical order!
else if ( strcmp(player[id1].name,player[id2].name) < 0 ) {
return TD.CodifyResult(id1, id2, 9);
}
else if ( strcmp(player[id1].name,player[id2].name) > 0 ) {
return TD.CodifyResult(id2, id1, 9);
}
}
}
// il primo a cambiare gli viene confermato il proprio duecolor
else if ( player[id1].duecolor && (TD.playerColor[id1][j] == BLACK_COLOR)) return 1;
else if ( (!player[id1].duecolor) && (TD.playerColor[id1][j] == WHITE_COLOR)) return 1;
else return -1;
}
return 0; // fictitious return to remove a silly warning message
}
void RoundData::VerifyColor(int round)
//
// PURPOSE: determine the color for each pair of the round 'round'
//
// INPUT VARIABLE
// round = current round
//
{ int i, npairs, id1, id2, res, code, flag;
npairs = TD.pairing[0][round];
for (i=1; i<=npairs; i++)
{ code = TD.pairing[i][round];
TD.DecodeResult(code, &id1, &id2, &res);
// -----------BUG !!!! aggiungi LIM, fatto il 24.10.2006
// il problema si presenta solo nella versione compilata con msc8
if (TD.PLAY_SYSTEM==LIM) flag = AssignColorLIM(id1, id2, round);
else flag = AssignColor(id1, id2, round);
if (flag==1) { // confirm id1 and change id2 color
if (player[id1].duecolor)
{ TD.pairing[i][round] = TD.CodifyResult(id1, id2, 9);
}
else { TD.pairing[i][round] = TD.CodifyResult(id2, id1, 9);
}
}
else if (flag==0) { // confirm both
if (player[id1].duecolor)
{ TD.pairing[i][round] = TD.CodifyResult(id1, id2, 9);
}
else { TD.pairing[i][round] = TD.CodifyResult(id2, id1, 9);
}
}
else if (flag==-1) { // confirm id2 and change id1 color
if (player[id2].duecolor)
{ TD.pairing[i][round] = TD.CodifyResult(id2, id1, 9);
}
else { TD.pairing[i][round] = TD.CodifyResult(id1, id2, 9);
}
}
else if (flag>1) TD.pairing[i][round] = flag;
}
}
void RoundData::DoFirstRound()
//
// PURPOSE: prepare the pairing for the first round
{ int nhalf, ans=1, n2, groupOdd = 0;
int i, k, id, prating, kshift, ratbye=1000000;
int idbye, id1, id2, playerAvailable[N_PLAYER_MAX+1], countAvailable=0;
//if (!RANDOM_SORT) ans = QuestionMessage(sss[S_HPWHI], sss[S_NO], sss[S_YES], NULL);//who get the white?
ans = PromptYesNo(t_("Do you want to assign the WHITE&to the higher rated players?"));
for (i=1; i<=NPlayer; i++)
{ if (player[i].isAvailable == "1") // get only available player
{ countAvailable++;
playerAvailable[countAvailable] = i;
idbye = i; // he is the last available as they are sorted by rating
//playerState[i].canChangeDuecolor = true;
}
}
if (countAvailable & 1) { // if number player odd
if (PLAY_SYSTEM != USCF) pairing[countAvailable/2+1][currentRound] = CodifyResult(idbye, 0, 3);
else { // USCF treatmet
for (k=countAvailable; k>=1; k--)
{ id = playerAvailable[k];
prating = player[id].RATING;
if (prating==0) prating = 10000; //unrated treatment
if (prating < ratbye)
{ idbye = id;
ratbye = prating;
kshift = k;
}
}
for (k=kshift; k<=countAvailable; k++) //remove the bye from the list
{ playerAvailable[k] = playerAvailable[k+1];
}
pairing[countAvailable/2+1][currentRound] = CodifyResult(idbye, 0, 3);
}
groupOdd = 1;
}
nhalf = countAvailable/2;
// set pair and colors for first round; by default the first player has white
if (NAccRound) { // accelerated rounds
n2 = nhalf/2;
for (i=1; i<=n2; i++) // first group made by nhalf player, i.e. n2 pairs
{ id1 = playerAvailable[i];
//if (PLAY_SYSTEM!=BURST) id2 = playerAvailable[i+n2];
//else id2 = playerAvailable[2*n2+1-i];
id2 = playerAvailable[i+n2];
if (ans) { // white at highest rated
if (i & 1) pairing[i][1] = CodifyResult(id1, id2, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id2, id1, 9);
}
else {
if (i & 1) pairing[i][1] = CodifyResult(id2, id1, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id1, id2, 9);
}
}
for (i=n2+1; i<=nhalf; i++) // second group made by nhalf player, i.e. n2 pairs
{ id1 = playerAvailable[i + n2];
if (PLAY_SYSTEM!=BURST) id2 = playerAvailable[i + nhalf];
else id2 = playerAvailable[2*nhalf+n2+1-i];
if (ans) { // white at highest rated
if (i & 1) pairing[i][1] = CodifyResult(id1, id2, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id2, id1, 9);
}
else {
if (i & 1) pairing[i][1] = CodifyResult(id2, id1, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id1, id2, 9);
}
}
}
else { // not accelerated rounds
for (i=1; i<=nhalf; i++)
{ id1 = playerAvailable[i];
//if (PLAY_SYSTEM!=BURST) id2 = playerAvailable[i+nhalf];
//else id2 = playerAvailable[2*nhalf+1-i];
id2 = playerAvailable[i+nhalf];
if (ans) { // white at highest rated
if (i & 1) pairing[i][1] = CodifyResult(id1, id2, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id2, id1, 9);
}
else {
if (i & 1) pairing[i][1] = CodifyResult(id2, id1, 9); // coppie dispari
else pairing[i][1] = CodifyResult(id1, id2, 9);
}
}
}
//----------- adesso aggiungere le coppie formate da chi ha avuto il BYE ---------!!!
// save the number of pairs
if (groupOdd) pairing[0][1] = nhalf+1;
else pairing[0][1] = nhalf;
//set the players that got a BYE
for (i=1; i<=NPlayer; i++) {
if ( IsNull(player[i].isAvailable) ) { // get byed player
playerOpponent[i][currentRound] = 0; // BYE assigned
roundResult[i][currentRound] = 3; // result 1F-0
playerColor[i][currentRound] = 0; // no-color
}
}
}