Im vorherigen Kapitel hatten wir uns schrittweise an die grafische Auswertung von elementaren Kennzahlen herangetastet. Wir haben zum Beispiel Gewinn- und Verlustquoten der einzelnen Spieler berechnet und daraus eine vergleichende Übersichtsgrafik erstellt. Außerdem haben wir gezeigt, dass unsere Zufalls-Stichprobe hinreichend gut mit der Gesamterhebung sämtlicher Partiedaten übereinstimmt.
Jetzt wollen wir etwas tiefer einsteigen, indem wir die Kennzahlen, die wir aus unseren Positions- und Spiel-Analysen gewonnen haben, betrachten und ebenfalls in die Bewertung einbeziehen.
Zugbewertungen
Beginnen werden wir mit der Gegenüberstellung von Quoten zur Zugbewertung, die wir anhand der fundamentalen cpl-Metrik in eine leicht verständliche Kategorisierung der einzelnen analysierten Züge umgerechnet hatten. Alle Züge wurden dazu entweder in eine der vier Kategorien ‚ENGINE‘, ‚INACCURACY‘, ‚MISTAKE‘ oder ‚BLUNDER‘ eingeordnet oder unbewertet gelassen. Letztere könnte man auch als „normale“ Züge betrachten. Wir ziehen allerdings den Begriff „valide“ vor und berücksichtigen diese Züge in unserer Rechnung, um zu einer Gesamtheit von 100% zu gelangen.
Hier der SQL- und Python-Code, den wir in einem Jupyter Notebook ausführen (Anmerkung: es wäre leichter gewesen, in unserem Programm unten die bereits aggregierten Kennzahlen in der Tabelle da_game zu verwenden, anstatt sie aus da_position neu zu berechnen).
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
Spieler,
round(CountEngineMoves / CountMoves * 100, 2) "Engine Move Rate",
round(CountValidMoves / CountMoves * 100, 2) "Valid Move Rate",
round(CountInaccurateMoves / CountMoves * 100, 2) "Inaccurate Move Rate",
round(CountMistakeMoves / CountMoves * 100, 2) "Mistake Move Rate",
round(CountBlunderMoves / CountMoves * 100, 2) "Blunder Move Rate"
from
(
select
case when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) then 1 else 0 end) CountMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) and dap.judgement = 'ENGINE' then 1 else 0 end) CountEngineMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) and dap.judgement is null then 1 else 0 end) CountValidMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) and dap.judgement = 'INACCURACY' then 1 else 0 end) CountInaccurateMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) and dap.judgement = 'MISTAKE' then 1 else 0 end) CountMistakeMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 1) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 0)) and dap.judgement = 'BLUNDER' then 1 else 0 end) CountBlunderMoves
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join position po on
po.game_id = g.id
join da_position dap on
dap.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end) t
order by
2 desc, 3 desc""", conn)
return(df)
def visualize_data(p_df):
color=['lime', 'green', 'yellow', 'orange', 'red']
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,28), color=color, ylabel="Judgement Rate", title="Zugbewertungs-Raten der Schachweltmeister")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Engine Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Valid Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Inaccurate Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Mistake Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Blunder Move Rate'], rotation = 0, label_type = "center")
plt.ylim([0, 110])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Was lässt sich aus obiger Grafik ablesen? Zunächst fallen die hohen Quoten mit Engine-Zügen bei Magnus Carlsen und Ding Liren auf, die beide bei nahezu 70% liegen. Hätten wir bekannte Eröffnungszüge mit bewertet, lägen diese Quoten mit großer Wahrscheinlichkeit noch deutlich höher.
Die fünf Schlusslichter Staunton, Lasker, Steinitz, Aljechin und Capablanca heben sich auch durch einen relativ hohen Anteil mit schlechten Zügen (‚INACCURATE‘, ‚MISTAKE‘, ‚BLUNDER‘) vom Gesamtfeld ab. Auch bei Paul Morphy sticht der im Vergleich etwas erhöhte Anteil von Partien mit der Bewertung ‚INACCURATE‘ und ‚MISTAKE‘ ins Auge, wobei die Quote seiner Schnitzer (‚BLUNDER‘) gut im vorderen Mittelfeld liegt. Was dessen Quote der Engine-Züge angeht, so liegt Morphy immerhin nur knapp einen Prozentpunkt hinter Karpow, aber z.B. noch deutlich vor Capablanca, Aljechin und Lasker! Man kann gar nicht genug hervorheben, wie sensationell diese Erkenntnis eigentlich ist! Wir werden später darauf zurück kommen.
Die geringste Rate an Patzern darf sich Michail Botwinnik anrechnen lassen, während Max Euwe diesbezüglich immer noch im Mittelfeld liegt, obwohl ihm ein gewisser Hang zu Patzen nachgesagt wurde. Allein, die hier untersuchte Datenbasis bestätigt diesen Ruf nicht.
Im Gegenteil – mit einer Blunder-Rate von 0,87% liegt Max Euwe sogar relativ weit unter den 1,14% von José Raúl Capablanca, der wegen seines präzisen Spiels seinerzeit auch als Schachmaschine bezeichnet wurde.
So aufschlussreich die obige Grafik auch wirken mag, wenn wir die Quoten der Gegenspieler als Anhaltspunkt für deren Spielstärke unberücksichtigt lassen, kennen wir nur die halbe Warheit.
gegnerische Zugbewertungen
Um die Qualität der gegnerischen Züge zu messen, müssen wir an unserem obigen Programm fast nichts ändern. Lediglich die Logik zur Ermittlung des Zugführenden anhand der Halbzugnummer muss umgekehrt und dazu noch die Überschrift des Schaubildes angepasst werden.
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
Spieler,
round(CountEngineMoves / CountMoves * 100, 2) "Engine Move Rate",
round(CountValidMoves / CountMoves * 100, 2) "Valid Move Rate",
round(CountInaccurateMoves / CountMoves * 100, 2) "Inaccurate Move Rate",
round(CountMistakeMoves / CountMoves * 100, 2) "Mistake Move Rate",
round(CountBlunderMoves / CountMoves * 100, 2) "Blunder Move Rate"
from
(
select
case when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) then 1 else 0 end) CountMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) and dap.judgement = 'ENGINE' then 1 else 0 end) CountEngineMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) and dap.judgement is null then 1 else 0 end) CountValidMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) and dap.judgement = 'INACCURACY' then 1 else 0 end) CountInaccurateMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) and dap.judgement = 'MISTAKE' then 1 else 0 end) CountMistakeMoves,
sum(case when ((p.id = g.white_player_id and mod(po.half_move_num, 2) = 0) or (p.id = g.black_player_id and mod(po.half_move_num, 2) = 1)) and dap.judgement = 'BLUNDER' then 1 else 0 end) CountBlunderMoves
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join position po on
po.game_id = g.id
join da_position dap on
dap.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end) t
order by
2 desc, 3 desc""", conn)
return(df)
def visualize_data(p_df):
color=['lime', 'green', 'yellow', 'orange', 'red']
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,28), color=color, ylabel="Judgement Rate", title="Zugbewertungs-Raten der Gegner")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Engine Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Valid Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Inaccurate Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Mistake Move Rate'], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Blunder Move Rate'], rotation = 0, label_type = "center")
plt.ylim([0, 110])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Zumindest ein Trend lässt sich aus obiger Grafik klar ablesen – die Gegner wurden/werden im Laufe der Zeit immer besser. Die schlechtesten Gegenspieler hatte anscheinend Paul Morphy am Brett. Doch lag das auch daran, dass er seine Gegner stets unter großen Druck setzte? Oder zog der relativ große Anteil an Schaukämpfen (freie Partien gegen Amateure, Vorgabepartien,(Blind-)Simultanvorstellungen) den Schnitt so weit nach unten? Für Ersteres spricht die ebenfalls relativ hohe Rate schlechter gegnerischer Züge bei den als scharfe Angriffsspieler bekannten Bobby Fischer und Alexander Aljechin – unter Druck werden erfahrungsgemäß leichter Fehler begangen. Aber dies ist lediglich ein Indiz und kein Beweis für unsere Vermutung.
ACPL
Die obigen Zugbewertungen sind ein relativ grobes Kriterium, in festen Stufen von den CPL-Kennzahlen abgeleitet. Mit der Kennzahl ACPL haben wir nicht nur ein genaueres Maß für die Qualität der Züge einzelner Partien, sondern mit dem STDCPL-Wert darüberhinaus auch noch einen Gradmesser für die Konstanz hochwertiger Züge einer Partie. Beide Werte sollten möglichst niedrig liegen. Niedrige Werte des Gegners sprechen ebenfalls für dessen Spielstärke.
Wir hatten die ACPL-Kennzahl als Durchschnittswert der CPL-Werte über alle Halbzüge einer Partie berechnet und in der Tabelle da_game gespeichert. Wir könnten diese Werte pro Spieler nochmals über alle seine Partien mitteln und erhielten so einen ziemlich nichtssagenden Gesamtwert.
ACPL-Klassifizierung
Wir wollen stattdessen ACPL-Intervalle als Güteklassen definieren und dabei die Anzahl der Partien für jede dieser Kategorien ermitteln. Wir wählen Anzahl und Größe der Intervalle so, dass sie zum einen hinreichend feingranular und damit aussagekräftig sind. Zum anderen streben wir der Übersichtlichkeit halber an, dass nicht zu viele Intervalle entstehen und dass jedes Intervall ausreichend und möglichst gleich viele Werte enthält.
Nach etwas Ausprobieren sind wir zu folgendem Schema gelangt:
| ACPL >= | < |
|---|---|
| 0 | 5 |
| 5 | 10 |
| 10 | 20 |
| 20 | 30 |
| 30 | 40 |
| 40 | 50 |
| 50 | 60 |
| 60 | ∞ |
Die zugehörigen Daten ermitteln wir uns zunächst über eine SQL-Abfrage an die Datenbank.
SQL-Code
select
t.spieler,
sum(case when t.ACPLSpieler >= 0 and t.ACPLSpieler < 5 then 1 else 0 end) / count(t.spieler) * 100 countAcpl0_5,
sum(case when t.ACPLSpieler >= 5 and t.ACPLSpieler < 10 then 1 else 0 end) / count(t.spieler) * 100 countAcpl6_10,
sum(case when t.ACPLSpieler >= 10 and t.ACPLSpieler < 20 then 1 else 0 end) / count(t.spieler) * 100 countAcpl11_20,
sum(case when t.ACPLSpieler >= 20 and t.ACPLSpieler < 30 then 1 else 0 end) / count(t.spieler) * 100 countAcpl21_30,
sum(case when t.ACPLSpieler >= 30 and t.ACPLSpieler < 40 then 1 else 0 end) / count(t.spieler) * 100 countAcpl31_40,
sum(case when t.ACPLSpieler >= 40 and t.ACPLSpieler < 50 then 1 else 0 end) / count(t.spieler) * 100 countAcpl41_50,
sum(case when t.ACPLSpieler >= 50 and t.ACPLSpieler < 60 then 1 else 0 end) / count(t.spieler) * 100 countAcpl51_60,
sum(case when t.ACPLSpieler >= 60 then 1 else 0 end) countAcpl60bis
from
(
select
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
nvl(case when p.id = g.white_player_id then dg.acpl_white else dg.acpl_black end, 0.0) "ACPLSpieler"
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join da_game dg on
dg.game_id = g.id
join position po on
po.game_id = g.id
join position_analysis pa on
pa.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end,
g.id
) t
group by
t.spieler
order by 1;

