Vor kurzem spiele ich ungefähr 2 Stunden lang einmal pro Woche mit meiner Familie auf der Online-Mahjong-Website Tenhou.
Dieses Mal werde ich die Analyse der Wettbewerbsergebnisse erläutern, damit jeder in der Familie sie im Internet sehen kann.
Als Prozess:
So fertig ↓ https://drmahjong.herokuapp.com/
Den Code finden Sie auf dem Github unten. https://github.com/mottoki/mahjan-score
Tenho-Daten können aus Log entnommen werden. Nehmen Sie die Daten mit einem Modul namens Anfrage.
python.py
import requests
import datetime
new_date = datetime.datetime.now().strftime('%Y%m%d')
url = "https://tenhou.net/sc/raw/dat/"+f"sca{new_date}.log.gz"
filename = f"sca{new_date}.log.gz"
# Download gz file from the url
with open(filename, "wb") as f:
r = requests.get(url)
f.write(r.content)
Filtern Sie die Rohdaten nach Spielernamen und extrahieren Sie mithilfe von Split Datenrahmen, die nur Spielernamen und Punkte enthalten.
new_data.py
import os
import pickle
import pandas as pd
#Spielername
playercol = ['date', 'Mirataro', 'Shinwan', 'ToShiroh', 'yukoron']
#In Pandas-Datenrahmen konvertieren
df = pd.read_csv(filename, usecols=[0], error_bad_lines=False, header=None)
df[len(df.columns)] = new_date
#Nach Spielernamen filtern
df = df[(df[0].str.contains(playercol[1])) &
(df[0].str.contains(playercol[2])) &
(df[0].str.contains(playercol[3])) &
(df[0].str.contains(playercol[4]))]
#Verarbeiten Sie den Datenrahmen
df[['one','two','three','four']] = df[0].str.split('|', 3, expand=True)
df.columns = ['original', 'date', 'room', 'time', 'type', 'name1']
df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')
df[['empty', 'n1', 'n2', 'n3', 'n4']] = df.name1.str.split(" ", n=4, expand=True)
#Verwenden Sie nur wichtige Spalten
df = df[['date', 'n1', 'n2', 'n3', 'n4']]
#Entfernen Sie die an der Partitur und dem Namen angebrachten Schlüsselklammern, um einen Datenrahmen zu erstellen
new_score = pd.DataFrame(columns=playercol)
k=0
for i, j in df.iterrows():
dd = j[0]
new_score.loc[k, 'date'] = dd
for name in df.columns[1:]:
s = j[name]
player = s.split('(')[0]
score = [p.split(')')[0] for p in s.split('(') if ')' in p][0]
score = int(float(score.replace('+', '')))
new_score.loc[k, player] = score
k += 1
#Rufen Sie alte Daten von Pickle auf
current_dir = os.getcwd()
old_score = pd.read_pickle(f"{current_dir}/players_score.pkl")
#Kombinieren Sie neue und alte Daten
concat_score = pd.concat([old_score, new_score], ignore_index=True)
concat_score.to_pickle(f"{current_dir}/players_score.pkl")
Verwenden Sie eine Bibliothek namens Dash, um Daten schnell zu visualisieren.
Das Dash-Tutorial ist am einfachsten zu verstehen. (Referenz: Dash Documentation & User Guide)
Der Teil, der in Dash abgefangen wird, ist die Funktion Callback, aber es gibt Leute, die dies ausführlich erläutern, z. B. Python-Visualisierungsbibliothek Dash 2 verwenden, siehe Callback. Bitte beziehen Sie sich darauf.
Das Erklären des gesamten Codes wäre langwierig, daher werde ich den Kernteil als Beispiel erläutern.
Grundsätzlich ist alles im ersten app.layout =
das, was Sie auf Ihrer Website sehen.
Wenn Sie style = {'display': 'none'}
eingeben, können Sie die Dinge ausblenden, die Sie nicht anzeigen möchten (z. B. die Daten, die Sie häufig als "Zwischenwerte" verwenden).
#Schreiben Sie das Frontend in diese
app.layout = html.Div([
#Ermöglichen Sie Benutzern, das Datum auszuwählen, das in den Daten angezeigt wird
html.Div([
html.H2("DR.Mahjong"),
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=dt(2020, 3, 1),
max_date_allowed=dt.today(),
end_date=dt.today()
),
], className="mytablestyle"),
#Daten oft verwendet:style={'display': 'none'}Mach es unsichtbar
html.Div(id='intermediate-value', style={'display': 'none'}),
#Übergang von Punkten (Grafik)
dcc.Graph(id='mygraph'),
#Umfassende Punkte (Tabelle)
html.Div([
html.Div(html.P('Aktuelle Gesamtpunkte')),
html.Div(id='totalscore'),
], className="mytablestyle"),
])
Lesen Sie die Daten mit pandas read_pickle, filtern Sie nach Datum, jsonize und geben Sie sie zurück.
Auf diese Weise können Sie dieselben Daten immer wieder in Grafiken und Tabellen verwenden.
@app.callback(Output("intermediate-value", "children"),
[Input("my-date-picker-range", "start_date"),
Input("my-date-picker-range", "end_date")])
def update_output(start_date, end_date):
players = pd.read_pickle('players_score.pkl')
if start_date is not None:
start_date = dt.strptime(re.split('T| ', start_date)[0], '%Y-%m-%d')
players = players.loc[(players['date'] >= start_date)]
if end_date is not None:
end_date = dt.strptime(re.split('T| ', end_date)[0], '%Y-%m-%d')
players = players.loc[(players['date'] <= end_date)]
return players.to_json(date_format='iso', orient='split')
Die jsonisierten Daten werden an den Pandas-Datenrahmen zurückgegeben und grafisch dargestellt und tabellarisch dargestellt.
Die Grafik übernimmt den Plotly-Stil und wird durch go.Figure () dargestellt.
Die Tabelle wird durch html.Table dargestellt. Es gibt auch eine Bibliothek namens dash_table für Tabellen, aber diesmal war die Tabelle einfach, deshalb habe ich mich für diesen Stil entschieden, weil ich ihn nicht brauchte.
@app.callback([Output('mygraph', 'figure'),
Output('totalscore', 'children')],
[Input('intermediate-value', 'children'),
Input('datatype', 'value')])
def update_fig(jsonified_df, data_type):
#Stellen Sie die Jsonized-Daten in Pandas wieder her.
players = pd.read_json(jsonified_df, orient='split')
#Grafik
fig = go.Figure()
for i, name in enumerate(players.columns[1:]):
fig.add_trace(go.Scatter(x=players.date,
y=np.array(players[name]).cumsum(),
mode='lines',
name=name,
line=dict(color=colors[i], width=4)))
fig.update_layout(plot_bgcolor='whitesmoke',
title='Übergang der Gesamtpunkte',
legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1,)
)
#Berechnen Sie die Gesamtpunktzahl
summed = players.sum()
#Gibt Grafiken und Tabellen zurück
return fig, html.Table([
html.Thead(
html.Tr([html.Th(col) for col in summed.index])
),
html.Tbody(
html.Tr([html.Td(val) for val in summed])
),
])
Schließlich werden wir mit Heroku und Github bereitstellen.
Die offizielle Website (Bereitstellen von Dash Apps) enthält detaillierte Anweisungen zur Verwendung von Git und Heroku, sodass die Methoden nahezu identisch sind.
Der Prozess sieht folgendermaßen aus:
Eröffnen Sie ein Github-Konto
Erstellen Sie ein neues Github-Repository
SSH nach Github. (Optional, aber einfacher durchzuführen. Siehe: SSH-Verbindung zu GitHub zulassen)
Erstellen Sie die für die Bereitstellung erforderlichen Dateien (.ignore
, Procfile
, require.txt
). Du brauchst auch ein Gunicorn, also installiere es mit pip install gunicorn
.
Verwenden Sie den Befehl Git, um die obige Datei und die Datendateien app.py
und player_score.pkl
an Github zu senden.
git init
git add .
git commit -m "Botschaft"
git remote add origin [email protected]:<Nutzername>/<Repository-Name>
git push origin master
Nachdem Sie bestätigt haben, dass es an Github gesendet wurde, erstellen Sie ein Heroku-Konto und erstellen Sie eine neue App mit der Schaltfläche "Neu> Neue App erstellen" (Region hat kein Japan, wählen Sie also USA).
Klicken Sie auf die Registerkarte Bereitstellen der erstellten App, setzen Sie die Bereitstellungsmethode auf Github und stellen Sie eine Verbindung zu dem in 2 erstellten Repository her.
Drücken Sie abschließend die schwarze Taste "Zweig bereitstellen" in "Manuelle Bereitstellung", um ihn ohne Erlaubnis bereitzustellen.
Wie war es?
Sie können auch cron und Herokus Automatic Deploy verwenden, um Aktualisierungen neuer Daten von Tenho zu automatisieren. (Referenz: Automatisieren des Push-Vorgangs mit Cron zu Github)
Recommended Posts