#include #include "Tournament.h" #include "pairing88.h" //extern ofstream verbosefile; /* Generazione di abbinamenti per un torneo di scacchi a sistema Svizzero. - Contiene dei controlli per evitare loop: ogni giocatore non pu� avere pi di n-1 incompatibilit�in un gruppo di n giocatori - Ricorda i giocatori scelti in occasione di ogni accoppiamento - Tiene traccia del miglior accoppiamento parziale qualora l'accoppiamento complessivo non possa essere realizzato */ extern int CanPlayWith(int player1, int player2, int round); /* * -------- class implementation --------------- */ // // This is the engine that produce the pairing. I am proude of it!!! :-) // It Realizes the pairing of 'np' players put on 2 columns as S1 and S2 in // the FIDE handbook . // It return the numebr of pair done, 'nmade' on a maximum np/2. // Se l'abbinamento e' riuscito vi saranno n_partial=n/2 coppie fatte. // The numbers of floaters will be n_floaters = np-2*nmade // int TPairingDubov::pairing(void) { int i, j, l, n_couple, sum, found; int pairing_possible = 1, max_pair; int count, i_player, j_player, checkCompatibility=0; int ll, opponent, i_player_last, j_player_last; int n_partial=0; //pair at the moment int avoid[LIMIT+1]; resetplayerFlag(IsPlayerFree, np); resetchallengerFlag(challengerFlag, np); if (np_s1==0) { // build the opponent list for each player in the case np_s1=0 for (i=1; i<=np2; i++) { // the last player is not considered count = 0; // counter of the compatible players // verbosefile << "player " << idpl[i] << ":"; for (j=1; j<=np2; j++) { // prima meta' del vettore opponent = challengerFlag[j]; // opponent list if (CanPlayWith(idpl[i], idpl[ opponent ], nround)) { count++; remind[count] = opponent; } } for (j=np2+i; j<=np; j++) { // seconda meta' opponent = challengerFlag[j]; // opponent list if (CanPlayWith(idpl[i], idpl[ opponent ], nround)) { count++; remind[count] = opponent; } } remind[0] = count; /* for (l=1; l<=count; l++) { verbosefile << idpl[ remind[l] ] <<"; "; } verbosefile << endl; */ // allocate space for a vector that store 'remind', that is the opponent list sss[i] = (unsigned int *) calloc(count+1, sizeof(unsigned int) ); // verbosefile << "opps= " << count << " -> "; for (l=0; l<=count; l++) { sss[i][l] = remind[l]; //store remind //if (l>0) verbosefile << idpl[ sss[i][l] ] <<", "; } //verbosefile << endl; } for (i=np2+1; i<=np-1; i++) { // the last player is not considered count = 0; // counter of the compatible players // verbosefile << "player " << idpl[i] << ":"; for (j=np2; j>i-np2; j--) { opponent = challengerFlag[j]; // opponent list if (CanPlayWith(idpl[i], idpl[ opponent ], nround)) { count++; remind[count] = opponent; } } remind[0] = count; //for (l=1; l<=count; l++) { // verbosefile << idpl[ remind[l] ] <<"; "; //} //verbosefile << endl; // allocate space for a vector that store 'remind', that is the opponent list sss[i] = (unsigned int *) calloc(count+1, sizeof(unsigned int) ); // verbosefile << "opps= " << count << " -> "; for (l=0; l<=count; l++) { sss[i][l] = remind[l]; //store remind //if (l>0) verbosefile << idpl[ sss[i][l] ] <<", "; } //verbosefile << endl; } // last element need a special treatment because he has no opponent sss[np] = (unsigned int *) calloc(1, sizeof(unsigned int) ); sss[np][0] = 0; } else { // np_s1>0 // build the opponent list for each player in the case np_s1=0 for (i=1; i<=np_s1; i++) { count = 0; // counter of the compatible players //verbosefile << "player " << idpl[i] << ":"; for (j=1; j<=np2; j++) { opponent = challengerFlag[j]; // opponent list if (CanPlayWith(idpl[i], idpl[ opponent ], nround)) { count++; remind[count] = opponent; } } remind[0] = count; /* for (l=1; l<=count; l++) { verbosefile << idpl[ sss[i][l] ] <<"; "; } verbosefile << endl; */ // allocate space for a vector that store 'remind', that is the opponent list sss[i] = (unsigned int *) calloc(count+1, sizeof(unsigned int) ); //verbosefile << "opps= " << count << " -> "; for (l=0; l<=count; l++) { sss[i][l] = remind[l]; //store remind //if (l>0) verbosefile<< idpl[ sss[i][l] ] <<","; } //verbosefile < " << endl; } } // reset the cursor of each vector_challenger for (i=1; i<=np; i++) curs_position[i] = 0; // reset the array that remind the destroyed pairing for (i=0; i<=LIMIT; i++) avoid[i] = 0; // reset the pair matrix for (i=1; i<=np2; i++) for (j=0; j<=1; j++) { pair[i][j] = 0; } max_pair = np2; // massimo numero di coppie possibile: sono np/2 se S1=S2 // altrimenti np_s1 se S1maximum_possible_pair) { for (l=1; l<=maximum_possible_pair; l++) { partial_pair[l][0] = pair[l][0]; partial_pair[l][1] = pair[l][1]; } return maximum_possible_pair; } //if (np_s1) i_player = findPlayer(IsPlayerFree, np_s1+1); //else i_player = findPlayer(IsPlayerFree, np); //verbosefile <<"Found " <=np) { verbosefile <0 imply i_player= LIMIT) { //if (IS_SET_VERBOSE) verbosefile <<" LIMIT REACHED... going out...\n"; Exclamation(" The iteration limit has been reached.&I am going out..."); flag_limit = 1; return n_partial; } for (ll=1; ll<=n_couple-1; ll++) avoid[ avoid[0] ] += pair[ll][0] * pair[ll][1]; checkCompatibility = 1; // flag to force the check on the next pair after the restart n_couple = n_couple - 2; // restore the flags of IsPlayerFree[] resetplayerFlag(IsPlayerFree, np); // restore IsPlayerFree[] of incompatibility for (ll=1; ll<=n_couple; ll++) { i_player_last = pair[ll][0]; IsPlayerFree[i_player_last] = 0; //curs_position[i_player_last] = 0; j_player_last = pair[ll][1]; IsPlayerFree[j_player_last] = 0; //curs_position[j_player_last] = 0; } n_couple++; //restart the pairing from N-1 } } } if (pairing_possible) return max_pair; else return n_partial; } // set to 1 all the elements of the vector void TPairingDubov::resetplayerFlag(int vector[], int n) { int i; for (i=1; i<=n; i++) vector[i] = 1; // 1 = not busy // if ( idpl[ vector[np2] ] == -1 && np>2) vector[np2+1] = 0; // ????????? if ( idpl[ vector[np2] ] == -1 ) vector[np2] = 0; // ????????? } void TPairingDubov::resetchallengerFlag(int vector[], int n) { int i; if (np_s1) { // ci sono meno giocatori in S1 che in S2 for (i=1; i<=np2; i++) vector[i] = np2+i; // for (i=n; i>np2; i--) vector[i] = n-i+1; for (i=np2+1; i<=n; i++) vector[i] = i - np2; // fixed bug CONTROLLARE // rimuove np_s1 giocatori dal challengerflag per evitare incontri tra giocatori di S1 for (i=n; i > np2; i--) vector[i] = 0; } else { for (i=1; i<=np2; i++) vector[i] = np2+i; // for (i=n; i>np2; i--) vector[i] = n-i+1; for (i=np2+1; i<=n; i++) vector[i] = i - np2; // fixed bug CONTROLLARE } //for (l=1; l<=n; l++) verbosefile << idpl[ vector[l] ] <<", "; verbosefile << endl; } // get the next free row in which find the player i_th int TPairingDubov::findPlayer(int index[], int n) { int r=1; while ( ( index[r]==0 || sss[r][0]==0 ) && rsss[i][0] ) { // overcame the limit curs_position[i] = 0; // restart the cursor from zero; return 0; // no player found => player i_th not compatible with anybody } else { curs_position[i] = j; // adjourn the cursor return sss[i][j]; } return 0; // fictitious return; } int TPairingDubov::dopairingMax(int nplayer, int npair_max, int idplayers[], int S1_S2[][2], int arrfloat[], int arrpartial[][2], int round) // // PURPOSE: This is the driver of the routine pairing. It looks for the floaters // The players enter in two columns in idplayers. The final pairing is put // in S1_S2 // // INPUT // nplayer = total players to be paired // npair_max = maximum pairs that it is expected to obtain ( less or equal to nplayer/2 ) // idplayers[] = vector containg the ID of the nplayers players // S1_S2[][2] = will contain the final pairs on success // arrfloat[] = will contain the eventual floaters // arrpartial[][2] = will contain the pairs if the floaters are met // round = current round // // OUTPUT // return the number of pairs done: they are nplayers/2 if there are no // floaters, otherwise they are less than nplayers/2. // { int i; int count_floaters = 0; int id; //------------- np = nplayer; // e' globale np2 = (int) np/2; // e' globale np_s1 = 0; // e' globale e se zero significa S1 = S2 maximum_possible_pair = npair_max; // e' globale for (i=1; i<=np; i++) idpl[i] = idplayers[i]; // now is made global nround = round; // now is global //------------- nmade = pairing(); // look up pair if ( nmade == np2 ) // no floaters: reached the maximum pairs possible { n_floaters = 0; for (i=1; i<=np2; i++) { id = pair[i][0]; S1_S2[i][0] = idplayers[id]; id = pair[i][1]; S1_S2[i][1] = idplayers[id]; } arrfloat[0] = 0; // no floaters } else // floaters treatment { n_floaters = 2*(np2-nmade); for (i=1; i<=np; i++) mask[i] = 1; for (i=1; i<=nmade; i++) { // let emerge the the floaters, they aren't in partial and in mask are denoted with 1 mask[ partial_pair[i][0] ] = 0; mask[ partial_pair[i][1] ] = 0; } for (i=1; i<=np; i++) { if (mask[i] == 1) { count_floaters++; arrfloat[count_floaters] = i; } } } if (n_floaters) { // set partial_pair array arrfloat[0] = n_floaters; for (i=1; i<=nmade; i++) { id = partial_pair[i][0]; arrpartial[i][0] = idplayers[id]; id = partial_pair[i][1]; arrpartial[i][1]= idplayers[id]; } // set floaters looking up their real id for (i=1; i<=n_floaters; i++) { id = arrfloat[i]; arrfloat[i] = idplayers[id]; } } for (i=1; i<=np; i++) if (sss[i] != NULL) free(sss[i]); if (flag_limit) return -nmade; else return nmade; } int TPairingDubov::dopairingFixed(int nplayer, int nplayer_s1, int idplayers[], int S1_S2[][2], int round) // // PURPOSE: This is the driver of the routine pairing. It looks for the floaters // The players enter in two columns in idplayers. The final pairing is put // in S1_S2 // // INPUT // nplayer = total players to be paired // player_s1 = players to pair in S1 // idplayers[] = vector containg the ID of the nplayers players // S1_S2[][2] = will contain the final pairs on success // round = current round // // OUTPUT // return the number of pairs done: they are nplayers/2 if there are no // floaters, otherwise they are less than nplayers/2. // { int i; int id; //------------- np = nplayer; // e' globale np2 = np/2; // e' globale np_s1 = maximum_possible_pair = nplayer_s1; // e' globale S1 < S2 => np_s1 < np_s2 for (i=1; i<=np; i++) idpl[i] = idplayers[i]; // now is made global nround = round; // now is global //------------- nmade = pairing(); // look up pair if ( nmade == np_s1 ) { for (i=1; i<=np_s1; i++) { id = pair[i][0]; S1_S2[i][0] = idplayers[id]; id = pair[i][1]; S1_S2[i][1] = idplayers[id]; } } else nmade = 0; // l'accoppiamento e' stato impossibile for (i=1; i<=np_s1; i++) delete sss[i]; return nmade; } //------------------- end implementazione TPairingDubov ------------------- //------------------- Start implementazione TPairingLim ------------------- int TPairingLim::pairingLIM() { int i, j, l, n_couple, sum, found; int pairing_possible = 1, max_pair; int count, i_player, j_player, checkCompatibility=0; int ll, opponent, i_player_last, j_player_last; int n_partial=0; //pair at the moment int avoid[LIMIT+1]; int opponentlist[N_PLAYER_MAX+1]; int typefloater; resetplayerFlag(IsPlayerFree, np); // reset the sss matrix to null for (i=1; i<=np; i++) sss[i] = NULL; // reset the cursor of each vector_challenger for (i=1; i<=np; i++) curs_position[i] = 0; // reset the array that remind the destroyed pairing for (i=0; i<=LIMIT; i++) avoid[i] = 0; // reset the pair matrix for (i=1; i<=np2; i++) for (j=0; j<=1; j++) { pair[i][j] = 0; } //verbosefile <<"group with points " << scoregroup<maximum_possible_pair) { // go to finish for (l=1; l<=maximum_possible_pair; l++) { partial_pair[l][0] = pair[l][0]; partial_pair[l][1] = pair[l][1]; } return maximum_possible_pair; } if (TD.IS_SET_VERBOSE) verbosefile <<" pair " <0) verbosefile << idpl[ sss[i_player][l] ] <<", "; } LABEL100: if (i_player<=np) j_player = findChallenger( i_player, np); else j_player = 0; // destroy the last good couple if (TD.IS_SET_VERBOSE) { if (j_player) verbosefile <<" try opponent " << idpl[j_player]<< "\n"; else verbosefile <<" has no suitable opponent! restart... " << "\n"; } found=0; if (j_player) { // j_player>0 imply i_player= LIMIT) { Exclamation(" The iteration limit has been reached.&I am going out..."); //----if (IS_SET_VERBOSE) verbosefile <<" LIMIT REACHED... going out...\n"; flag_limit = 1; return n_partial; } for (ll=1; ll<=n_couple-1; ll++) avoid[ avoid[0] ] += pair[ll][0] * pair[ll][1]; checkCompatibility = 1; // flag to force the check on the next pair after the restart n_couple = n_couple - 2; // restore the flags of IsPlayerFree[] resetplayerFlag(IsPlayerFree, np); // restore IsPlayerFree[] before of incompatibility for (ll=1; ll<=n_couple; ll++) { i_player_last = pair[ll][0]; IsPlayerFree[i_player_last] = 0; //curs_position[i_player_last] = 0; j_player_last = pair[ll][1]; IsPlayerFree[j_player_last] = 0; //curs_position[j_player_last] = 0; } n_couple++; //restart the pairing from N-1 } } } if (pairing_possible) return max_pair; else return n_partial; } // get the next free row in which find the player i_th int TPairingLim::findPlayerLIM(int index[], int n, int *typeFloater) { int r; r=1; // look for downfloater from left to right while ( index[r]==0 && rscoregroup) { // found downfloater *typeFloater = DOWNFLOATER; return r; } r=n; // look for upfloater from right to left while ( index[r]==0 && r>1 ) r--; if (player[ idpl[r] ].tiebreak[SCORE]1 ) r--; *typeFloater = STANDARD; return r; } } void TPairingLim::makevectorchallengers(int id, int freeplayer[], int challengers[], int floaterType) { int i, count = 0, aux, m; int x, y, t, duec; // grab the remained unpaired players. switch (floaterType) { case STANDARD: // STANDARD TREATMENT: player id is NOT a floater if (DOWNWARD) { // moving downward get all unpaired players from left to right // 1,2,3,4, 5,6,7,8 for (i=1; i<=np; i++) { if (freeplayer[i]) { count++; challengers[count] = i; } } // Exchange the bottom half with the top half // 5,6,7,8 1,2,3,4, m = count/2; for (i=1; i<=m; i++) { aux = challengers[i]; challengers[i] = challengers[i+m]; challengers[i+m] = aux; } // revert the order of the bottom half // 5,6,7,8 3,4,1,2, for (i=1; i<=m/2; i++) { aux = challengers[i+m]; challengers[i+m] = challengers[count + 1 -i]; challengers[count + 1 -i] = aux; } } else { // moving upward get all unpaired players from right to left // 1,2,3,4, 5,6,7,8 it is the final wanted order! for (i=1; i<=np; i++) { if (freeplayer[i]) { count++; challengers[count] = i; } } // revert the order of the top half // 4,3,1,2, 5,6,7,8 it is the final wanted order! m = count/2; for (i=1; i<=m/2; i++) { aux = challengers[i]; challengers[i] = challengers[m + 1 -i]; challengers[m + 1 -i] = aux; } } break; case DOWNFLOATER: // DOWNFLOATER TREATMENT: player id is a downfloater // ..... no sort, just the actual rating order in descendent order if (TD.IS_SET_VERBOSE) verbosefile <<"(downfloater) " ; for (i=1; i<=np; i++) { if (freeplayer[i]){ count++; challengers[count] = i; } } break; case UPFLOATER: // UPFLOATER TREATMENT: player id is an upfloater // ..... no sort, grab the remained player from the lowest score-rated to // the highest rated, i.e. the reverse order if (TD.IS_SET_VERBOSE) verbosefile <<"(upfloater) "; for (i=np; i>=1; i--) { if (freeplayer[i]) { count++; challengers[count] = i; } } break; } // sort the challengers depending on the due color of player id duec=player[ idpl[id] ].duecolor;; if (duec == -1) { // if duecolor neutral then do not sort the color challengers[0] = count; return; } y=2; while ( y<=count) { if ( player[ idpl[challengers[y]] ].duecolor == duec ) y++; else { // found a different duecolor that must be brought up // if this do not alter the ranking score x = y; while (x>1) { if (player[ idpl[challengers[x-1]] ].duecolor == duec && player[ idpl[challengers[x-1]] ].tiebreak[SCORE]==player[ idpl[challengers[x]] ].tiebreak[SCORE]) { t = challengers[x-1]; challengers[x-1] = challengers[x]; challengers[x] = t; x--;} else break; } y++; } } challengers[0] = count; } int TPairingLim::dopairingMax(int nplayer, int npair_max, int idplayers[], int S1_S2[][2], int arrfloat[], int arrpartial[][2], int round, float SCOREGROUP, String& verbose) // // PURPOSE: This is the driver of the routine pairing. It looks for the floaters // The players enter in two columns in idplayers. The final pairing is put // in S1_S2 // // INPUT // nplayer = total players to be paired // npair_max = maximum pairs that it is expected to obtain ( less or equal to nplayer/2 ) // idplayers[] = vector containg the ID of the nplayers players // S1_S2[][2] = will contain the final pairs on success // arrfloat[] = will contain the eventual floaters // arrpartial[][2] = will contain the pairs if the floaters are met // round = current round // // OUTPUT // return the number of pairs done: they are nplayers/2 if there are no // floaters, otherwise they are less than nplayers/2. // { int i; int count_floaters = 0; int id; verbosefile = ""; //------------- np = nplayer; // e' globale np2 = (int) np/2; // e' globale np_s1 = 0; // e' globale e se zero significa S1 = S2 maximum_possible_pair = npair_max; // e' globale for (i=1; i<=np; i++) idpl[i] = idplayers[i]; // now is made global nround = round; // now is global //------------- // Lim treatment : check scoregroup scoregroup = SCOREGROUP; //score of the group we are considering if ( SCOREGROUP >= (round-1)*TD.WON/2.) DOWNWARD=1; else DOWNWARD=0; nmade = pairingLIM(); // look up pair if ( nmade == np2 ) // no floaters: reached the maximum pairs possible { n_floaters = 0; for (i=1; i<=np2; i++) { id = pair[i][0]; S1_S2[i][0] = idplayers[id]; id = pair[i][1]; S1_S2[i][1] = idplayers[id]; } arrfloat[0] = 0; // no floaters } else // floaters treatment { n_floaters = 2*(np2-nmade); for (i=1; i<=np; i++) mask[i] = 1; for (i=1; i<=nmade; i++) { // let emerge the the floaters, they aren't in partial and in mask are denoted with 1 mask[ partial_pair[i][0] ] = 0; mask[ partial_pair[i][1] ] = 0; } for (i=1; i<=np; i++) { if (mask[i] == 1) { count_floaters++; arrfloat[count_floaters] = i; } } } if (n_floaters) { // set partial_pair array arrfloat[0] = n_floaters; for (i=1; i<=nmade; i++) { id = partial_pair[i][0]; arrpartial[i][0] = idplayers[id]; id = partial_pair[i][1]; arrpartial[i][1]= idplayers[id]; } // set floaters looking up their real id for (i=1; i<=n_floaters; i++) { id = arrfloat[i]; arrfloat[i] = idplayers[id]; } } for (i=1; i<=np; i++) if (sss[i] != NULL) free(sss[i]); verbose = verbosefile; if (flag_limit) return -nmade; else return nmade; }