Vraag aan slimme dammende php- en mysql programmeurs.
Zoals sommigen wel weten is programmeren niet mijn beroep. Het maken van php-scripts en mysql-query’s heb ik me van forums (bijv.
http://www.phpfreakz.nl) wat aangeleerd en is een leuke hobby en houd je van de straat.
Gevolg is wel dat flink wat scripts in Toernooibase omslachtig zullen zijn en inefficiënt.
Vanaf eind december ben ik van tijd tot tijd bezig geweest de nieuwe TPR-berekening methode Wouter Ludwig (zoals ik deze maar noem) bij een Zwitsers toernooi voor Toernooibase geschikt te krijgen. Dit in verband met de NK Kwalificatie.
In de testomgeving heb ik een werkende methode, maar deze duurt gewoon te lang (zo ongeveer 10 seconden) met veel opvraag en updates in de database. Dat kan dus niet in de live-omgeving. En dat zint me eigenlijk niet.
Ik leg een beetje uit hoe ik tot dusver te werk ben gegaan.
- allereerst breng ik de ingevoerde wedstrijden van een toernooi vanuit een tabel waarin alle uitslagen van detailwedstrijden in Toernooibase zijn opgeslagen in een temporary tabel. (dan ga ik van zo’n 345.000 records naar maximaal 96 (8x12) records bij de NK Kwalificatie. Lijkt me efficiënt).
- In deze temporary tabel voeg ik de gebruikte rating van de spelers toe.
- Ik maak ook een ranglijst in een temporary table (zou misschien beter in een array kunnen) op basis van behaalde punten en zet daarin ook de totale weerstandrating van een speler.
- Op basis van die tabel kan ik vervolgens met behulp van de ratingtabel opgeslagen in Toernooibase de TPR op basis van gemiddelde weerstand berekenen. Dat betekent het percentage berekenen van de behaalde score, dit in de ratingtabel aflezen, het ratingverschil bij de gemiddelde tegenstandersrating optellen of aftrekken en je hebt de TPR op basis van gemiddelde tegenstandersrating.
- Dat doe ik met hetzelfde principe ook voor de huidige ratinglijsten en wordt ook bij een speler bij zijn details bij een toernooi (als je op de spelersnaam klikt, getoond. Dus alles op basis van gemiddelde tegenstandersrating).
- Deze TPR, alsmede het gewone aantal behaalde punten sla ik op bij de basisgegevens (basistabel) van de speler bij het toernooi (dus in de database).
Dan moet ik de slag naar de methode TPR Wouter Ludwig maken. Dat wordt ingewikkeld met veel meer acties. Dat doe ik als volgt:
Op basis van deze eerste TPR per speler (op basis van gemiddelde tegenstandersrating) bereken ik aan de hand van de ratingtabel bij elke detailwedstrijd (dus nu ga ik naar een individuele berekening per tegenstander) de normscore. Dat is dus al een flinke opvraagsessie naar de ratingtabel. Het totaal van de normscores sla ik dan weer op in de basistabel van het toernooi.
Vervolgens maak ik een loop van 7 stappen. (Ai, dat wordt een zware belasting).
Afhankelijk van het verschil tussen behaalde score en normscore verlaag ik of verhoog ik de eerste TPR met 16 punten (uiteindelijk moet het verschil tussen behaalde score en normscore 0 zijn – een onbereikbaar ideaal – maar in ieder geval minimaal zijn).
Vervolgens bereken ik op basis van die nieuwe TPR opnieuw de individuele normscores (weer veel opvraagacties naar ratingtabel) en sla de nieuwe TPR op in de database met het totaal van de normscores. In de loop maak ik vervolgens het ratingverschil steeds kleiner met 2 punten (dus wordt 14, 12, 10 etc.). Ik heb een tolerantienorm van verschil tussen werkelijk behaalde score en normscores van 0.02 ingebouwd. Als het verschil minder dan die 0.02 is sla ik de desbetreffende speler over (c.q. geen update meer in database), en ga verder met volgende spelers, totdat iedereen voldoet (of zou moeten voldoen) aan die tolerantie van 0.02.
Daarna ga ik finetunen. Dat doe ik in een loop van 3 stappen (met dezelfde constructie als in de loop van 7 stappen).
De tolerantiegrens zet ik naar 0.00999. Ik verhoog of verlaag de opgeslagen TPR met 1 punt. Voldoet de tolerantiegrens, dan wordt de TPR weer definitief.
Vervolgens blijft er nog 1 stap over. Spelers waar het verschil tussen berekende normscores en behaalde score hoger blijft dan 0.00999.
Ik bereken daarbij dan het verschil tussen normscores en behaalde scores voor twee naastliggende TPRs.
Waar het verschil tussen de normscores en behaalde scores dan het kleinst is wordt de definitieve TPR (methode Wouter Ludwig) en wordt opgeslagen in de database.
Daarna is de sortering natuurlijk een fluitje van een cent. Behaalde opgeslagen punten en opgeslagen TPR en klaar is Kees. (en ook WP en SB als extra criteriums nog berekenen, al heeft dit volgens mij vrijwel geen invloed bij de NK Kwalificatie methode Wouter Ludwig).
Dus zo’n 11 stappen met loops (en dus query’s die in een loop zitten en veel opvraag en update acties in die database) om die TPR te berekenen.
Oh ja, een bijkomstigheid is nog eventjes ook dat als een speler een 0% resultaat (0 punten) heeft of een 100% resultaat (alles gewonnen) er een remise tegen zichzelf in de berekening opgenomen moet worden.
Waar is denk ik de winst te behalen (efficiëntie en tijdwinst):
Allereerst denk ik dat als je een functie of berekening van de normaalverdeling kunt maken (zoals Guido dat doet in zijn Excel-sheet, dat hij bij het topic NK Kwalificatie 2012 heeft geplaatst) in plaats van telkens een opvraag te doen in de database op de ratingtabel voor het verschil tussen TPR en rating van de tegenstander om de normscore te berekenen, dat je dan een flinke slag maakt. Maar hoe die functie te schrijven? Of moet je die gehele ratingtabel in een array gaan plaatsen?
Daarnaast denk ik dat je in plaats van temporary tables een aantal zaken beter in een array kunt wegschrijven dan updates te doen in de database, en vervolgens berekende TPRs (die beter zijn) en bijbehorende normscores in die array moet vervangen.
Al vraag ik me af of dat juist niet weer een flinke aanslag gaat geven op het geheugen. Maar dan doe je alles in php en belast je niet de database.
Enfin, voor php en mysql specialisten misschien een hele mooie uitdaging om een fraai script te schrijven, dat snel en efficient een ranglijst op de TPR-methode Wouter Ludwig kan produceren. En natuurlijk zijn ook tips gewoon welkom (pm).
Op aanvraag wil ik via pm wel mijn php-script (een include in Toernooibase) sturen (momenteel een 450 regels).
Ik ben benieuwd naar reacties!
https:toernooibase.kndb.nl More than 415.000 games on applet, more than 1.300.000 results, more than 21.000 games broadcasted (semi-)live, more than 12.900 inserted tournaments!