はじめに
csTimer で記録したスピードキューブの結果をヒストグラムで表示する Python script を作りましたので紹介します。
このブログでは、定期的にスピードキューブ (9マスで区切られた色違いの6面体を揃えるゲーム) の結果を記事にしています。バラバラにする手順と揃えるまでの時間の記録には csTimer というサイトを使用しています。
csTimer のサイトでは、記録している結果を txt ファイル (中身は JSON 形式) で出力する事が出来ます。過去の結果を振り返る為やデータの意図しない消去に備える為に、一日のキューブを揃える時間を記録した後には、PC にバックアップするようにしています。
このバックアップしているデータは生データですので、なかなか活用できていませんでした。今回、gemini と協力してスピードキューブのソルブ時間をヒストグラムで表示する Python script を作りましたので紹介します。
動作確認した環境
紹介する Python Script は次の環境で動作する事を確認しました。
- Windows11 Pro 24H2 : Build 26100.3037
- WSL2 & WSLg : Ver.2.3.26.0
- Ubuntu (WSL2) : 22.04.5 LTS
- Python (Ubuntu) : Ver.3.10.12
- python3-venv (Ubuntu) : 3.10.6
- python3L-tk (Ubuntu) : 3.10.8
- Japanese Font : IPAGothic
- Simplified Chinese Font : Microsoft YaHei
以下に動作環境の作り方とスクリプトについて記載します。
Windows11 WSL2 Ubuntu の環境を作る
最初に、Windows11 に WSL2 Ubuntu の環境を作成します。今回は Ubuntu 22.04 LTS の環境が既にありましたので、この環境を使用しました。
WSL2 Ubuntu の環境を新たに作る方法については、検索すると色々出てきますので省略します。日本語の場合は note に記事を書いていますので、こちらを参考にして下さい。
この状態で WSL2 で Python が動作する事を確認して下さい。
$ python3 --version
Python 3.10.12
Bash後で使いますので、python3-venv と python3-tk をインストールします。インストール済であれば以下の表示となります。
$ sudo apt install python3-venv python3-tk
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
python3-tk is already the newest version (3.10.8-1~22.04).
python3-venv is already the newest version (3.10.6-1~22.04.1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
BashPython 仮想環境を作る
Python を使用する場合には、仮想環境を作成して、その中で作業すると良いと思います。大元の環境を汚さずに作業できますし、不要になればディレクトリごと削除すれば済みます。
今回は python3-venv で仮想環境を作って仮想環境の中に入ります。
$ mkdir cstimer_histgram_ja
$ cd cstimer_histgram_ja
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $
Bash必要な Python ライブラリを pip でインストールします。
$ pip install pandas matplotlib
Bashmatplotlib で描画したグラフを WSLg で Windows11 側に表示する為に、前項で python3-tk をインストールしました。
csTimer の JSON をヒストグラム表示する Python Script
次の Python script を該当ディレクトリに保存して下さい。名称は cstimer_histgram_ja.py とします。
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import json
import argparse
import pytz
import datetime
def calculate_and_plot(session_data, session_name):
"""
指定されたセッションのデータに対して、平均値を計算し、ヒストグラムを表示する関数
Args:
session_data: セッションのデータ (リスト)
session_name: セッションの名前 (文字列)
"""
# session_name が properties の時は何もせずに戻る
if session_name == "properties":
return
# ソルブ時間を抽出
tz = pytz.timezone('Asia/Tokyo')
solve_times = []
timestamps = []
for item in session_data:
if len(item) > 0 and isinstance(item[0], list) and len(item[0]) > 1:
solve_time = item[0][1] / 1000
timestamp = datetime.datetime.fromtimestamp(item[3], tz=tz)
else:
solve_time = None
timestamp = None
#print(f"Warning: Unexpected data format in session {session_name}, item: {item}")
solve_times.append(solve_time)
timestamps.append(timestamp)
# 平均値を計算
valid_solve_times = [t for t in solve_times if t is not None]
if valid_solve_times:
average_time = sum(valid_solve_times) / len(valid_solve_times)
average_time = round(average_time,3)
start_datetime = timestamps[0].strftime("%Y/%m/%d %H:%M")
end_datetime = timestamps[-1].strftime("%Y/%m/%d %H:%M")
print(f"{session_name} : 平均ソルブ時間 : {average_time} : 開始日時 : {start_datetime} : 終了日時 : {end_datetime}")
# ヒストグラムを表示
plt.hist(valid_solve_times, bins=20)
plt.title(f"セッション{session_name}のソルブ時間ヒストグラム")
plt.xlabel("ソルブ時間")
plt.ylabel("頻度")
plt.show()
#plt.savefig(f"time_distribution_{session_name}.png")
plt.clf() # グラフ領域をクリア
else:
print(f"セッション{session_name} に有効なデータが存在しません。")
# rcParamsの設定
plt.rcParams['font.family'] = 'IPAGothic' # 使用するフォント名
plt.rcParams['font.size'] = 16
# コマンドライン引数を解析する
parser = argparse.ArgumentParser()
parser.add_argument("json_file", help="JSONファイルのパス")
parser.add_argument("-s","--session_name", help="集計対処のセッション名")
parser.add_argument("-a","--all", help="全セッションで実行", action='store_true')
args = parser.parse_args()
# JSONファイルを読み込む
with open(args.json_file, 'r') as f:
data = json.load(f)
# 各セッションに対して処理を実行
if args.all == False:
if args.session_name in data : # sessison が指定されていればそのセッションのみ集計
session_data = data[args.session_name]
calculate_and_plot(session_data, args.session_name)
else:
print(f"セッション:{args.session_name}が見つかりません。")
# 全てのセッションを集計
if args.all:
for session_name, session_data in data.items():
calculate_and_plot(session_data, session_name)
cstimer_histgram_ja.pyWSL2 の該当ディレクトリで notepad.exe を起動するのが簡単です。次のように WSL2 で空のファイルを作成して、そのファイルを notepad.exe で開き、上記のスクリプトをコピーして貼り付け保存します。
(.venv) $ echo "" > cstimer_histgram_ja.py
(.venv) $ notepad.exe cstimer_histgram_ja.py
Bash空のファイルを作成するのは、改行コードを Linux に合わせる為です。
実行例
csTimer で記録した txt ファイルを、Python script と同じディレクトリに準備してください。
cstimer_histgram_ja.py を ‘-h’ 付で実行すると、使い方が表示されます。
(.venv) $ python cstimer_histgram_ja.py -h
usage: cstimer_histgram_ja.py [-h] [-s SESSION_NAME] [-a] json_file
positional arguments:
json_file JSONファイルのパス
options:
-h, --help show this help message and exit
-s SESSION_NAME, --session_name SESSION_NAME
集計対処のセッション名
-a, --all 全セッションで実行
Bashtxt ファイルとセッションを指定して実行した結果です。
(.venv) $ python cstimer_histgram_ja.py -s session1 cstimer_20250126_235844.txt
session1 : 平均ソルブ時間 : 52.324 : 開始日時 : 2024/07/21 21:29 : 終了日時 : 2024/08/27 20:21
Bash
ターミナルにはセッションの平均ソルブ時間、開始日時、終了日時が表示されます。新しいウィンドウが開き、ヒストグラムが表示されます。
ヒストグラムのウィンドウを閉じると、ターミナル上で Python script が終了します。
オプション ‘-s’ の代わりに ‘-a’ を指定すると、全てのセッションのそれぞれについて平均ソルブ時間やヒストグラムが表示されます。グラフの画面表示が鬱陶しい場合には、Python script の 51行目をコメントに、52行目のコメントを外すと、PNG ファイルで保存されます。

結び
csTimer で記録して PC にバックアップしていた過去データをどのように活用するか考えていました。csTimer の JSON ファイルの構造についての資料もありませんでしたので、gemini にデータを渡して解析を手伝ってもらい、更に Python script の形にまとめる部分も生成してもらいました。
エラーメッセージをコピペするだけで改善案も生成されますので、生成 AI と共同してプログラムを作成するのは効率よく作業できます。
今後は
- ao5 や ao12 を算出
- session を跨いで期間を指定した平均、ヒストグラムの算出
- トレンドグラフの作成
- GUI の追加
辺りに取り組めたらと考えています。
コメントを残す