Frage zu Elo-System



  • Hi,

    ich versuche momentan das Elo-System zu verstehen. Naja "eig." recht Simpel 🙂

    Nun gut folgende Formel:

    Rn = Ro + C * (S - Se) (1)

    Rn = new rating
    Ro = old rating
    S = score (1.0)
    Se = expected score (table)
    C = constant

    ----------------

    Elo

    diff Expected score
    0 0.50
    20 0.53
    40 0.58
    60 0.62
    80 0.66
    100 0.69
    120 0.73
    140 0.76
    160 0.79
    180 0.82
    200 0.84
    300 0.93
    400 0.97
    ... ...
    Table 1: Expected score

    Es gibt tausend von verschiedenen möglichkeiten für diff und die Expected score!!!

    Nun Frage:
    Wie berechne ich jedoch die Expected score ?



  • keine ahnung, ob es dir hilft, aber in der unverbesserlichen annahme, daß du letztendlich die mathematischen infos benutzen magst, um ein programm zu schreiben, puste ich mal meinen code:

    #include "Tournier.h"
    
    #include <assert.h>
    #include <conio.h>
    #include <iostream>
    #include <fstream>
    #include <math.h>
    #include <stdlib.h>
    #include <windows.h>
    
    #include "Spielleiter.h"
    
    using namespace std;
    
    Spieler* Tournier::alleSpieler[MAX_ANZ];
    int Tournier::spielerAnz=0;
    
    double siegWahrscheinlichkeit(double d)
    {
       return 1/(1+pow(10,-d/400));
    }
    double verlustWahrscheinlichkeit(double d)
    {
       return 1-siegWahrscheinlichkeit(d);
    }
    
    void Tournier::anmelden(Spieler *spieler)
    {
       assert(spielerAnz<MAX_ANZ);
       spieler->eloPunkte=0;
       alleSpieler[spielerAnz]=spieler;
       ++spielerAnz;
    }
    void Tournier::abmelden(Spieler *spieler)
    {
       for(int i=0;i<spielerAnz;++i)
       {
          if(alleSpieler[i]==spieler)
          {
             --spielerAnz;
             alleSpieler[i]=alleSpieler[spielerAnz];
             return;
          }
       }
       assert(0);
    }
    
    void Tournier::punkteLaden()
    {
       ifstream in("elo.txt");
       while(in)
       {
          string name;
          double punkte;
          getline(in,name);
          in>>punkte;
          Spieler *s=getSpieler(name);
          if(s!=0)
             s->eloPunkte=punkte;
          getline(in,name);
    	}
       if(getSpieler("Zufall"))
    		getSpieler("Zufall")->eloPunkte=1000;
    }
    void Tournier::punkteSpeichern()
    {
       ofstream out("elo.txt");
       for(int i=0;i<spielerAnz;++i)
       {
          if(alleSpieler[i]->getName()!="Test")
          {
             out<<alleSpieler[i]->getName()<<endl;
             out<<alleSpieler[i]->eloPunkte<<endl;
          }
       }
    }
    void Tournier::ranglisteZeigen()
    {
       ofstream out("rangliste.js");
    out<<"document.write(\"<table border>\");\n";
    out<<"document.write(\"<th>Rang</th>\");\n";
    out<<"document.write(\"<th>elo-Punkte</th>\");\n";
    out<<"document.write(\"<th>Name</th>\");\n";
       out<<"document.write(\"<th>Autor</th>\");\n";
       cout<<"Rangliste"<<endl;
       for(int i=0;i<spielerAnz;++i)
          if(alleSpieler[i]->eloPunkte!=0)
          {
             cout<<i+1<<". mit "<<int(alleSpieler[i]->eloPunkte)<<" elo-Punkten "<<alleSpieler[i]->getName()<<endl;
             out<<"document.write(\"<tr>\");\n";
             out<<"document.write(\"<td>"<<i+1<<"</td>\");\n";
             out<<"document.write(\"<td>"<<int(alleSpieler[i]->eloPunkte)<<"</td>\");\n";
             out<<"document.write(\"<td>"<<alleSpieler[i]->getName()<<"</td>\");\n";
             out<<"document.write(\"<td>"<<alleSpieler[i]->getAutor()<<"</td>\");\n";
             out<<"document.write(\"</tr>\");\n";
          }
          out<<"document.write(\"</table>\");\n";
          cout<<endl;
    }
    void Tournier::punkteSortieren()
    {
       for(int i=0;i<spielerAnz-1;++i)
          for(int j=i+1;j<spielerAnz;++j)
             if(alleSpieler[i]->eloPunkte<alleSpieler[j]->eloPunkte)
                swap(alleSpieler[i],alleSpieler[j]);
    }
    void Tournier::neuBewertung(Spieler *spieler,bool show)
    {
       int spieleAnz=10;
       cout<<"Der Spieler "<<spieler->getName()<<" hat noch keine elo-Bewertung.\n";
       cout<<"Er spielt jetzt gegen alle bereits bewerteten Spieler "<<spieleAnz<<" Spiele...\n";
       double gesamtSumme=0;
       for(int s=0;s<spielerAnz;++s)
       {
          if(alleSpieler[s]->eloPunkte!=0)
          {
             double summe=0;
             Spielleiter spielleiter;
             for(int i=0;i<spieleAnz;++i)
             {
                int gewonnen;
                if(i>=spieleAnz/2)
                {
                   gewonnen=spielleiter.start(spieler,alleSpieler[s],show,"");
                   if(gewonnen==WEISS)
                      summe+=1;
                   else if(gewonnen==KEINER)
                      summe+=0.5;
                   else
                      summe+=0;
                }
                else
                {
                   gewonnen=spielleiter.start(alleSpieler[s],spieler,show,"");
                   if(gewonnen==WEISS)
                      summe+=0;
                   else if(gewonnen==KEINER)
                      summe+=0.5;
                   else
                      summe+=1;
                }
                cout<<alleSpieler[s]->getName()<<" "<<summe<<"/"<<i+1<<"    \r";
             }
             gesamtSumme+=summe;
          }
          cout<<endl;
       }
       double eloAlt=0,eloNeu=1000;
       while(int(eloAlt)!=int(eloNeu))
       {
          double we=0;
          eloAlt=eloNeu;
          int gegner=0;
          for(s=0;s<spielerAnz;++s)
          {
             if(alleSpieler[s]->eloPunkte!=0)
             {
                we+=siegWahrscheinlichkeit(eloAlt-alleSpieler[s]->eloPunkte)*spieleAnz;
             }
             ++gegner;
          }
          eloNeu=eloAlt+(gesamtSumme-we)*800/(gegner*spieleAnz);
       }
       spieler->eloPunkte=eloNeu;
       punkteSortieren();
       ranglisteZeigen();
    }
    void Tournier::neuBewertungen(bool show)
    {
       for(int i=0;i<spielerAnz;++i)
          if(alleSpieler[i]->eloPunkte==0)
             neuBewertung(alleSpieler[i],show);
    }
    void Tournier::start(bool show)
    {
       SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST);
       punkteLaden();
       punkteSortieren();
       ranglisteZeigen();
       neuBewertungen(show);
    
       const int SPIELE=1000;
       int punkte[MAX_ANZ][MAX_ANZ];
       {//Punkte auf 0 setzen
          for(int n1=0;n1<spielerAnz;++n1)
             for(int n2=0;n2<spielerAnz;++n2)
                punkte[n1][n2]=0;
       }
       {//Tournier durchführen
          //cout<<"Tournier"<<endl;
          Spielleiter spielleiter;
          for(int n1=0;n1<spielerAnz;++n1)
          {
             Spieler *s1=alleSpieler[n1];
             for(int n2=0;n2<spielerAnz;++n2)
             {
                Spieler *s2=alleSpieler[n2];
                if(n1!=n2)
                {
                   for(int i=0;i<SPIELE/2;++i)
                   {
                      int ergebnis=spielleiter.start(s1,s2,show,"");
                      if(show)
                         Sleep(1000);
                      punkte[n1][n2]+=1+ergebnis;
                      punkte[n2][n1]+=1-ergebnis;
                   }
                   cout<<punkte[n1][n2]/2.0<<'\t';
                }
                else
                   cout<<"-\t";
             }
             cout<<endl;
          }
       }
       double eloPunkteNeu[MAX_ANZ];
       {
          const double k=.1;//200.0/(20+SPIELE);
          for(int n1=0;n1<spielerAnz;++n1)
          {
             double w=0,we=0;
             for(int n2=0;n2<spielerAnz;++n2)
             {
                if(n2!=n1)
                {
                   w+=punkte[n1][n2]/2.0;
                   we+=siegWahrscheinlichkeit(alleSpieler[n1]->eloPunkte-alleSpieler[n2]->eloPunkte)*SPIELE;
                }
             }
             eloPunkteNeu[n1]=alleSpieler[n1]->eloPunkte+(w-we)*k;
          }
       }
       {
          for(int n1=0;n1<spielerAnz;++n1)
          {
             alleSpieler[n1]->eloPunkte=eloPunkteNeu[n1];
             if(alleSpieler[n1]->getName()=="Zufall")
                alleSpieler[n1]->eloPunkte=1000;
          }
       }
       punkteSortieren();
       ranglisteZeigen();
       punkteSpeichern();
    }
    


  • Hi,

    thx!

    Hät auch das gereicht ! ..

    double siegWahrscheinlichkeit(double d)
    {
    return 1/(1+pow(10,-d/400));
    }

    Cu



  • Jayson schrieb:

    Hät auch das gereicht ! ..

    double siegWahrscheinlichkeit(double d)
    {
    return 1/(1+pow(10,-d/400));
    }

    ok.
    die formel ist nicht total genau exakt. für was total genaues, hätte ich ich dieses komische ∫-zeichen gebraucht, und da weiß ich nicht, wie die c++-funktion heißt.


Anmelden zum Antworten