Partien mit ACPL-Werten oberhalb von 60 darf man getrost als „miserabel“ bezeichnen – sie bedürfen nach unserem Verständnis daher keiner weiteren Differenzierung.
Für den Wertevergleich zwischen den Spielern wollen wir ähnlich vorgehen wie beim Vergleich der Spielresultate oder den obigen Zugbewertungen, indem wir die prozentualen Anteile für jedes ACPL-Intervall bezogen auf die jeweilige Anzahl analysierter Partien ermitteln. Wir achten bei der Erstellung unserer Jupyter Notebook Anwendung darauf, dass die verschiedenen Anteile der einzelnen Spieler immer 100% ergeben (modulo kleiner Rundungsfehler) und wählen eine geeignete Farbpalette für die Anteile von „gut“ (grün) bis „miserabel“ (tiefrot).
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
t.spieler "Spieler",
round(sum(case when t.ACPLSpieler >= 0 and t.ACPLSpieler < 5 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [0;5[",
round(sum(case when t.ACPLSpieler >= 5 and t.ACPLSpieler < 10 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [5;10[",
round(sum(case when t.ACPLSpieler >= 10 and t.ACPLSpieler < 20 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [10;20[",
round(sum(case when t.ACPLSpieler >= 20 and t.ACPLSpieler < 30 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [20;30[",
round(sum(case when t.ACPLSpieler >= 30 and t.ACPLSpieler < 40 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [30;40[",
round(sum(case when t.ACPLSpieler >= 40 and t.ACPLSpieler < 50 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [40;50[",
round(sum(case when t.ACPLSpieler >= 50 and t.ACPLSpieler < 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [50;60[",
round(sum(case when t.ACPLSpieler >= 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL 60-"
from
(
select
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
nvl(case when p.id = g.white_player_id then dg.acpl_white else dg.acpl_black end, 0.0) "ACPLSpieler"
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join da_game dg on
dg.game_id = g.id
join position po on
po.game_id = g.id
join position_analysis pa on
pa.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end,
g.id
) t
group by
t.spieler
order by 2 desc,
3 desc,
4 desc,
5 desc""", conn)
return(df)
def visualize_data(p_df):
cmap = plt.cm.RdYlGn_r
colors = cmap(np.linspace(0.0, 1.0, 8))
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,21), color=colors, ylabel="Anteile ACPL-Klassen", title="Partie-Anteile der Schachweltmeister nach ACPL-Klassen")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Anteil ACPL [0;5['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Anteil ACPL [5;10['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Anteil ACPL [10;20['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Anteil ACPL [20;30['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Anteil ACPL [30;40['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[5], labels=p_df['Anteil ACPL [40;50['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[6], labels=p_df['Anteil ACPL [50;60['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[7], labels=p_df['Anteil ACPL 60-'], rotation = 0, label_type = "center")
plt.ylim([0, 115])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Im direkten Vergleich zur obigen Grafik zur Zugbewertung verschiebt sich die Rangliste hier etwas, denn der ACPL-Wert misst die durchschnittliche Qualität einer ganzen Partie anstatt einzelner Züge. Augenfällig wird die Diskrepanz z.B. bei D. Gukesh, der beim Anteil von ENGINE-Zügen auf Platz 3 lag, nun aber im ACPL-Ranking auf den 14. Platz abgerutscht ist. Eine Erklärung wäre eine schlechtere Konstanz seiner Züge und dies sollte sich vom STDCPL-Wert ablesen lassen. Bevor wir uns aber mit der Zugkonstanz-Thematik befassen, sehen wir uns noch die ACPL-Anteile der jeweiligen Gegner unserer Protagonisten an, die ja auch etwas über deren Spielstärke aussagt und damit indirekt auch über die Stärken der Weltmeister selbst.
ACPL-Klassifizierung der Gegner
Die Anpassung hierfür ist wieder einfach – die Umkehrung der Seiten, ein paar Spaltenumbennungen sowie eine neue Überschrift.
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
t.spieler "Spieler",
round(sum(case when t.ACPLGegenspieler >= 0 and t.ACPLGegenspieler < 5 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [0;5[",
round(sum(case when t.ACPLGegenspieler >= 5 and t.ACPLGegenspieler < 10 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [5;10[",
round(sum(case when t.ACPLGegenspieler >= 10 and t.ACPLGegenspieler < 20 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [10;20[",
round(sum(case when t.ACPLGegenspieler >= 20 and t.ACPLGegenspieler < 30 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [20;30[",
round(sum(case when t.ACPLGegenspieler >= 30 and t.ACPLGegenspieler < 40 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [30;40[",
round(sum(case when t.ACPLGegenspieler >= 40 and t.ACPLGegenspieler < 50 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [40;50[",
round(sum(case when t.ACPLGegenspieler >= 50 and t.ACPLGegenspieler < 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL [50;60[",
round(sum(case when t.ACPLGegenspieler >= 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil ACPL 60-"
from
(
select
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
nvl(case when p.id = g.white_player_id then dg.acpl_black else dg.acpl_white end, 0.0) "ACPLGegenspieler"
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join da_game dg on
dg.game_id = g.id
join position po on
po.game_id = g.id
join position_analysis pa on
pa.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end,
g.id
) t
group by
t.spieler
order by 2 desc,
3 desc,
4 desc,
5 desc""", conn)
return(df)
def visualize_data(p_df):
cmap = plt.cm.RdYlGn_r
colors = cmap(np.linspace(0.0, 1.0, 8))
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,21), color=colors, ylabel="Anteile ACPL-Klassen Gegenspieler", title="Partie-Anteile der Gegenspieler nach ACPL-Klassen")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Anteil ACPL [0;5['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Anteil ACPL [5;10['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Anteil ACPL [10;20['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Anteil ACPL [20;30['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Anteil ACPL [30;40['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[5], labels=p_df['Anteil ACPL [40;50['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[6], labels=p_df['Anteil ACPL [50;60['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[7], labels=p_df['Anteil ACPL 60-'], rotation = 0, label_type = "center")
plt.ylim([0, 115])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Die schwächsten Gegner hatte offenbar Howard Staunton, während die Gegner von Paul Morphy in der Spitze etwa gleichstark wie die Gegner von Steinitz, Lasker und Aljechin waren. Den höchsten Anteil miserabelster Gegner darf ebenfalls Paul Morphy für sich verbuchen, wobei man bedenken muss, das Morphy praktisch nur 3 Jahre lang ernsthaft spielte und das auch nur gegen wenige starke Gegner. Die überwiegende Zahl seiner Partien stammt aus (Blind-)Simultan-, Vorgabe- und freien Partien gegen jedermann. Dass diese Gelegenheits-Partien überhaupt erhalten sind, ist lediglich dem Umstand geschuldet, dass sie sehr oft mit ihren brillanten Kombinationen aus strategisch überlegenem Spiel heraus unsterbliche Beispiele für Morphy’s Spielkunst geworden sind, quasi ein Erbe der Menschheitsgeschichte – zumindest was die Schachwelt betrifft.
Den geringsten Anteil an miserablen Gegnern hatten Petrosian, Smyslov, Botvinnik und Spassky – Spieler, die in ihrer Epoche in enger, hauptsächlich sowjetischer Konkurrenz jeweils um den Spitzenplatz kämpften.
STDCPL-Klassifizierung
Zunächst ermitteln wir über eine entsprechende SQL-Abfrage die Werteverteilung und gelangen so zu folgender Skalierung.
| STDCPL>= | < |
|---|---|
| 0 | 5 |
| 5 | 10 |
| 10 | 20 |
| 20 | 30 |
| 30 | 40 |
| 40 | 50 |
| 50 | 60 |
| 60 | 70 |
| 70 | 80 |
| 80 | 90 |
| 90 | 100 |
| 100 | ∞ |
Da die Werte allein noch kein Gefühl dafür vermitteln, wie sie hinsichtlich der Güte ihrer Aussagekraft einzuschätzen sind, sehen wir uns drei Beispiele genauer an.
Zunächst betrachten wir die Partie Vladimir Kramnik vs Viswanathan Anand mit dem STDCPL-Wert 3.67 aus dem ersten Intervall. Die Analyse beginnt erst mit dem neunten Zug von Schwarz, da die vorherigen Züge aus dem Eröffnungsbuch stammen. Man sieht in der Tabelle unten, dass Kramnik ohne jede Ungenauigkeit fast nur ENGINE-Züge spielt – ein hervorragendes Beispiel eines praktisch perfekten Spiels von Weiß.
SQL-Code
select
pw.name white,
pb.name black,
g.id,
g.event,
g.game_date,
p.half_move_num,
p.move_white,
p.move_black,
pa.best_move_uci ,
pa.centipawn ,
dap.accuracy ,
dap.judgement ,
dag.stdcpl_white ,
dag.stdcpl_black
from
game g
join player pw on
g.white_player_id = pw.id
join player pb on
g.black_player_id = pb.id
join position p on
(g.id = p.game_id)
join position_analysis pa on
(p.id = pa.position_id)
join da_position dap on dap.position_id =p.id
join da_game dag on dag.game_id =g.id
where
(dag.stdcpl_black < 5 or dag.stdcpl_white <5) and g.id=2360041;
| white | black | id | event | game_date | half_move_num | move_white | move_black | best_move_uci | centipawn | accuracy | judgement | stdcpl_white | stdcpl_black |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 18 | f6e4 | c1b2 | -32 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 19 | c1b2 | b8d7 | -36 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 20 | e4c3 | b2c3 | -20 | 93.60867927746872 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 21 | b2c3 | b8c6 | -22 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 22 | b7b6 | e1g1 | -20 | 99.17745804216128 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 23 | c4d5 | e6d5 | -32 | 95.16649901377349 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 24 | e6d5 | e1g1 | -29 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 25 | e1g1 | b8d7 | -25 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 26 | b8c6 | f3e5 | -21 | 98.36206246346103 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 27 | f3e5 | c6e5 | -19 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 28 | c6e5 | d4e5 | -22 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 29 | d4e5 | c8e6 | -19 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 30 | c8e6 | f1e1 | -21 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 31 | f1e1 | f8e8 | -19 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 32 | d8d7 | c3b4 | -10 | 96.34747592266002 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 33 | d1d2 | f8d8 | -17 | 97.14749439702474 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 34 | a8c8 | c3b4 | -17 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 35 | c3d4 | c8c7 | -32 | 93.99259155395328 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 36 | c8c7 | g2f1 | -34 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 37 | a2a4 | f8b8 | -29 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 38 | f8c8 | a4a5 | -20 | 96.35221197627955 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 39 | g2f1 | g7f8 | -22 | 99.17745804216128 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 40 | g7f8 | f1a6 | -18 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 41 | f1a6 | c8a8 | -16 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 42 | c8d8 | h2h4 | -19 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 43 | h2h4 | f8c5 | -21 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 44 | f8c5 | h4h5 | -24 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 45 | b3b4 | c5d4 | -18 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 46 | c5d4 | d2d4 | -13 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 47 | d2d4 | h7h5 | -15 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 48 | d7e7 | a6d3 | -5 | 95.94825610342897 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 49 | a6d3 | d8b8 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 50 | g8g7 | a4a5 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 51 | a4a5 | d8c8 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 52 | d8c8 | a5b6 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 53 | a5b6 | a7b6 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 54 | a7b6 | d3a6 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 55 | d3f1 | h7h5 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 56 | b6b5 | e1b1 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 57 | f1d3 | h7h5 | 0 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 58 | c7c4 | d3c4 | 70 | 74.88187392779255 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 59 | d3c4 | e7b4 | 93 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 60 | e7b4 | a1b1 | 105 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 61 | a1b1 | b4c4 | 93 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 62 | b4c4 | d4d2 | 97 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 63 | d4d2 | c4g4 | 118 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 64 | h7h5 | b1c1 | 301 | 51.73718431845201 | INACCURACY | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 65 | b1c1 | c4g4 | 386 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 66 | c4b3 | c1c8 | 391 | 98.71977271216318 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 67 | c1c8 | e6c8 | 390 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 68 | e6c8 | d2f4 | 389 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 69 | d2f4 | d5d4 | 389 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 70 | c8f5 | e5e6 | 707 | 57.01063231837722 | INACCURACY | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 71 | e5e6 | b3c3 | 756 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 72 | f5e6 | f4e5 | 766 | 99.1115816926653 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 73 | f4e5 | g7f8 | 770 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 | |
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 74 | g7h7 | e1a1 | 823 | 95.87227092919485 | 3.674904911473817 | 67.36800632245301 | ||
| Kramnik, Vladimir | Anand, Viswanathan | 2360041 | Zurich Korchnoi CC 2017 | 2017-04-13 | 75 | e1a1 | b3a4 | 882 | 100.0 | ENGINE | 3.674904911473817 | 67.36800632245301 |
Als nächstes wählen wir als Beispiel die Partie Capablanca,Jose Raul – Van Hoorn,Petrus Franciscus, Netherlands Tour Capablanca Netherlands 09.09.1911 aus dem mittleren Intervall-Bereich (40-50). Obwohl Capablanca in der Partie keinen groben Fehler begeht, genügt eine einzige Ungenauigkeit, sowie in der Folge fehlerloses Spiel des Gegners, damit die Partie im Endspiel für Capablanca verloren geht. Gutes Spiel allein genügt offenbar nicht, wenn der Gegner noch besser spielt!
SQL-Code
select
pw.name white,
pb.name black,
g.game_date,
p.half_move_num,
p.move_white,
p.move_black,
pa.best_move_uci ,
pa.centipawn ,
dap.accuracy ,
case when mod(p.half_move_num, 2) = 1 then concat(dap.judgement, ' (white)') else concat(dap.judgement, ' (black)') end judgement ,
dag.stdcpl_white ,
dag.stdcpl_black
from
game g
join player pw on
g.white_player_id = pw.id
join player pb on
g.black_player_id = pb.id
join position p on
(g.id = p.game_id)
join position_analysis pa on
(p.id = pa.position_id)
join da_position dap on dap.position_id =p.id
join da_game dag on dag.game_id =g.id
where
((dag.stdcpl_black > 40 and dag.stdcpl_black <= 50) or (dag.stdcpl_white > 40 and dag.stdcpl_white <=50)) and g.id=2175170;
| white | black | game_date | half_move_num | move_white | move_black | best_move_uci | centipawn | accuracy | judgement | stdcpl_white | stdcpl_black |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 7 | e2e3 | c7c5 | -52 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 8 | c7c5 | b4c5 | -48 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 9 | b4c5 | f8c5 | -48 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 10 | f8c5 | g1f3 | -47 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 11 | d2d4 | d8b6 | -44 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 12 | c5d6 | g1f3 | -39 | 97.9648417522937 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 13 | c2c4 | e8g8 | -39 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 14 | d5c4 | f1c4 | -15 | 90.56224775826414 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 15 | f1c4 | a7a6 | -16 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 16 | e8g8 | g1f3 | -13 | 98.767743563892 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 17 | b1d2 | b7b5 | -12 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 18 | a7a6 | a3a4 | 1 | 94.76297394880179 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 19 | g1f3 | b7b5 | -22 | 90.91941177497507 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 20 | b7b5 | c4d3 | -23 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 21 | c4d3 | b8d7 | -20 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 22 | c8b7 | e1g1 | -18 | 99.17723599627786 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 23 | e1g1 | b8d7 | -13 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 24 | b8d7 | a3a4 | -14 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 25 | e3e4 | d6e7 | -17 | 98.76786806300103 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 26 | d6e7 | a3a4 | -18 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 27 | f1e1 | d7b6 | -41 | 90.94169339985832 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 28 | d8b6 | d1e2 | -15 | 89.81795691857425 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 29 | d2f1 | f8c8 | -21 | 97.5512542535127 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 30 | f8c8 | h2h3 | -13 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 31 | h2h3 | a6a5 | -14 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 32 | g7g6 | a1b1 | 22 | 86.14383700669794 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 33 | d1d2 | b5b4 | 0 | 91.29726071728015 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 34 | e7f8 | f1h2 | 55 | 79.65234615753745 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 35 | d2f4 | b6c7 | 17 | 85.48994886176074 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 36 | f8g7 | f1g3 | 31 | 94.3814707082338 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 37 | f3g5 | h7h6 | -27 | 78.61942916345987 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 38 | b6c7 | e4e5 | 77 | 64.9796646049572 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 39 | e4e5 | d7f8 | 73 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 40 | d7f8 | f1g3 | 69 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 41 | a1c1 | f6d5 | 68 | 99.59372204139315 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 42 | f6d5 | f4g3 | 71 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 43 | c1c7 | d5f4 | -36 | 64.14369635497788 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 44 | d5f4 | c7b7 | -35 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 45 | c7c8 | a8c8 | -180 | 55.99627100051622 | INACCURACY (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 46 | a8c8 | d3e4 | -202 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 47 | d3e4 | b7e4 | -205 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 48 | b7e4 | g5e4 | -218 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 49 | g5e4 | f4d3 | -216 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 50 | f4d3 | e1b1 | -204 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 51 | e1e2 | f8d7 | -221 | 94.12002089131617 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 52 | f8d7 | b2c3 | -232 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 53 | b2c3 | d3f4 | -233 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 54 | d3f4 | e2d2 | -229 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 55 | e2d2 | f4d5 | -239 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 56 | f4d5 | c3b4 | -235 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 57 | d2d3 | f7f5 | -281 | 85.78294798597507 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 58 | g7f8 | c3d2 | -189 | 72.7184705312564 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 59 | c3b2 | d7b6 | -313 | 65.74290063156899 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 60 | d7b6 | d3d2 | -335 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 61 | g2g3 | b6a4 | -381 | 88.07587345945528 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 62 | b6a4 | d3d2 | -388 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 63 | d3d2 | a4b2 | -399 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 64 | a4b2 | d2b2 | -402 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 65 | d2b2 | f8a3 | -413 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 66 | f8a3 | b2a2 | -415 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 67 | b2a2 | b5b4 | -422 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 68 | b5b4 | g1g2 | -422 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 69 | e4c5 | d5c3 | -482 | 87.53232078156535 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 70 | a6a5 | f1d2 | -446 | 92.55030680240901 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 71 | f1e3 | d5c3 | -469 | 95.09833836861502 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 72 | d5c3 | a2c2 | -468 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 73 | a2c2 | c3b5 | -461 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 74 | c8d8 | e3c4 | -310 | 67.39132390157383 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 75 | e3c4 | c3b5 | -312 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 76 | c3b5 | c4a5 | -308 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 77 | c4a5 | b5d4 | -309 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 78 | b5d4 | c2a2 | -312 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 79 | c2a2 | d4f3 | -312 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 80 | d4f3 | g1f1 | -312 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 81 | g1g2 | f3e5 | -368 | 85.16594185235815 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 82 | f3e5 | g2f1 | -378 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 83 | a5b3 | g8g7 | -400 | 94.49095089082972 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 84 | d8d5 | c5e4 | -388 | 96.99148807293709 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 85 | f2f4 | e5d3 | -423 | 91.6820358785656 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 86 | e5d3 | c5e4 | -433 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 87 | c5d3 | d5d3 | -478 | 90.58118518274807 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 88 | d5d3 | b3c5 | -504 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 89 | b3c5 | d3c3 | -527 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 90 | d3c3 | c5e4 | -520 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 91 | c5e4 | c3c1 | -542 | 100.0 | ENGINE (white) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 92 | c3e3 | e4d6 | -479 | 88.68983059287123 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 93 | e4c5 | e3c3 | -545 | 88.22757521950984 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 94 | a3c1 | a2a8 | -425 | 78.22496322599059 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 95 | g2f2 | e3a3 | -592 | 72.44512183059014 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 96 | e3a3 | a2e2 | -606 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 97 | a2c2 | c1e3 | -643 | 95.05013695325762 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 98 | c1e3 | f2e2 | -660 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 | |
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 99 | f2g2 | a3c3 | -851 | 83.83049669966114 | 46.74324143442006 | 34.81813460952965 | ||
| Capablanca, Jose | Van Hoorn, Peter | 1911-09-09 | 100 | a3c3 | c2c3 | -929 | 100.0 | ENGINE (black) | 46.74324143442006 | 34.81813460952965 |
Im letzten Beispiel wählen wir eine außergewöhnlich miserable Partie, die 1843 zwischen Howard Staunton und Pierre Saint Amant gespielt wurde. Diese Partie strotzt von wechselseitigen schweren Fehlern bis hin zu Patzern, wo Staunton einzügig die Dame einstellt und sein Gegner das Nehmen im nächsten Zug übersieht. Dementsprechend hoch sind die beidseitigen STDCPL-Werte in dieser Partie (403 bzw. 370). Den Spielausgang kann man daher getrost als rein zufällig bezeichnen.
SQL-Code
select
pw.name white,
pb.name black,
g.game_date,
p.half_move_num,
p.move_white,
p.move_black,
pa.best_move_uci ,
pa.centipawn ,
dap.accuracy ,
case
when mod(p.half_move_num, 2) = 1 then concat(dap.judgement, ' (white)')
else concat(dap.judgement, ' (black)')
end judgement ,
dag.stdcpl_white ,
dag.stdcpl_black
from
game g
join player pw on
g.white_player_id = pw.id
join player pb on
g.black_player_id = pb.id
join position p on
(g.id = p.game_id)
left outer join position_analysis pa on
(p.id = pa.position_id)
left outer join da_position dap on
dap.position_id = p.id
join da_game dag on
dag.game_id = g.id
where
(dag.stdcpl_black > 100
or dag.stdcpl_white > 100)
and g.id = 2135380;
| white | black | game_date | half_move_num | move_white | move_black | best_move_uci | centipawn | accuracy | judgement | stdcpl_white | stdcpl_black |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 1 | e2e3 | 403.74044333982107 | 370.3756426476594 | |||||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 2 | c7c5 | c2c4 | 50 | 403.74044333982107 | 370.3756426476594 | |||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 3 | d2d4 | d7d5 | 48 | 99.18287334703136 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 4 | b8c6 | d4d5 | 127 | 72.64819113459816 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 5 | g1f3 | e7e6 | 44 | 71.45097510986818 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 6 | g8f6 | d4d5 | 117 | 74.35052759072649 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 7 | c2c4 | c5d4 | 37 | 72.21769573355104 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 8 | e7e6 | d4d5 | 112 | 73.67713104740619 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 9 | b1c3 | d7d5 | 39 | 74.29254981986386 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 10 | a7a6 | d4d5 | 138 | 67.00118700766166 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 11 | b2b3 | c5d4 | 24 | 62.92062187634332 | INACCURACY (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 12 | f8d6 | d4d5 | 92 | 75.65811662588936 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 13 | f1d3 | b7b6 | 73 | 92.60155090848069 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 14 | c5d4 | e3d4 | 79 | 97.59540924274071 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 15 | e3d4 | e8g8 | 79 | 100.0 | ENGINE (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 16 | d6b4 | c1b2 | 94 | 94.12644832526924 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 17 | c1b2 | e8g8 | 97 | 100.0 | ENGINE (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 18 | b7b5 | a2a3 | 112 | 94.19185434199976 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 19 | e1g1 | b5c4 | 68 | 83.74005474114756 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 20 | c6e7 | d4d5 | 162 | 68.84101472758404 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 21 | d1e2 | e7g6 | 56 | 65.5025076137702 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 22 | e8g8 | c3e4 | 135 | 72.76221332973304 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 23 | a1d1 | c8b7 | 30 | 65.29404159355278 | 403.74044333982107 | 370.3756426476594 | ||
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 24 | e7d5 | c4d5 | 424 | 24.905030901840107 | MISTAKE (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 25 | e2e4 | f6e4 | -504 | 1.91813508827628 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 26 | g7g6 | e4e1 | 15 | 16.67689126087987 | BLUNDER (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 27 | f3e5 | f6e4 | -455 | 18.7207852320375 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 28 | b4d6 | e4e1 | 165 | 9.068517093385463 | BLUNDER (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 29 | f1e1 | f6e4 | -434 | 9.64340361663811 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 30 | f8e8 | e4h4 | 211 | 7.707210635239614 | BLUNDER (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 31 | e5g4 | f6e4 | -314 | 11.653088091962234 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 32 | g8f8 | g4f6 | 497 | 3.698043271077733 | BLUNDER (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 33 | e4d5 | e6d5 | -417 | 2.070225949606596 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 34 | b5b4 | d5d6 | 849 | 0.27815417317886837 | BLUNDER (black) | 403.74044333982107 | 370.3756426476594 | |
| Staunton, Howard | Saint Amant, Pierre C | 1843-01-01 | 35 | f2f3 | e6d5 | -451 | 0.025104528136267845 | BLUNDER (white) | 403.74044333982107 | 370.3756426476594 |
Damit können wir guten Gewissens, eine brauchbare Einstufung gefunden zu haben, die Zählung für unsere Spielerliste durchführen.
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
t.spieler "Spieler",
round(sum(case when t.STDCPLSpieler >= 0 and t.STDCPLSpieler < 5 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [0;5[",
round(sum(case when t.STDCPLSpieler >= 5 and t.STDCPLSpieler < 10 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [5;10[",
round(sum(case when t.STDCPLSpieler >= 10 and t.STDCPLSpieler < 20 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [10;20[",
round(sum(case when t.STDCPLSpieler >= 20 and t.STDCPLSpieler < 30 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [20;30[",
round(sum(case when t.STDCPLSpieler >= 30 and t.STDCPLSpieler < 40 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [30;40[",
round(sum(case when t.STDCPLSpieler >= 40 and t.STDCPLSpieler < 50 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [40;50[",
round(sum(case when t.STDCPLSpieler >= 50 and t.STDCPLSpieler < 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [50;60[",
round(sum(case when t.STDCPLSpieler >= 60 and t.STDCPLSpieler < 70 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [60;70[",
round(sum(case when t.STDCPLSpieler >= 70 and t.STDCPLSpieler < 80 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [70;80[",
round(sum(case when t.STDCPLSpieler >= 80 and t.STDCPLSpieler < 90 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [80;90[",
round(sum(case when t.STDCPLSpieler >= 90 and t.STDCPLSpieler < 100 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [90;100[",
round(sum(case when t.STDCPLSpieler >= 100 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL 100-"
from
(
select
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
nvl(case when p.id = g.white_player_id then dg.stdcpl_white else dg.stdcpl_black end, 0.0) "STDCPLSpieler"
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join da_game dg on
dg.game_id = g.id
join position po on
po.game_id = g.id
join position_analysis pa on
pa.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end,
g.id
) t
group by
t.spieler
order by 2 desc,
3 desc,
4 desc,
5 desc""", conn)
return(df)
def visualize_data(p_df):
cmap = plt.cm.RdYlGn_r
colors = cmap(np.linspace(0.0, 1.0, 12))
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,21), color=colors, ylabel="Anteile STDCPL-Klassen", title="Partie-Anteile der Schachweltmeister nach Spielkonstanz")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Anteil STDCPL [0;5['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Anteil STDCPL [5;10['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Anteil STDCPL [10;20['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Anteil STDCPL [20;30['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Anteil STDCPL [30;40['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[5], labels=p_df['Anteil STDCPL [40;50['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[6], labels=p_df['Anteil STDCPL [50;60['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[7], labels=p_df['Anteil STDCPL [60;70['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[8], labels=p_df['Anteil STDCPL [70;80['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[9], labels=p_df['Anteil STDCPL [80;90['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[10], labels=p_df['Anteil STDCPL [90;100['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[11], labels=p_df['Anteil STDCPL 100-'], rotation = 0, label_type = "center")
plt.ylim([0, 130])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Die obige Grafik ist durchaus diskussionswürdig. Gewichtet man das engste STDCPL-Intervall am höchsten, gelangt man zum gezeigten Ergebnis mit Anand als konstantestem Spieler, Morphy in einer Liga mit Spassky und Carlsen sowie Gukesh auf dem vorletzten Platz.
Wenn man die STDCPL-Werte empirisch mit der ELO-Zahl als Maß für die Spielstärke verknüpft wie in einem bekannten Artikel, käme man eher zum Ergebnis, dass ein STDCPL-Wert bis 40 auf jeden Fall eines Super-Großmeisters würdig ist. Das entspricht in unserer Grafik den ersten fünf (grünen) Balkensegmenten. Danach wäre Tigran Petrosian mit knappem Vorsprung vor Spassky und Smyslov der konstanteste Spieler. Von Staunton kann man auf jeden Fall sagen, dass er den kleinsten Anteil an Partien mit konstantesten und den größten Anteil mit den wechselhaftesten Zügen aufweist. Das hätten wir so erwartet. Auch bestätigt sich unsere obige Vermutung bezüglich der relativ schlechten Platzierung im ACPL-Ranking von D.Gukesh. Tatsächlich fällt er im direkten Vergleich der Konstanzwerte mit den meisten heutigen Top-Spielern aufallend zurück.
Dass aber ein risikofreudiger Spieler wie Tal mit weitem Vorsprung vor Fischer und Capablanca und sogar noch knapp vor Karpow liegt, erstaunt. Jedenfalls lässt die Grafik viel Raum zur Interpretation.
STDCPL-Klassifizierung der Gegner
wir zeigen analog zur ACPL-Klassifizierung der Gegner kurz noch deren STDCPL-Intervall-Anteile. Wieder sind nur geringfügige Code-Änderungen notwendig.
Jupyter Notebook Code
import sys
import os
import getpass
import mariadb
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import warnings
from dotenv import load_dotenv
warnings.filterwarnings('ignore')
def connect(p_password):
global conn
global cursor
# Database connection details
db_config = {
"user": "chess_user",
"password": p_password,
"host": "localhost",
"database": "chess",
"port": 3306, # Standard port for MariaDB
}
# Establishing the connection
conn = mariadb.connect(**db_config)
# Disable autocommit
conn.autocommit = False
# Create a cursor to execute queries
cursor = conn.cursor()
def disconnect():
cursor.close()
conn.close()
def get_data():
df = pd.read_sql_query("""select
t.spieler "Spieler",
round(sum(case when t.STDCPLGegner >= 0 and t.STDCPLGegner < 5 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [0;5[",
round(sum(case when t.STDCPLGegner >= 5 and t.STDCPLGegner < 10 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [5;10[",
round(sum(case when t.STDCPLGegner >= 10 and t.STDCPLGegner < 20 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [10;20[",
round(sum(case when t.STDCPLGegner >= 20 and t.STDCPLGegner < 30 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [20;30[",
round(sum(case when t.STDCPLGegner >= 30 and t.STDCPLGegner < 40 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [30;40[",
round(sum(case when t.STDCPLGegner >= 40 and t.STDCPLGegner < 50 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [40;50[",
round(sum(case when t.STDCPLGegner >= 50 and t.STDCPLGegner < 60 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [50;60[",
round(sum(case when t.STDCPLGegner >= 60 and t.STDCPLGegner < 70 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [60;70[",
round(sum(case when t.STDCPLGegner >= 70 and t.STDCPLGegner < 80 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [70;80[",
round(sum(case when t.STDCPLGegner >= 80 and t.STDCPLGegner < 90 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [80;90[",
round(sum(case when t.STDCPLGegner >= 90 and t.STDCPLGegner < 100 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL [90;100[",
round(sum(case when t.STDCPLGegner >= 100 then 1 else 0 end) / count(t.spieler) * 100, 2) "Anteil STDCPL 100-"
from
(
select
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end Spieler,
nvl(case when p.id = g.white_player_id then dg.stdcpl_black else dg.stdcpl_white end, 0.0) "STDCPLGegner"
from
player p
join game g on
(p.id = g.black_player_id
or p.id = g.white_player_id )
join da_game dg on
dg.game_id = g.id
join position po on
po.game_id = g.id
join position_analysis pa on
pa.position_id = po.id
where
p.name in ('Staunton, Howard', 'Morphy, Paul', 'Steinitz, Wilhelm', 'Lasker, Emanuel', 'Capablanca, Jose', 'Alekhine, Alexander', 'Euwe, Max',
'Botvinnik, Mikhail URS', 'Smyslov, Vasily', 'Smyslov, V.', 'Tal, Mikhail', 'Petrosian, Tigran V', 'Spassky, Boris V.', 'Fischer, Robert J', 'Karpov, Anatoly',
'Kasparov, Garry', 'Kasparov, G.', 'Kramnik, Vladimir', 'Anand, Viswanathan', 'Carlsen, Magnus', 'Ding, Liren', 'Gukesh D')
group by
case
when p.name in ('Kasparov, Garry', 'Kasparov, G.') then 'Kasparov, Garry'
when p.name in ('Smyslov, Vasily', 'Smyslov, V.') then 'Smyslov, Vasily'
else p.name
end,
g.id
) t
group by
t.spieler
order by 2 desc,
3 desc,
4 desc,
5 desc""", conn)
return(df)
def visualize_data(p_df):
cmap = plt.cm.RdYlGn_r
colors = cmap(np.linspace(0.0, 1.0, 12))
ax=p_df.plot(x='Spieler', kind='bar', width=.8, stacked=True, figsize=(20,21), color=colors, ylabel="Anteile gegnerische STDCPL-Klassen", title="Partie-Anteile der Gegner nach Spielkonstanz")
plt.bar_label(ax.containers[-1], rotation = 0, label_type = "edge", padding=6)
plt.bar_label(ax.containers[0], labels=p_df['Anteil STDCPL [0;5['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[1], labels=p_df['Anteil STDCPL [5;10['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[2], labels=p_df['Anteil STDCPL [10;20['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[3], labels=p_df['Anteil STDCPL [20;30['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[4], labels=p_df['Anteil STDCPL [30;40['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[5], labels=p_df['Anteil STDCPL [40;50['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[6], labels=p_df['Anteil STDCPL [50;60['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[7], labels=p_df['Anteil STDCPL [60;70['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[8], labels=p_df['Anteil STDCPL [70;80['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[9], labels=p_df['Anteil STDCPL [80;90['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[10], labels=p_df['Anteil STDCPL [90;100['], rotation = 0, label_type = "center")
plt.bar_label(ax.containers[11], labels=p_df['Anteil STDCPL 100-'], rotation = 0, label_type = "center")
plt.ylim([0, 130])
plt.show()
def main():
# try to get passwd from .env file
load_dotenv()
passwd = os.getenv("passwd")
# If password not provided, prompt securely
if not passwd:
try:
passwd = getpass.getpass(prompt="Enter database password: ")
except (KeyboardInterrupt, EOFError):
print("\nPassword input cancelled.")
sys.exit(1)
# Validate password input
if not passwd.strip():
print("Error: Database password cannot be empty.")
sys.exit(1)
# connect to database
try:
connect(passwd)
df = get_data()
visualize_data(df)
disconnect()
except Exception as e:
print(e)
try:
disconnect()
except:
pass
sys.exit(1)
if __name__ == "__main__":
main()

Als erstes sticht auch bei dieser Metrik wieder das schlechteste Abschneiden von Morphy’s Gegnern ins Auge, dicht gefolgt von Staunton’s Gegnern.
Dass bei Bobby Fisher die rötlichen Bereiche viel ausgedehnter sind als bei seinen russischen Zeitgenossen wie z.B. Tal, Smyslow, Petrosian und Spassky dürfte dem Umstand geschuldet sein, dass die meisten seiner Gegner in der westlichen Hemisphäre beheimatet waren. Insbesondere Amerika war im Vergleich zur damaligen Sowjetunion schachlich wenig entwickelt und eine US-Meisterschaft zu jener Zeit hielt keinem Vergleich zur Meisterschaft der UDSSR stand.
Im Übrigen zeigt sich das erwartete Gesamtbild – heutige Gegner spielen nicht nur stärker, sondern auch konstant stärker.
Was noch?
Wir könnten an dieser Stelle noch weitere Kennzahlen wie Sharpness oder die Kennzahlen-Entwicklung einzelner Spieler im Laufe ihrer Entwicklung über verschiedene Jahre hinweg betrachten. Doch wir wollen unsere Untersuchungen an dieser Stelle beenden und damit auch Raum für weitere interessante Forschungen geben.
Im nächsten Kapitel werden wir die Bilanz unserer bisherigen Erkenntnisse ziehen und unsere Gesamt-Einschätzung hinsichtlich der Eingangsfrage darlegen.