Hilfe bei Algorithmus (Turnierwebseite - vergeben der Punkte nach Ergebnis)

12/11/2022 02:14 papierkorp#1
Servus,

bin privat dabei für eine LAN Party unter Freunden so eine kleine Turnierwebseite zu programmieren.

Zum einen um die tatsächlich mal zu verwenden und zum anderen zum Rumspielen mit verschiedenen Techniken.

Da dass vermutlich gefragt wird: ich verwende dafür Python - Flask.

Jetzt häng ich da aber bei einem (kleinen) Problem:

Ich muss für die Ergebnisse in den Spielen Punkte vergeben. Dabei soll pro Spiele jede Runde einzeln gewertet werden. Als Beispiel:

Game Counter Strike Deathmatch, Sieger ist der mit den meisten Kills.

Runde 1  
Spieler Kills Punkte
lorem 5 0
ipsum 12 3
dolor 7 1
Runde 2   
lorem 15 3
ipsum 8 1
dolor 3 0
Gesamt   
lorem (3) 1
ipsum (4) 3
dolor (1) 0

Jetzt soll der Sieger (Spieler 2) 3 Punkte bekommen der Zweitplatzierte 1 Punkt und der letzte 0 Punkte.

Wenn es 4 Spieler gibt, bekommt der Sieger 4 Punkte, der Zweitplatzierte 2 Punkte, der Dritte 1 Punkte und der letzte 0 Punkte.

Also:
Sieger Punkte = Anzahl Spieler
nächster Platz = Anzahl Spieler - 2,
nächster Platz = Anzahl Spieler -3,
solange bis Anzahl Spieler - x == 0 ist

Als Ausgangslage hab ich eine Liste mit allen Games. Die Games sind dann wieder eine Liste. Und pro Game gibt es je eine Liste pro Runde. (siehe unten)

Bei mehreren Runden soll dann jede Runde einzeln nach dem obrigen Schema bewertet werden. Dann sollen die Punkte für jede Runde zusammengezählt und wieder mit obrigen Schema bewertet werden.

Und dabei das ganze in eine Funktion zu packen, macht mein Hirn leider absolut nicht mit :/.

Hier mal der Code den ich im Moment habe / bei dem ich im Moment hänge:

[Only registered and activated users can see links. Click Here To Register...]

Code:
#punkteliste_pro_game = ["Game", "Teilnehmer", "Ergebnistyp", "Runde", "Ergebnis"]
punkteliste_alt = [
    [
        [('Counter Strike:Globale Offensive', 'sancho', 'kills', 1, 15), ('Counter Strike:Globale Offensive', 'draham', 'kills', 1, 21), ('Counter Strike:Globale Offensive', 'brandmeister', 'kills', 1, 21), ('Counter Strike:Globale Offensive', 'tobse', 'kills', 1, 42), ('Counter Strike:Globale Offensive', 'papierkorp', 'kills', 1, 45)]
        ], 
    [
        [('Trackmania', 'brandmeister', 'zeit', 1, 45), ('Trackmania', 'papierkorp', 'zeit', 1, 47), ('Trackmania', 'tobse', 'zeit', 1, 51), ('Trackmania', 'draham', 'zeit', 1, 77), ('Trackmania', 'sancho', 'zeit', 1, 93)]
    ], 
    [
        [('Worms Armageddon', 'brandmeister', 'platz', 1, 1), ('Worms Armageddon', 'papierkorp', 'platz', 1, 2), ('Worms Armageddon', 'tobse', 'platz', 1, 3), ('Worms Armageddon', 'sancho', 'platz', 1, 4), ('Worms Armageddon', 'draham', 'platz', 1, 5)], 
        [('Worms Armageddon', 'papierkorp', 'platz', 2, 1), ('Worms Armageddon', 'sancho', 'platz', 2, 2), ('Worms Armageddon', 'draham', 'platz', 2, 3), ('Worms Armageddon', 'brandmeister', 'platz', 2, 4), ('Worms Armageddon', 'tobse', 'platz', 2, 5)]
    ]
]
 
anzahlTeilnehmer = 5
punkte_game={"sancho":0, "draham":0, "brandmeister":0,"tobse":0, "papierkorp":0}
punkte_gesamt={"sancho":0, "draham":0, "brandmeister":0,"tobse":0, "papierkorp":0}

