/*:
 * @plugin WeightedRandomChoice
 * @target MZ
 * @plugindesc 重み付きランダム選択を行うプラグイン
 * @help
 * @author えむうん
 * @desc 重み付きランダム選択を行うプラグイン
 * @help
 * WeightedRandomChoice プラグイン
 * 
 * このプラグインは、重み付きランダム選択機能を提供します。
 * イベントコマンドのプラグインコマンドから利用できます。
 * 
 * 【主な機能】
 * 1. 重み付きランダム選択
 * 2. 確率テーブルの保存と読み込み
 * 3. 複数回の重み付きランダム選択
 * 4. 乱数シードの設定
 * 
 * 【使用方法】
 * 1. 重み付きランダム選択:
 *    確率に基づいてランダムに値を選択し、指定した変数に格納します。
 *    例: 10,20,30,40 と指定した場合、
 *        1が選ばれる確率: 10%
 *        2が選ばれる確率: 20%
 *        3が選ばれる確率: 30%
 *        4が選ばれる確率: 40%
 * 
 * 2. 確率テーブルの保存:
 *    よく使う確率パターンを名前を付けて保存できます。
 * 
 * 3. 確率テーブルの読み込み:
 *    保存した確率パターンを読み込んで使用します。
 * 
 * 4. 複数回の重み付きランダム選択:
 *    指定回数だけランダム選択を繰り返し、結果を配列として変数に格納します。
 * 
 * 5. 乱数シードの設定:
 *    乱数生成のシードを設定し、再現可能な結果を得られるようにします。
 * 
 * 【注意事項】
 * - 確率の重みは自動的に正規化されるため、合計が100である必要はありません。
 * - 乱数シードを設定すると、同じシードでは常に同じ結果が得られます。
 * 
 * @command weightedRandom
 * @text 重み付きランダム選択
 * @desc 指定された重みに基づいてランダムな選択を行います。
 *
 * @arg variableId
 * @type variable
 * @text 結果を格納する変数
 * @desc 選択結果を格納する変数のIDを指定します。
 *
 * @arg weights
 * @type string
 * @text 重み
 * @desc カンマ区切りで重みを指定します。例: 10,20,30,40
 *
 * @command saveWeightTable
 * @text 確率テーブルの保存
 * @desc 確率テーブルを保存します。
 *
 * @arg tableId
 * @type string
 * @text テーブルID
 * @desc 保存する確率テーブルのIDを指定します。
 *
 * @arg weights
 * @type string
 * @text 重み
 * @desc カンマ区切りで重みを指定します。例: 10,20,30,40
 *
 * @command loadWeightTable
 * @text 確率テーブルの読み込み
 * @desc 保存された確率テーブルを読み込んでランダム選択を行います。
 *
 * @arg tableId
 * @type string
 * @text テーブルID
 * @desc 読み込む確率テーブルのIDを指定します。
 *
 * @arg variableId
 * @type variable
 * @text 結果を格納する変数
 * @desc 選択結果を格納する変数のIDを指定します。
 *
 * @command multipleWeightedRandom
 * @text 複数回の重み付きランダム選択
 * @desc 指定された重みに基づいて複数回のランダム選択を行います。
 *
 * @arg variableId
 * @type variable
 * @text 結果を格納する変数
 * @desc 選択結果を格納する変数のIDを指定します。配列として格納されます。
 *
 * @arg weights
 * @type string
 * @text 重み
 * @desc カンマ区切りで重みを指定します。例: 10,20,30,40
 *
 * @arg times
 * @type number
 * @text 選択回数
 * @desc ランダム選択を行う回数を指定します。
 * @default 1
 *
 * @command setSeed
 * @text 乱数シードの設定
 * @desc 乱数生成のシードを設定します。
 *
 * @arg seed
 * @type number
 * @text シード値
 * @desc 乱数生成のシード値を指定します。
 */

(() => {
    const pluginName = "WeightedRandomChoice";

    let randomGenerator = Math.random;

    // 重み付きランダム選択の関数
    function weightedRandomChoice(weights) {
        const normalizedWeights = normalizeWeights(weights);
        const randomNum = randomGenerator();
        let cumulativeWeight = 0;
        
        for (let i = 0; i < normalizedWeights.length; i++) {
            cumulativeWeight += normalizedWeights[i];
            if (randomNum < cumulativeWeight) {
                return i + 1;  // 1から始まる数字にするため+1
            }
        }
    }

    // 重みの正規化関数
    function normalizeWeights(weights) {
        const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
        return weights.map(weight => weight / totalWeight);
    }

    PluginManager.registerCommand(pluginName, "weightedRandom", args => {
        const variableId = Number(args.variableId);
        const weights = args.weights.split(',').map(Number);
        const result = weightedRandomChoice(weights);
        $gameVariables.setValue(variableId, result);
    });

    PluginManager.registerCommand(pluginName, "saveWeightTable", args => {
        const tableId = args.tableId;
        const weights = args.weights.split(',').map(Number);
        $gameSystem.weightTables = $gameSystem.weightTables || {};
        $gameSystem.weightTables[tableId] = weights;
    });

    PluginManager.registerCommand(pluginName, "loadWeightTable", args => {
        const tableId = args.tableId;
        const variableId = Number(args.variableId);
        const weights = $gameSystem.weightTables[tableId];
        if (weights) {
            const result = weightedRandomChoice(weights);
            $gameVariables.setValue(variableId, result);
        } else {
            console.error(`Error: Weight table "${tableId}" not found.`);
        }
    });

    PluginManager.registerCommand(pluginName, "multipleWeightedRandom", args => {
        const variableId = Number(args.variableId);
        const weights = args.weights.split(',').map(Number);
        const times = Number(args.times);
        const results = [];
        for (let i = 0; i < times; i++) {
            results.push(weightedRandomChoice(weights));
        }
        $gameVariables.setValue(variableId, results);
    });

    PluginManager.registerCommand(pluginName, "setSeed", args => {
        const seed = Number(args.seed);
        const random = new Math.seedrandom(seed);
        randomGenerator = () => random();
    });

    // Math.seedrandom のシンプルな実装
    // 注意: これは完全な実装ではありません。本格的な用途には適切なライブラリを使用してください。
    Math.seedrandom = function(seed) {
        return function() {
            seed = (seed * 9301 + 49297) % 233280;
            return seed / 233280;
        };
    };
})();