csTimer のスピードキューブの結果をヒストグラムで表示する Python script

3 x 3 rubiks cube

カテゴリー :

,

ページ言語切替

はじめに

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 が動作する事を確認して下さい。

Bash
$ python3 --version
Python 3.10.12
Bash

後で使いますので、python3-venv と python3-tk をインストールします。インストール済であれば以下の表示となります。

Bash
$ 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.
Bash

Python 仮想環境を作る

Python を使用する場合には、仮想環境を作成して、その中で作業すると良いと思います。大元の環境を汚さずに作業できますし、不要になればディレクトリごと削除すれば済みます。

今回は python3-venv で仮想環境を作って仮想環境の中に入ります。

Bash
$ mkdir cstimer_histgram_ja
$ cd cstimer_histgram_ja
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $
Bash

必要な Python ライブラリを pip でインストールします。

Bash
$ pip install pandas matplotlib
Bash

matplotlib で描画したグラフを WSLg で Windows11 側に表示する為に、前項で python3-tk をインストールしました。

csTimer の JSON をヒストグラム表示する Python Script

次の Python script を該当ディレクトリに保存して下さい。名称は cstimer_histgram_ja.py とします。

Python
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.py

WSL2 の該当ディレクトリで notepad.exe を起動するのが簡単です。次のように WSL2 で空のファイルを作成して、そのファイルを notepad.exe で開き、上記のスクリプトをコピーして貼り付け保存します。

Bash
(.venv) $ echo "" > cstimer_histgram_ja.py
(.venv) $ notepad.exe cstimer_histgram_ja.py
Bash

空のファイルを作成するのは、改行コードを Linux に合わせる為です。

実行例

csTimer で記録した txt ファイルを、Python script と同じディレクトリに準備してください。

cstimer_histgram_ja.py を ‘-h’ 付で実行すると、使い方が表示されます。

Bash
(.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             全セッションで実行
Bash

txt ファイルとセッションを指定して実行した結果です。

Bash
(.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 ファイルで保存されます。

PNG でヒストグラムを記録
PNG でヒストグラムを記録

結び

csTimer で記録して PC にバックアップしていた過去データをどのように活用するか考えていました。csTimer の JSON ファイルの構造についての資料もありませんでしたので、gemini にデータを渡して解析を手伝ってもらい、更に Python script の形にまとめる部分も生成してもらいました。

エラーメッセージをコピペするだけで改善案も生成されますので、生成 AI と共同してプログラムを作成するのは効率よく作業できます。

今後は

  • ao5 や ao12 を算出
  • session を跨いで期間を指定した平均、ヒストグラムの算出
  • トレンドグラフの作成
  • GUI の追加

辺りに取り組めたらと考えています。

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です