import sys
import numpy as np
import matplotlib.pyplot as plt
import random
from matplotlib import rcParams

# フォント設定
rcParams['font.family'] = 'MS Gothic'

# パラメータ設定
Nmax = 1000         # 乱数の最大値
Nsmax = 10          # seedの最大値
num_samples = 100   # 各seedで生成する乱数の個数

# アルゴリズムとGeneratorタイプの選択
# random, numpy: Mersenne Twister
#generator:
# PCG64: Permuted Congruential Generator 64-bit	高速・現代的・デフォルトの選択肢。周期は 2^128
# MT19937: Mersenne Twister 19937-bit	古典的で広く使われる。周期は 2^19937 − 1
# Philox: Philox Counter-Based RNG	並列処理に強く、暗号的設計に近い。
# SFC64:Small Fast Counter 64-bit
selected_algorithm = "generator"       # "numpy", "generator", "random"
selected_generator_type = "MT19937"    # "PCG64", "MT19937", "Philox", "SFC64"

if len(sys.argv) > 1: selected_algorithm = sys.argv[1]
if len(sys.argv) > 2: selected_generator_type = sys.argv[2]
if selected_algorithm == 'numpy' or selected_algorithm == 'random':
    selected_generator_type = 'Mersenne Twister'

def usage():
    print()
    print("Usage: python rand_trace.py algorithm generator_type")
    print("   algorithm: 'random' and 'numpy' for Mersenne Twister method")
    print("   algorithm: 'generator' can choose the following options")
    print("     generator_type: 'PCG64', 'MT19937', 'Philox', 'SFC64'")
    print()


# Generatorの種類を選択
def get_bit_generator(generator_type, seed):
    if generator_type == "PCG64":
        return np.random.Generator(np.random.PCG64(seed))
    elif generator_type == "MT19937":
        return np.random.Generator(np.random.MT19937(seed))
    elif generator_type == "Philox":
        return np.random.Generator(np.random.Philox(seed))
    elif generator_type == "SFC64":
        return np.random.Generator(np.random.SFC64(seed))
    else:
        raise ValueError("未対応のGeneratorタイプです: PCG64 / MT19937 / Philox / SFC64")

# 乱数生成関数（アルゴリズム選択）
def generate_random_series(seed, size, max_value, algorithm="numpy", generator_type="PCG64"):
    if algorithm == "numpy":
        np.random.seed(seed)
        return np.random.randint(0, max_value + 1, size=size)
    elif algorithm == "generator":
        rng = get_bit_generator(generator_type, seed)
        return rng.integers(0, max_value + 1, size=size)
    elif algorithm == "random":
        random.seed(seed)
        return [random.randint(0, max_value) for _ in range(size)]
    else:
        print(f"未対応のアルゴリズムです [{algorithm}]: numpy / generator / random")
        usage()

# サブプロットの準備
fig, axes = plt.subplots(1, Nsmax, figsize=(20, 4), sharey=True)

for seed in range(1, Nsmax + 1):
    random_values = generate_random_series(seed, num_samples, Nmax,
                                           algorithm=selected_algorithm,
                                           generator_type=selected_generator_type)
    ax = axes[seed - 1]
    ax.plot(random_values, range(num_samples), lw=1)
    ax.set_title(f"seed={seed}")
    ax.set_xlabel("乱数の値")
    if seed == 1:
        ax.set_ylabel("発生番号")
    ax.grid(True)

plt.suptitle(f"アルゴリズム: {selected_algorithm}（{selected_generator_type}）", fontsize=14)
plt.tight_layout()

usage()

plt.show()