print("\n\n------------------------------------\n------------------------------------\n\n")
for spiel in punkteliste_alt:
    punkte_runde={"sancho":0, "draham":0, "brandmeister":0,"tobse":0, "papierkorp":0}
    game = spiel[0][0][0]
    
    print("\ngame:", game)
 
    for runde in spiel:
        ergebnistyp = runde[0][2]
        counter1=0
        counter2=2
        #todo sonderfall gleichviele punkte
        if ergebnistyp == "kills" or ergebnistyp == "Punkte":
            punkte_runde[runde[-1][1]] += anzahlTeilnehmer #1. Platz = der letzte in der Liste
            runde.remove(runde[-1])
         
        if ergebnistyp == "zeit" or ergebnistyp == "platz":
            punkte_runde[runde[0][1]] += anzahlTeilnehmer #1. Platz = der erste in der Liste
            runde.remove(runde[0])
         
         
         
        for detail in sorted(runde, key=lambda tup: tup[4]):
            print("\nrunde vorher\n", runde)
            ergebnistyp = detail[2]
            spieler=detail[1]
            if ergebnistyp == "kills" or ergebnistyp == "punkte":
                punkte_runde[spieler] += counter1
                counter1 += 1
            if ergebnistyp == "zeit" or ergebnistyp == "platz":
                punkte_runde[spieler] += anzahlTeilnehmer - counter2
                counter2 += 1

 
            runde.remove(detail)
            print("\npunkte_runde\n", punkte_runde)
            print("\nrunde nachher\n", runde)
             
    print("\npunkte_runde gesamt\n", punkte_runde)
    print("\npunkte_runde gesamt sorted\n", dict(sorted(punkte_runde.items(), key=lambda item:item[1])))
    
    # Punkte pro Spiel ausrechnen (bei mehreren Runden)
    for spieler in dict(sorted(punkte_runde.items(), key=lambda item:item[1])):
        print()
            
    # Punkte gesamt ausrechnen
    for spieler in dict(sorted(punkte_game.items(), key=lambda item:item[1])):
        print()
        

         
 
    print("\npunkte_game ende:\n", punkte_game)

print("\npunkte_gesamt:\n", punkte_gesamt)
Wäre natürlich geil wenn mir da wer direkt in Python helfen könnte. Wäre aber auch schon glücklich wenn ihr meinen Kopf durch frische Gedanken ein bissl entwirren könntent :)

Viele Dank schon mal für jegliche Hilfe

Gruß
Markus
12/11/2022 17:30 sk8land​#2
So in etwa?

Code:
from collections import defaultdict

ordnung = {
    'kills': True,
    'zeit': False,
    'platz': False,
}

punkte_gesamt = defaultdict(int)

for spiel in punkteliste_alt:
    punkte_game = defaultdict(int)
    for runde in spiel:
        runde_sortiert = sorted(runde, key=lambda x: x[4], reverse=ordnung[runde[0][2]])
        punkte_runde = {x[1]: len(runde_sortiert) - (i + 1 if i else 0) for i, x in enumerate(runde_sortiert)}

        for x, y in punkte_runde.items():
            punkte_game[x] += y
            punkte_gesamt[x] += y

        print("    punkte_runde:", sorted(punkte_runde.items(), key=lambda x: x[1], reverse=True))
    print("  punkte_game:", sorted(punkte_game.items(), key=lambda x: x[1], reverse=True))
print("\npunkte_gesamt:", sorted(punkte_gesamt.items(), key=lambda x: x[1], reverse=True))
12/14/2022 20:52 papierkorp#3
Sorry dass ich jetzt erst antworte, hab leider nicht jeden Tag Zeit :/.

Jo ist genau was ich gebraucht hab vielen Dank dafür, auch wenn ich den Code noch nicht ganz verstanden hab :D.

Welche Möglichkeiten hätt ich wenn 2 Spieler das selbe Ergebnis haben? Im Moment hat einer dann einfach Pech gehabt. Hatte mir da keine Gedanken darum gemacht.
12/15/2022 18:53 sk8land​#4
Du könntest mit itertools.groupby Dopplungen in der sortierten Liste herausfinden und die Punkte entsprechend der gruppierten Liste zuteilen.
12/15/2022 19:59 papierkorp#5
Ich werds mal versuchen, vielen Dank.
Wenn ich nicht weiterkomme meld ich mich nochmal hier :D