显示 csTimer 速方结果直方图的 Python 脚本

3 x 3 rubiks cube

页面语言切换

序文

我们创建了一个 Python 脚本,用于显示 csTimer 记录的速方结果直方图。

本博客定期发布 “速度立方体”(Speed Cube,一种将不同颜色的六面体排列在 9 个方格之间的游戏)的结果。我使用 csTimer 网站记录肢解过程和排列棋子所需的时间。

在 csTimer 网站上,您可以将记录的结果输出为 txt 文件(内容为 JSON 格式)。为了回顾过去的结果并防备无意中删除数据,我在记录完每天的立方体对齐时间后都会备份电脑。

这些备份数据是原始数据,因此不易利用。这次,我与 gemini 合作,创建了一个 Python 脚本,用于显示 speedcube 解算时间的直方图。

检查操作的环境

此处介绍的 Python 脚本已被确认可在以下环境中运行

  • 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

下面将介绍如何创建工作环境和脚本。

创建 Windows 11 WSL2 Ubuntu 环境

首先,在 Windows 11 上创建一个 WSL2 Ubuntu 环境。这次我使用 Ubuntu 22.04 LTS 环境,因为它已经可用。

关于如何创建一个新的 WSL2 Ubuntu 环境的信息,我将省略,因为在搜索时会以各种方式出现。日文请参阅注释中的文章。

确保 Python 在这种状态下能与 WSL2 一起工作。

Bash
$ python3 -V
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_zh
$ cd cstimer_histgram_zh
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $
Bash

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

Bash
$ pip install pandas matplotlib
Bash

为了在 Windows11 端使用 WSLg 显示用 matplotlib 绘制的图形,我在上一节中安装了 python3-tk。

显示 csTimer JSON 直方图的 Python 脚本

将以下 Python 脚本保存在相关目录中。将其命名为 cstimer_histgram_zh.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}") # 警告:会话 {session_name} 中数据格式意外,项目:{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'] = 'Microsoft YaHei'  # 使用的字体名称
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 :  # 如果指定了会话,则只统计该会话
        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_zh.py

在 WSL2 的相关目录中启动 notepad.exe 很容易。在 WSL2 中创建一个如下所示的空文件,用 notepad.exe 打开该文件,复制、粘贴并保存上述脚本。

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

创建空文件的原因是为了使换行代码适应 Linux。

工作示例

在与 Python 脚本相同的目录下准备 csTimer 记录的 txt 文件。

使用”-h “运行 cstimer_histgram_zh.py,了解如何使用它。

Bash
(.venv) $ python cstimer_histgram_zh.py -h
usage: cstimer_histgram_zh.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_zh.py cstimer_20250126_235844.txt -s session1
session1 : 平均解算时间 : 52.324 : 开始日期时间 : 2024/07/21 21:29 : 结束日期时间 : 2024/08/27 20:21
Bash
在窗口中显示直方图
在窗口中显示直方图

终端会显示会话的平均求解时间、开始日期和时间以及结束日期和时间。打开一个新窗口并显示柱状图。

关闭直方图窗口可终止终端上的 Python 脚本。

如果指定”-a “而不是选项”-s”,则会显示所有会话的平均求解时间和直方图。如果屏幕上显示的图形令人沮丧,可取消 Python 脚本第 51 行和第 52 行的注释,将其保存为 PNG 文件。

以 PNG 格式记录直方图
以 PNG 格式记录直方图

Musubi

csTimer 的 JSON 文件结构没有文档说明,因此我将数据交给了 gemini,让他们帮我分析数据,并生成一个 Python 脚本对数据进行汇总。我还请 gemini 生成一个 Python 脚本来汇总数据。

使用生成的人工智能创建程序非常高效,因为只需复制和粘贴错误信息就能生成改进建议。

未来,

  • 计算 ao5 和 ao12
  • 计算指定时段内各时段的平均值和柱状图。
  • 创建趋势图
  • 增加图形用户界面

我们希望在该地区开展工作。

Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注