{
  "name": "horseRacing",
  "author": "Limon",
  "supportedGames": [
    "all"
  ],
  "takaroVersion": "main",
  "versions": [
    {
      "tag": "0.0.1",
      "description": "A virtual horse racing system where players can bet and win currency.\n",
      "configSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"type\":\"object\",\"required\":[],\"additionalProperties\":false,\"properties\":{\"minBet\":{\"title\":\"minBet\",\"description\":\"Minimum amount required to place a bet\",\"default\":50,\"type\":\"number\",\"minimum\":1},\"maxBet\":{\"title\":\"maxBet\",\"description\":\"Maximum amount allowed for a bet\",\"default\":1000,\"type\":\"number\",\"minimum\":1},\"Horses\":{\"title\":\"Horses\",\"description\":\"List of horses that can race. Format: HorseName; Odds (whole number) - one horse per line\",\"default\":[\"Thunder; 2\",\"Lightning; 3\",\"Shadow; 3\",\"Blaze; 4\",\"Seacove; 5\",\"Arrow; 5\",\"Dark Knight; 6\"],\"type\":\"array\",\"items\":{\"type\":\"string\"}}}}",
      "uiSchema": "{}",
      "commands": [
        {
          "name": "horses",
          "trigger": "horses",
          "helpText": "No help text available",
          "function": "import { data, TakaroUserError } from '@takaro/helpers';\nimport { parseHorses, getRaceData, getTimeUntilRace } from './utils.js';\n\nasync function main() {\n    try {\n        const { player, module: mod, gameServerId } = data;\n\n        // Parse horses using the utility function\n        const horses = parseHorses(mod.userConfig);\n\n        if (horses.length === 0) {\n            throw new TakaroUserError('No horses are configured for racing!');\n        }\n\n        // Get current race info\n        const raceData = await getRaceData(gameServerId, mod.moduleId);\n        const timeUntil = getTimeUntilRace(raceData.nextRaceTime);\n\n        await player.pm('🏇 HORSE RACING INFORMATION 🏇');\n        await player.pm('═══════════════════════════════════');\n        await player.pm(`🏁 Next Race: #${raceData.raceNumber} in ${timeUntil}`);\n        await player.pm(`🎫 Current Bets: ${raceData.bets.length}`);\n        await player.pm('🐎 AVAILABLE HORSES:');\n\n        // Show horses with enhanced info\n        for (let i = 0; i < horses.length; i++) {\n            const horse = horses[i];\n            const betsOnHorse = raceData.bets.filter(bet => \n                bet.horse.toLowerCase() === horse.name.toLowerCase()).length;\n            \n            let horseLine = `  ${i + 1}. ${horse.name} - ${horse.odds}:1 odds`;\n            if (betsOnHorse > 0) {\n                horseLine += ` (${betsOnHorse} bet${betsOnHorse !== 1 ? 's' : ''})`;\n            }\n            \n            // Add performance indicator\n            if (horse.odds <= 2) {\n                horseLine += ' ⭐ Favorite';\n            } else if (horse.odds >= 6) {\n                horseLine += ' 🎯 Longshot';\n            }\n            \n            await player.pm(horseLine);\n        }\n\n        const minBet = mod.userConfig?.minBet || 50;\n        const maxBet = mod.userConfig?.maxBet || 1000;\n\n        await player.pm('📋 BETTING INFORMATION:');\n        await player.pm(`💰 Bet Range: ${minBet} - ${maxBet} currency`);\n        await player.pm('🎯 Command: /horsebet <horse> <amount>');\n        await player.pm('📊 Example: /horsebet Thunder 100');\n\n        // Show current player's bets if any\n        const playerBets = raceData.bets.filter(bet => bet.playerId === player.id);\n        if (playerBets.length > 0) {\n            await player.pm('🎫 YOUR CURRENT BETS:');\n            for (const bet of playerBets) {\n                const potentialWin = Math.floor(bet.amount * bet.odds);\n                await player.pm(`  ${bet.horse}: ${bet.amount} → potential win: ${potentialWin}`);\n            }\n        }\n\n        // Show helpful tips\n        await player.pm('💡 TIP: Lower odds = higher chance to win, but lower payout');\n        await player.pm('🎰 Special jackpot races trigger randomly for extra prizes!');\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in horses command:', error);\n        throw new TakaroUserError('Unable to load horse information. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "horseBet",
          "trigger": "horsebet",
          "helpText": "Name of the horse you want to bet on",
          "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nimport { parseHorses, getRaceData } from './utils.js';\n\nasync function main() {\n    const { player, gameServerId, module: mod, pog, arguments: args } = data;\n\n    // Check permission\n    if (!checkPermission(pog, 'HORSE_RACING_BET')) {\n        throw new TakaroUserError('You do not have permission to place bets.');\n    }\n\n    // Validate arguments\n    if (!args.horse) {\n        throw new TakaroUserError('Please specify the horse name you want to bet on.');\n    }\n\n    const betAmount = parseInt(args.amount);\n    const minBet = mod.userConfig?.minBet || 50;\n    const maxBet = mod.userConfig?.maxBet || 1000;\n\n    if (!betAmount || betAmount < minBet || betAmount > maxBet) {\n        throw new TakaroUserError(`Please specify a valid amount to bet (min: ${minBet}, max: ${maxBet}).`);\n    }\n\n    try {\n        // Get horse list using utility function\n        const horses = parseHorses(mod.userConfig);\n\n        // Find the horse\n        const horseName = args.horse.toLowerCase().trim();\n        const horseMatch = horses.find(h => h.name.toLowerCase() === horseName);\n\n        if (!horseMatch) {\n            const availableHorses = horses.map(h => h.name).join(', ');\n            throw new TakaroUserError(`Horse \"${args.horse}\" not found. Available horses: ${availableHorses}`);\n        }\n\n        // Check if player has enough currency\n        const playerData = await takaro.playerOnGameserver.playerOnGameServerControllerGetOne(gameServerId, player.id);\n        const balance = playerData.data.data.currency;\n\n        if (balance < betAmount) {\n            throw new TakaroUserError(`You don't have enough currency. Your balance: ${balance}`);\n        }\n\n        // Get race data using utility function\n        const raceData = await getRaceData(gameServerId, mod.moduleId);\n\n        // Check if player already has a bet\n        const existingBetIndex = raceData.bets.findIndex(bet => bet.playerId === player.id);\n\n        if (existingBetIndex >= 0) {\n            // Check if it's on the same horse\n            if (raceData.bets[existingBetIndex].horse.toLowerCase() === horseMatch.name.toLowerCase()) {\n                throw new TakaroUserError(`You already have a bet on ${horseMatch.name}. Use /myhorsebets to see your bets.`);\n            }\n\n            // Refund previous bet\n            const oldBet = raceData.bets[existingBetIndex];\n            await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(\n                gameServerId,\n                player.id,\n                { currency: oldBet.amount }\n            );\n\n            // Remove from array\n            raceData.bets.splice(existingBetIndex, 1);\n            await player.pm(`Refunded your previous bet of ${oldBet.amount} on ${oldBet.horse}`);\n        }\n\n        // Deduct currency from player\n        await takaro.playerOnGameserver.playerOnGameServerControllerDeductCurrency(\n            gameServerId,\n            player.id,\n            { currency: betAmount }\n        );\n\n        // Create new bet\n        raceData.bets.push({\n            playerId: player.id,\n            playerName: player.name,\n            horse: horseMatch.name,\n            amount: betAmount,\n            odds: horseMatch.odds,\n            placedAt: Date.now()\n        });\n\n        // Update race data\n        const currentRace = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['current_race'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n            },\n        });\n\n        await takaro.variable.variableControllerUpdate(currentRace.data.data[0].id, {\n            value: JSON.stringify(raceData),\n        });\n\n        // Calculate potential winnings\n        const potentialWin = Math.floor(betAmount * horseMatch.odds);\n        \n        await player.pm(`✅ Bet placed: ${betAmount} on ${horseMatch.name} (${horseMatch.odds}:1 odds)`);\n        await player.pm(`💰 Potential winnings: ${potentialWin}`);\n\n        // Show time until race\n        const timeUntilRace = Math.max(0, raceData.nextRaceTime - Date.now());\n        if (timeUntilRace > 0) {\n            const minutesUntilRace = Math.floor(timeUntilRace / 60000);\n            if (minutesUntilRace > 0) {\n                await player.pm(`⏰ Next race (#${raceData.raceNumber}) in approximately ${minutesUntilRace} minutes`);\n            } else {\n                await player.pm(`⏰ Next race (#${raceData.raceNumber}) starting soon!`);\n            }\n        }\n\n        // Show total bets for this race\n        await player.pm(`📊 Total bets for this race: ${raceData.bets.length}`);\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in horsebet command:', error);\n        throw new TakaroUserError('Something went wrong placing your bet. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": [
            {
              "name": "horse",
              "type": "string",
              "helpText": "Name of the horse you want to bet on",
              "defaultValue": "",
              "position": 0
            },
            {
              "name": "amount",
              "type": "string",
              "helpText": "Amount of currency to bet",
              "defaultValue": "",
              "position": 1
            }
          ]
        },
        {
          "name": "mybets",
          "trigger": "myhorsebets",
          "helpText": "No help text available",
          "function": "import { data, TakaroUserError } from '@takaro/helpers';\nimport { getRaceData } from './utils.js';\n\nasync function main() {\n    try {\n        const { player, module: mod, gameServerId } = data;\n\n        const raceData = await getRaceData(gameServerId, mod.moduleId);\n\n        // Check if player has bets\n        const playerBets = raceData.bets.filter(bet => bet.playerId === player.id);\n\n        if (playerBets.length === 0) {\n            await player.pm('You have not placed any bets for the upcoming race.');\n            await player.pm('Use /horsebet <horse> <amount> to place a bet!');\n            return;\n        }\n\n        await player.pm(`🏇 Your bets for Race #${raceData.raceNumber}:`);\n\n        let totalPotential = 0;\n        for (const bet of playerBets) {\n            const potential = Math.floor(bet.amount * bet.odds);\n            totalPotential += potential;\n            await player.pm(`${bet.horse} - ${bet.amount} (potential win: ${potential})`);\n        }\n\n        await player.pm(`Total potential winnings: ${totalPotential}`);\n    } catch (error) {\n        console.log('Error in myBets command:', error);\n        throw new TakaroUserError('Something went wrong. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "startrace",
          "trigger": "startrace",
          "helpText": "Immediately starts a horse race with current bets",
          "function": "import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';\nimport { parseHorses, simulateRace } from './utils.js';\n\nasync function main() {\n    const { gameServerId, module: mod, player, pog } = data;\n\n    // Check admin permission\n    if (!checkPermission(pog, 'HORSE_RACING_ADMIN')) {\n        throw new TakaroUserError('You need admin permissions to manually start races.');\n    }\n\n    try {\n        // Get race data\n        const currentRace = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['current_race'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n            },\n        });\n\n        let raceData;\n        if (currentRace.data.data.length === 0) {\n            // Initialize race data if it doesn't exist\n            raceData = {\n                nextRaceTime: Date.now() + 3600000,\n                bets: [],\n                lastRaceResults: null,\n                raceNumber: 1,\n                state: 'waiting'\n            };\n\n            await takaro.variable.variableControllerCreate({\n                key: 'current_race',\n                value: JSON.stringify(raceData),\n                gameServerId,\n                moduleId: mod.moduleId,\n            });\n        } else {\n            raceData = JSON.parse(currentRace.data.data[0].value);\n        }\n\n        // Check if no bets\n        if (!raceData.bets || raceData.bets.length === 0) {\n            throw new TakaroUserError('Cannot start race - no bets have been placed!');\n        }\n\n        // Parse horses and simulate race\n        const horses = parseHorses(mod.userConfig);\n        const raceResults = simulateRace(horses);\n\n        // Store race results\n        raceData.results = raceResults;\n        raceData.state = 'complete';\n\n        // Get winner\n        const winningHorse = raceResults[0].name;\n        const winningBets = raceData.bets.filter(bet => \n            bet.horse.toLowerCase() === winningHorse.toLowerCase());\n\n        // Announce race and results immediately\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🏇 MANUAL RACE #${raceData.raceNumber} - The horses are off!`\n        });\n\n        // Small delay for drama\n        await new Promise(resolve => setTimeout(resolve, 3000));\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🏆 ${winningHorse} WINS Race #${raceData.raceNumber}!`\n        });\n\n        // Process winnings\n        let totalPayout = 0;\n        if (winningBets.length > 0) {\n            for (const bet of winningBets) {\n                const winnings = Math.floor(bet.amount * bet.odds);\n                totalPayout += winnings;\n\n                try {\n                    await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(\n                        gameServerId,\n                        bet.playerId,\n                        { currency: winnings }\n                    );\n                } catch (error) {\n                    console.log(`Error processing win for player ${bet.playerName}:`, error);\n                }\n            }\n\n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: `💰 ${winningBets.length} winner${winningBets.length !== 1 ? 's' : ''} received ${totalPayout} total currency!`\n            });\n        } else {\n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: \"💸 No one bet on the winning horse. House wins!\"\n            });\n        }\n\n        // Save race results for history\n        raceData.lastRaceResults = {\n            raceNumber: raceData.raceNumber,\n            results: raceResults,\n            winners: winningBets,\n            totalPayout: totalPayout,\n            timestamp: Date.now()\n        };\n\n        // Setup next race\n        raceData.raceNumber++;\n        raceData.nextRaceTime = Date.now() + (2 * 60 * 60 * 1000);\n        raceData.bets = [];\n        raceData.state = 'waiting';\n\n        // Update race data\n        if (currentRace.data.data.length === 0) {\n            await takaro.variable.variableControllerCreate({\n                key: 'current_race',\n                value: JSON.stringify(raceData),\n                gameServerId,\n                moduleId: mod.moduleId,\n            });\n        } else {\n            await takaro.variable.variableControllerUpdate(currentRace.data.data[0].id, {\n                value: JSON.stringify(raceData),\n            });\n        }\n\n        await player.pm(`Race #${raceData.raceNumber - 1} completed successfully. Next race scheduled for 2 hours from now.`);\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in manual startrace:', error);\n        throw new TakaroUserError('Failed to start race. Check logs for details.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "horseLeaderboard",
          "trigger": "horseleaderboard",
          "helpText": "View top bettors by winnings and win rate",
          "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\n\nasync function main() {\n    const { player, gameServerId, module: mod } = data;\n\n    try {\n        // Get all player statistics\n        const statsSearch = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['horse_racing_stats'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n            },\n        });\n\n        if (statsSearch.data.data.length === 0) {\n            throw new TakaroUserError('No betting statistics available yet. Place some bets and race to build up the leaderboard!');\n        }\n\n        // Parse all player stats\n        const allStats = [];\n        for (const statVar of statsSearch.data.data) {\n            try {\n                const stats = JSON.parse(statVar.value);\n                const playerInfo = await takaro.playerOnGameserver.playerOnGameServerControllerGetOne(gameServerId, statVar.playerId);\n                \n                allStats.push({\n                    playerId: statVar.playerId,\n                    playerName: playerInfo.data.data.player.name,\n                    totalWinnings: stats.totalWinnings || 0,\n                    totalBets: stats.totalBets || 0,\n                    totalWagered: stats.totalWagered || 0,\n                    wins: stats.wins || 0,\n                    losses: stats.losses || 0,\n                    biggestWin: stats.biggestWin || 0,\n                    favoriteHorse: stats.favoriteHorse || 'None'\n                });\n            } catch (error) {\n                console.log('Error parsing player stats:', error);\n                continue;\n            }\n        }\n\n        if (allStats.length === 0) {\n            throw new TakaroUserError('No valid betting statistics found.');\n        }\n\n        // Sort by total winnings (descending)\n        allStats.sort((a, b) => b.totalWinnings - a.totalWinnings);\n\n        await player.pm('🏆 HORSE RACING LEADERBOARD 🏆');\n        await player.pm('═══════════════════════════════');\n\n        // Show top 10\n        const topPlayers = allStats.slice(0, 10);\n        for (let i = 0; i < topPlayers.length; i++) {\n            const p = topPlayers[i];\n            const winRate = p.totalBets > 0 ? Math.round((p.wins / p.totalBets) * 100) : 0;\n            const roi = p.totalWagered > 0 ? Math.round(((p.totalWinnings - p.totalWagered) / p.totalWagered) * 100) : 0;\n            \n            await player.pm(`${i + 1}. ${p.playerName}`);\n            await player.pm(`   💰 Net: ${p.totalWinnings - p.totalWagered} | Wins: ${p.wins}/${p.totalBets} (${winRate}%)`);\n            if (i < 3) { // Show extra details for top 3\n                await player.pm(`   🎯 ROI: ${roi}% | Biggest Win: ${p.biggestWin} | Fav: ${p.favoriteHorse}`);\n            }\n        }\n\n        // Show current player's position if not in top 10\n        const playerStats = allStats.find(s => s.playerId === player.id);\n        if (playerStats) {\n            const playerRank = allStats.findIndex(s => s.playerId === player.id) + 1;\n            if (playerRank > 10) {\n                const winRate = playerStats.totalBets > 0 ? Math.round((playerStats.wins / playerStats.totalBets) * 100) : 0;\n                await player.pm(`Your rank: #${playerRank}`);\n                await player.pm(`Your stats: ${playerStats.wins}/${playerStats.totalBets} wins (${winRate}%) | Net: ${playerStats.totalWinnings - playerStats.totalWagered}`);\n            }\n        } else {\n            await player.pm('You haven\\'t placed any bets yet! Use /horsebet to get started.');\n        }\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in horse leaderboard:', error);\n        throw new TakaroUserError('Failed to load leaderboard. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "nextRace",
          "trigger": "nextrace",
          "helpText": "No help text available",
          "function": "import { data, TakaroUserError } from '@takaro/helpers';\nimport { getRaceData, getTimeUntilRace } from './utils.js';\n\nasync function main() {\n    try {\n        const { player, module: mod, gameServerId } = data;\n\n        const raceData = await getRaceData(gameServerId, mod.moduleId);\n        const timeUntil = getTimeUntilRace(raceData.nextRaceTime);\n\n        await player.pm(`🏇 Race #${raceData.raceNumber} will begin in ${timeUntil}.`);\n        await player.pm(`${raceData.bets.length} bet${raceData.bets.length !== 1 ? 's' : ''} have been placed so far.`);\n\n        // Check if player has bets\n        const playerBets = raceData.bets.filter(bet => bet.playerId === player.id);\n        if (playerBets.length > 0) {\n            await player.pm('Your bets:');\n            for (const bet of playerBets) {\n                await player.pm(`${bet.horse} - ${bet.amount} (potential win: ${Math.floor(bet.amount * bet.odds)})`);\n            }\n        } else {\n            await player.pm('You have not placed any bets yet. Use /horsebet <horse> <amount> to place a bet!');\n        }\n    } catch (error) {\n        console.log('Error in nextRace command:', error);\n        throw new TakaroUserError('Something went wrong. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "lastRace",
          "trigger": "lastRace",
          "helpText": "No help text available",
          "function": "import { data, TakaroUserError } from '@takaro/helpers';\nimport { getRaceData } from './utils.js';\n\nasync function main() {\n    try {\n        const { player, module: mod, gameServerId } = data;\n\n        const raceData = await getRaceData(gameServerId, mod.moduleId);\n\n        if (!raceData.lastRaceResults) {\n            throw new TakaroUserError('No previous race results found. Wait for a race to finish!');\n        }\n\n        const results = raceData.lastRaceResults;\n        const raceDate = new Date(results.timestamp).toLocaleString();\n\n        await player.pm(`🏇 RACE #${results.raceNumber} RESULTS`);\n        await player.pm('═══════════════════════════════');\n        await player.pm(`📅 Completed: ${raceDate}`);\n\n        // Show top 5 finishing positions\n        const topHorses = results.results.slice(0, Math.min(5, results.results.length));\n        await player.pm('🏁 FINAL STANDINGS:');\n        for (let i = 0; i < topHorses.length; i++) {\n            const position = i + 1;\n            const medal = position === 1 ? '🥇' : position === 2 ? '🥈' : position === 3 ? '🥉' : `${position}.`;\n            await player.pm(`  ${medal} ${topHorses[i].name}`);\n        }\n\n        // Show payout information\n        if (results.winners.length > 0) {\n            await player.pm(`💰 PAYOUTS: ${results.winners.length} winner${results.winners.length !== 1 ? 's' : ''} - ${results.totalPayout} total currency paid out`);\n            \n            // Show jackpot if there was one\n            if (results.jackpot && results.jackpot > 0) {\n                await player.pm(`🎰 Jackpot bonus: ${results.jackpot} currency!`);\n            }\n\n            // Check if current player won\n            const playerWin = results.winners.find(bet => bet.playerId === player.id);\n            if (playerWin) {\n                let winnings = Math.floor(playerWin.amount * playerWin.odds);\n                if (results.jackpot) {\n                    winnings += Math.floor(results.jackpot / results.winners.length);\n                }\n                await player.pm(`🎉 YOU WON ${winnings} with your ${playerWin.amount} bet on ${playerWin.horse}!`);\n            } else {\n                // Check if player had any losing bets\n                const playerBets = results.winners.filter(bet => bet.playerId === player.id);\n                if (playerBets.length === 0) {\n                    await player.pm('🤷‍♂️ You didn\\'t place any bets in this race.');\n                } else {\n                    await player.pm('😔 Your horse didn\\'t win this time. Better luck next race!');\n                }\n            }\n        } else {\n            await player.pm('💸 No one bet on the winning horse - house wins!');\n        }\n\n        // Show race statistics\n        const totalBets = results.winners.length;\n        await player.pm(`📊 Race Stats: ${totalBets} total bet${totalBets !== 1 ? 's' : ''} placed`);\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in lastRace command:', error);\n        throw new TakaroUserError('Unable to retrieve race results. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        },
        {
          "name": "horseStats",
          "trigger": "horsestats",
          "helpText": "Shows your betting history, win rate, and favorite horses",
          "function": "import { takaro, data, TakaroUserError } from '@takaro/helpers';\n\nasync function main() {\n    const { player, gameServerId, module: mod } = data;\n\n    try {\n        // Get player statistics\n        const statsSearch = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['horse_racing_stats'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n                playerId: [player.id],\n            },\n        });\n\n        if (statsSearch.data.data.length === 0) {\n            throw new TakaroUserError('You haven\\'t placed any bets yet! Use /horsebet <horse> <amount> to get started.');\n        }\n\n        const stats = JSON.parse(statsSearch.data.data[0].value);\n        \n        // Calculate derived stats\n        const winRate = stats.totalBets > 0 ? Math.round((stats.wins / stats.totalBets) * 100) : 0;\n        const netProfit = stats.totalWinnings - stats.totalWagered;\n        const roi = stats.totalWagered > 0 ? Math.round((netProfit / stats.totalWagered) * 100) : 0;\n\n        await player.pm('📊 YOUR HORSE RACING STATISTICS 📊');\n        await player.pm('═══════════════════════════════════');\n        await player.pm(`🎯 Win Rate: ${stats.wins}/${stats.totalBets} (${winRate}%)`);\n        await player.pm(`💰 Net Profit: ${netProfit}`);\n        await player.pm(`📈 ROI: ${roi}%`);\n        await player.pm(`🏆 Biggest Win: ${stats.biggestWin}`);\n        await player.pm(`💎 Total Wagered: ${stats.totalWagered}`);\n        await player.pm(`🐎 Favorite Horse: ${stats.favoriteHorse}`);\n\n        // Show per-horse breakdown if available\n        if (stats.horseStats && Object.keys(stats.horseStats).length > 0) {\n            await player.pm('🐎 PER-HORSE BREAKDOWN:');\n            \n            // Sort horses by most bet on\n            const horseEntries = Object.entries(stats.horseStats)\n                .sort(([,a], [,b]) => b.bets - a.bets)\n                .slice(0, 5); // Show top 5\n\n            for (const [horseName, horseStats] of horseEntries) {\n                const horseWinRate = horseStats.bets > 0 ? Math.round((horseStats.wins / horseStats.bets) * 100) : 0;\n                await player.pm(`  ${horseName}: ${horseStats.wins}/${horseStats.bets} wins (${horseWinRate}%) - ${horseStats.totalWagered} wagered`);\n            }\n        }\n\n        // Performance category\n        let category = '🔰 Novice Bettor';\n        if (stats.totalBets >= 50 && winRate >= 30) {\n            category = '🥇 Professional Gambler';\n        } else if (stats.totalBets >= 20 && winRate >= 25) {\n            category = '🥈 Experienced Bettor';\n        } else if (stats.totalBets >= 10) {\n            category = '🥉 Regular Bettor';\n        }\n        \n        await player.pm(`🏷️  Status: ${category}`);\n\n        // Give tips based on performance\n        if (winRate < 20 && stats.totalBets > 5) {\n            await player.pm('💡 Tip: Try betting on horses with lower odds for better chances!');\n        } else if (roi > 50) {\n            await player.pm('🎉 Outstanding performance! You\\'re a horse racing champion!');\n        }\n\n    } catch (error) {\n        if (error instanceof TakaroUserError) {\n            throw error;\n        }\n        console.log('Error in horseStats command:', error);\n        throw new TakaroUserError('Failed to load your statistics. Please try again.');\n    }\n}\n\nawait main();",
          "arguments": []
        }
      ],
      "hooks": [
        {
          "name": "test",
          "eventType": "log",
          "description": "Hook for log events",
          "regex": "takaro-hook-regex-placeholder",
          "function": "import { data, takaro } from '@takaro/helpers';\nasync function main() {\n    const {} = data;\n}\nawait main();"
        }
      ],
      "cronJobs": [
        {
          "name": "announceRace",
          "temporalValue": "0 0 * * *",
          "description": "",
          "function": "import { takaro, data } from '@takaro/helpers';\n\nasync function main() {\n    try {\n        const { gameServerId, module: mod } = data;\n\n        // Get online players\n        const onlinePlayers = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({\n            filters: {\n                gameServerId: [gameServerId],\n                online: [true]\n            }\n        });\n\n        // Skip if no one is online\n        if (onlinePlayers.data.meta.total === 0) {\n            return true;\n        }\n\n        // Get race data\n        const currentRace = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['current_race'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n            },\n        });\n\n        let raceData;\n        if (currentRace.data.data.length === 0) {\n            // Initialize race data if it doesn't exist\n            raceData = {\n                nextRaceTime: Date.now() + 3600000, // 1 hour from now\n                bets: [],\n                lastRaceResults: null,\n                raceNumber: 1,\n                state: 'waiting'\n            };\n\n            await takaro.variable.variableControllerCreate({\n                key: 'current_race',\n                value: JSON.stringify(raceData),\n                gameServerId,\n                moduleId: mod.moduleId,\n            });\n        } else {\n            raceData = JSON.parse(currentRace.data.data[0].value);\n        }\n\n        // Get horse list\n        let horses = [];\n        if (mod.userConfig?.Horses && Array.isArray(mod.userConfig.Horses)) {\n            horses = mod.userConfig.Horses.map(horseStr => {\n                const [name, oddsStr] = horseStr.split(';').map(s => s.trim());\n                return `${name} (${oddsStr}x)`;\n            });\n        } else {\n            horses = [\n                \"Thunder (2x)\",\n                \"Lightning (3x)\",\n                \"Shadow (3x)\",\n                \"Blaze (4x)\",\n                \"Seacove (5x)\",\n                \"Arrow (5x)\",\n                \"Dark Knight (6x)\"\n            ];\n        }\n\n        // Announce upcoming race\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🏇 Attention! Horse Race #${raceData.raceNumber} will begin in 5 minutes!`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `Available horses: ${horses.join(', ')}`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `Place your bets with /horsebet <horse> <amount> (min: 50, max: 1000)`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `${raceData.bets.length} bet${raceData.bets.length !== 1 ? 's' : ''} placed so far!`\n        });\n\n        return true;\n    } catch (error) {\n        console.log('Error in announceRace cronjob:', error);\n        return true;\n    }\n}\n\nawait main();"
        },
        {
          "name": "runRace",
          "temporalValue": "0 0 * * *",
          "description": "",
          "function": "import { takaro, data } from '@takaro/helpers';\nimport { parseHorses, simulateRace, getRaceCommentary, updatePlayerStats, checkAndCreateJackpot } from './utils.js';\n\nasync function main() {\n    try {\n        const { gameServerId, module: mod } = data;\n\n        // Get online players\n        const onlinePlayers = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({\n            filters: {\n                gameServerId: [gameServerId],\n                online: [true]\n            }\n        });\n\n        // Skip race if no one is online\n        if (onlinePlayers.data.meta.total === 0) {\n            return true;\n        }\n\n        // Get race data\n        const currentRace = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['current_race'],\n                gameServerId: [gameServerId],\n                moduleId: [mod.moduleId],\n            },\n        });\n\n        let raceData;\n        if (currentRace.data.data.length === 0) {\n            // Initialize race data if it doesn't exist\n            raceData = {\n                nextRaceTime: Date.now() + 3600000, // 1 hour from now\n                bets: [],\n                lastRaceResults: null,\n                raceNumber: 1,\n                state: 'waiting'\n            };\n\n            await takaro.variable.variableControllerCreate({\n                key: 'current_race',\n                value: JSON.stringify(raceData),\n                gameServerId,\n                moduleId: mod.moduleId,\n            });\n        } else {\n            raceData = JSON.parse(currentRace.data.data[0].value);\n        }\n\n        // If no bets, just announce and set next race\n        if (!raceData.bets || raceData.bets.length === 0) {\n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: \"🏇 The race track is quiet... No bets have been placed! Next race in 2 hours.\"\n            });\n\n            raceData.nextRaceTime = Date.now() + (2 * 60 * 60 * 1000);\n            \n            await takaro.variable.variableControllerUpdate(currentRace.data.data[0].id, {\n                value: JSON.stringify(raceData),\n            });\n\n            return true;\n        }\n\n        // Check for jackpot\n        const totalBetsAmount = raceData.bets.reduce((sum, bet) => sum + bet.amount, 0);\n        const jackpotInfo = await checkAndCreateJackpot(gameServerId, mod.moduleId, totalBetsAmount);\n\n        // Parse horses and simulate race\n        const horses = parseHorses(mod.userConfig);\n        const raceResults = simulateRace(horses);\n\n        // Get winner\n        const winningHorse = raceResults[0].name;\n        const winningBets = raceData.bets.filter(bet => \n            bet.horse.toLowerCase() === winningHorse.toLowerCase());\n\n        // RACE PROGRESSION SEQUENCE - No setTimeout, just progressive messages\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🏁 RACE #${raceData.raceNumber} IS STARTING! 🏁`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: getRaceCommentary('start', horses, raceResults)\n        });\n\n        if (jackpotInfo.isJackpot) {\n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: `🎰 JACKPOT RACE! Winner gets an extra ${jackpotInfo.amount} currency!`\n            });\n        }\n\n        // Show race positions as it progresses\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🐎 Early positions: ${raceResults[0].name} leads, followed by ${raceResults[1].name} and ${raceResults[2].name}!`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: getRaceCommentary('midRace', horses, raceResults)\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `⚡ Final stretch! ${raceResults[0].name} is pulling ahead, ${raceResults[1].name} charging hard behind!`\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: getRaceCommentary('finish', horses, raceResults)\n        });\n\n        // Show final standings\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: `🏆 FINAL RESULTS: 1st: ${raceResults[0].name} 🥇 | 2nd: ${raceResults[1].name} 🥈 | 3rd: ${raceResults[2].name} 🥉`\n        });\n\n        // Process winnings and update stats\n        let totalPayout = 0;\n        if (winningBets.length > 0) {\n            for (const bet of winningBets) {\n                let winnings = Math.floor(bet.amount * bet.odds);\n                \n                // Add jackpot bonus\n                if (jackpotInfo.isJackpot) {\n                    winnings += Math.floor(jackpotInfo.amount / winningBets.length);\n                }\n                \n                totalPayout += winnings;\n\n                try {\n                    await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(\n                        gameServerId,\n                        bet.playerId,\n                        { currency: winnings }\n                    );\n\n                    // Update player statistics\n                    await updatePlayerStats(gameServerId, mod.moduleId, bet.playerId, bet, true, winnings);\n\n                    // Notify winner if online\n                    const isOnline = onlinePlayers.data.data.some(p => p.playerId === bet.playerId);\n                    if (isOnline) {\n                        let winMessage = `🎉 Congratulations! ${winningHorse} won! You received ${winnings} currency!`;\n                        if (jackpotInfo.isJackpot) {\n                            winMessage += ` (Including jackpot bonus!)`;\n                        }\n                        \n                        await takaro.player.playerControllerSendMessage(bet.playerId, {\n                            message: winMessage\n                        });\n                    }\n                } catch (error) {\n                    console.log(`Error processing win for player ${bet.playerName}:`, error);\n                }\n            }\n\n            let payoutMessage = `💰 WINNERS: ${winningBets.length} lucky bettor${winningBets.length !== 1 ? 's' : ''} won ${totalPayout} total currency!`;\n            if (jackpotInfo.isJackpot) {\n                payoutMessage += ` 🎰`;\n            }\n            \n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: payoutMessage\n            });\n\n            // Show who won what\n            const winnerNames = winningBets.map(bet => bet.playerName).slice(0, 3);\n            if (winnerNames.length > 0) {\n                await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                    message: `🎊 Winners: ${winnerNames.join(', ')} bet on the winning horse ${winningHorse}!`\n                });\n            }\n        } else {\n            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n                message: `💸 Nobody bet on ${winningHorse}! The house wins this round!`\n            });\n        }\n\n        // Update stats for losing bets\n        for (const bet of raceData.bets) {\n            const isWinner = winningBets.some(wb => wb.playerId === bet.playerId);\n            if (!isWinner) {\n                await updatePlayerStats(gameServerId, mod.moduleId, bet.playerId, bet, false, 0);\n            }\n        }\n\n        // Clear jackpot if used\n        if (jackpotInfo.isJackpot) {\n            const jackpotSearch = await takaro.variable.variableControllerSearch({\n                filters: {\n                    key: ['current_jackpot'],\n                    gameServerId: [gameServerId],\n                    moduleId: [mod.moduleId],\n                },\n            });\n\n            if (jackpotSearch.data.data.length > 0) {\n                await takaro.variable.variableControllerDelete(jackpotSearch.data.data[0].id);\n            }\n        }\n\n        // Save race results for history\n        raceData.lastRaceResults = {\n            raceNumber: raceData.raceNumber,\n            results: raceResults,\n            winners: winningBets,\n            totalPayout: totalPayout,\n            jackpot: jackpotInfo.isJackpot ? jackpotInfo.amount : 0,\n            timestamp: Date.now()\n        };\n\n        // Setup next race\n        raceData.raceNumber++;\n        raceData.nextRaceTime = Date.now() + (2 * 60 * 60 * 1000);\n        raceData.bets = [];\n        raceData.state = 'waiting';\n\n        // Update race data\n        await takaro.variable.variableControllerUpdate(currentRace.data.data[0].id, {\n            value: JSON.stringify(raceData),\n        });\n\n        await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {\n            message: \"🗓️ Next race in 2 hours! Use /horsebet <horse> <amount> to place your bets!\"\n        });\n\n        return true;\n    } catch (error) {\n        console.log('Error in runRace cronjob:', error);\n        return true;\n    }\n}\n\nawait main();"
        }
      ],
      "functions": [
        {
          "name": "utils",
          "description": "",
          "function": "// utils.js\nimport { takaro } from '@takaro/helpers';\n\n// Helper to find a horse by name\nexport function findHorse(horses, horseName) {\n    return horses.find(h => h.name.toLowerCase() === horseName.toLowerCase());\n}\n\n// Parse horses from config - improved with better error handling\nexport function parseHorses(userConfig) {\n    try {\n        let horses = [];\n\n        if (userConfig?.Horses && Array.isArray(userConfig.Horses)) {\n            horses = userConfig.Horses.map(horseStr => {\n                if (typeof horseStr !== 'string') {\n                    return {\n                        name: String(horseStr),\n                        odds: 2\n                    };\n                }\n\n                const parts = horseStr.split(';');\n                if (parts.length >= 2) {\n                    const name = parts[0].trim();\n                    const oddsStr = parts[1].trim();\n                    const odds = parseInt(oddsStr, 10);\n                    return {\n                        name: name,\n                        odds: isNaN(odds) ? 2 : odds\n                    };\n                } else {\n                    return {\n                        name: horseStr.trim(),\n                        odds: 2\n                    };\n                }\n            });\n        } else {\n            // Fall back to default horses\n            horses = [\n                { name: \"Thunder\", odds: 2 },\n                { name: \"Lightning\", odds: 3 },\n                { name: \"Shadow\", odds: 3 },\n                { name: \"Blaze\", odds: 4 }\n            ];\n        }\n\n        // Filter out any invalid horses\n        horses = horses.filter(h => h && h.name);\n\n        return horses;\n    } catch (error) {\n        // Return default horses on error\n        return [\n            { name: \"Thunder\", odds: 2 },\n            { name: \"Lightning\", odds: 3 },\n            { name: \"Shadow\", odds: 3 },\n            { name: \"Blaze\", odds: 4 }\n        ];\n    }\n}\n\n// Helper function to manage race data\nexport async function getRaceData(gameServerId, moduleId) {\n    const currentRace = await takaro.variable.variableControllerSearch({\n        filters: {\n            key: ['current_race'],\n            gameServerId: [gameServerId],\n            moduleId: [moduleId],\n        },\n    });\n\n    if (currentRace.data.data.length === 0) {\n        // Initialize race data if it doesn't exist\n        const initialRace = {\n            nextRaceTime: Date.now() + 3600000, // 1 hour from now\n            bets: [],\n            lastRaceResults: null,\n            raceNumber: 1\n        };\n\n        await takaro.variable.variableControllerCreate({\n            key: 'current_race',\n            value: JSON.stringify(initialRace),\n            gameServerId,\n            moduleId,\n        });\n\n        return initialRace;\n    }\n\n    // Safely parse JSON with fallback\n    try {\n        return JSON.parse(currentRace.data.data[0].value);\n    } catch (e) {\n        console.log('Error parsing race data:', e);\n        // Return a new race if parsing fails\n        return {\n            nextRaceTime: Date.now() + 3600000,\n            bets: [],\n            lastRaceResults: null,\n            raceNumber: 1\n        };\n    }\n}\n\n// Update race data\nexport async function updateRaceData(gameServerId, moduleId, raceData) {\n    try {\n        const currentRace = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['current_race'],\n                gameServerId: [gameServerId],\n                moduleId: [moduleId],\n            },\n        });\n\n        if (currentRace.data.data.length === 0) {\n            // Create if it doesn't exist\n            await takaro.variable.variableControllerCreate({\n                key: 'current_race',\n                value: JSON.stringify(raceData),\n                gameServerId,\n                moduleId,\n            });\n        } else {\n            // Update existing\n            await takaro.variable.variableControllerUpdate(currentRace.data.data[0].id, {\n                value: JSON.stringify(raceData),\n            });\n        }\n    } catch (error) {\n        console.log('Error updating race data:', error);\n    }\n}\n\n// Helper to get the next race time in a human-readable format\nexport function getTimeUntilRace(nextRaceTime) {\n    const timeRemaining = nextRaceTime - Date.now();\n\n    if (timeRemaining <= 0) {\n        return \"any moment now\";\n    }\n\n    const minutes = Math.floor(timeRemaining / 60000);\n    if (minutes < 60) {\n        return `${minutes} minute${minutes !== 1 ? 's' : ''}`;\n    }\n\n    const hours = Math.floor(minutes / 60);\n    const remainingMinutes = minutes % 60;\n    return `${hours} hour${hours !== 1 ? 's' : ''} and ${remainingMinutes} minute${remainingMinutes !== 1 ? 's' : ''}`;\n}\n\n// Simulate race with weighted probabilities based on odds\nexport function simulateRace(horses) {\n    if (!horses || !Array.isArray(horses) || horses.length === 0) {\n        console.log('Invalid horses data for simulation, using defaults');\n        horses = [\n            { name: \"Thunder\", odds: 2 },\n            { name: \"Lightning\", odds: 3 },\n            { name: \"Shadow\", odds: 3 },\n            { name: \"Blaze\", odds: 4 }\n        ];\n    }\n\n    // Convert odds to weights (lower odds = higher chance to win)\n    const totalWeight = horses.reduce((sum, horse) => sum + (1 / horse.odds), 0);\n\n    // Create weighted array\n    const weightedHorses = [];\n    for (const horse of horses) {\n        // Calculate weight - inverse of odds, normalized\n        const weight = (1 / horse.odds) / totalWeight;\n        weightedHorses.push({\n            name: horse.name,\n            weight,\n            position: 0,\n            speed: 0.5 + (Math.random() * 0.5) // Randomize speed a bit\n        });\n    }\n\n    // Run the race simulation - 10 steps\n    for (let step = 0; step < 10; step++) {\n        for (const horse of weightedHorses) {\n            // Movement based on weight (higher weight = more likely to advance) and speed\n            horse.position += horse.weight * horse.speed * (0.8 + Math.random() * 0.4);\n        }\n    }\n\n    // Sort by final position\n    return weightedHorses.sort((a, b) => b.position - a.position);\n}\n\n// Generate a visual representation of the race\nexport function generateRaceProgress(results) {\n    if (!results || !Array.isArray(results) || results.length === 0) {\n        return \"The race is too close to call!\";\n    }\n\n    const top3 = results.slice(0, Math.min(3, results.length));\n    return top3.map((horse, index) => `${horse.name}${index === 0 ? ' in the lead' : ''}`).join(', ') + \"!\";\n}\n\n// Track player statistics\nexport async function updatePlayerStats(gameServerId, moduleId, playerId, bet, isWin, winnings = 0) {\n    try {\n        // Get existing player stats\n        const statsSearch = await takaro.variable.variableControllerSearch({\n            filters: {\n                key: ['horse_racing_stats'],\n                gameServerId: [gameServerId],\n                moduleId: [moduleId],\n                playerId: [playerId],\n            },\n        });\n\n        let stats;\n        if (statsSearch.data.data.length === 0) {\n            // Initialize new player stats\n            stats = {\n                totalWinnings: 0,\n                totalBets: 0,\n                totalWagered: 0,\n                wins: 0,\n                losses: 0,\n                biggestWin: 0,\n                favoriteHorse: bet.horse,\n                horseStats: {}\n            };\n        } else {\n            stats = JSON.parse(statsSearch.data.data[0].value);\n        }\n\n        // Update stats\n        stats.totalBets++;\n        stats.totalWagered += bet.amount;\n        \n        if (isWin) {\n            stats.wins++;\n            stats.totalWinnings += winnings;\n            if (winnings > stats.biggestWin) {\n                stats.biggestWin = winnings;\n            }\n        } else {\n            stats.losses++;\n        }\n\n        // Track horse betting patterns\n        if (!stats.horseStats) {\n            stats.horseStats = {};\n        }\n        if (!stats.horseStats[bet.horse]) {\n            stats.horseStats[bet.horse] = { bets: 0, wins: 0, totalWagered: 0 };\n        }\n        \n        stats.horseStats[bet.horse].bets++;\n        stats.horseStats[bet.horse].totalWagered += bet.amount;\n        if (isWin) {\n            stats.horseStats[bet.horse].wins++;\n        }\n\n        // Update favorite horse (most bet on)\n        const mostBetHorse = Object.entries(stats.horseStats).reduce((a, b) => \n            stats.horseStats[a[0]].bets > stats.horseStats[b[0]].bets ? a : b\n        );\n        stats.favoriteHorse = mostBetHorse[0];\n\n        // Save or update stats\n        if (statsSearch.data.data.length === 0) {\n            await takaro.variable.variableControllerCreate({\n                key: 'horse_racing_stats',\n                value: JSON.stringify(stats),\n                gameServerId,\n                moduleId,\n                playerId,\n            });\n        } else {\n            await takaro.variable.variableControllerUpdate(statsSearch.data.data[0].id, {\n                value: JSON.stringify(stats),\n            });\n        }\n\n    } catch (error) {\n        console.log('Error updating player stats:', error);\n    }\n}\n\n// Get exciting race commentary\nexport function getRaceCommentary(stage, horses, results) {\n    const commentaries = {\n        start: [\n            \"🏇 The horses are lined up at the starting gate!\",\n            \"🚩 And they're off! The race has begun!\",\n            \"⚡ Lightning start as the horses burst from the gate!\",\n            \"🎯 The field is packed and ready to run!\"\n        ],\n        midRace: [\n            `🔥 ${results[0].name} takes the early lead!`,\n            `💨 It's a tight race between ${results[0].name} and ${results[1].name}!`,\n            `🏃‍♂️ The pack is bunched together - anyone could win!`,\n            `⚡ ${results[0].name} pulls ahead with a burst of speed!`\n        ],\n        finish: [\n            `🏆 Victory! ${results[0].name} crosses the finish line first!`,\n            `🥇 What a race! ${results[0].name} wins by a nose!`,\n            `🎊 ${results[0].name} takes the checkered flag!`,\n            `🏅 Champion! ${results[0].name} dominates the field!`\n        ]\n    };\n\n    const stageComments = commentaries[stage] || commentaries.start;\n    return stageComments[Math.floor(Math.random() * stageComments.length)];\n}\n\n// Generate jackpot system\nexport async function checkAndCreateJackpot(gameServerId, moduleId, totalBets) {\n    try {\n        // Create jackpot every 10 races or when there are 20+ total bets\n        if (totalBets >= 20) {\n            const jackpotSearch = await takaro.variable.variableControllerSearch({\n                filters: {\n                    key: ['current_jackpot'],\n                    gameServerId: [gameServerId],\n                    moduleId: [moduleId],\n                },\n            });\n\n            let jackpotAmount = Math.floor(totalBets * 50); // Base jackpot\n            \n            if (jackpotSearch.data.data.length === 0) {\n                // Create new jackpot\n                await takaro.variable.variableControllerCreate({\n                    key: 'current_jackpot',\n                    value: JSON.stringify({\n                        amount: jackpotAmount,\n                        active: true,\n                        createdAt: Date.now()\n                    }),\n                    gameServerId,\n                    moduleId,\n                });\n                return { isJackpot: true, amount: jackpotAmount };\n            }\n        }\n        \n        return { isJackpot: false, amount: 0 };\n    } catch (error) {\n        console.log('Error checking jackpot:', error);\n        return { isJackpot: false, amount: 0 };\n    }\n}"
        }
      ],
      "permissions": [
        {
          "permission": "HORSE_RACING_BET",
          "friendlyName": "Place Horse Racing Bets",
          "description": "Allows the player to bet on horse races",
          "canHaveCount": false
        },
        {
          "permission": "HORSE_RACING_ADMIN",
          "friendlyName": "Horse Racing Admin",
          "description": "Allows the player to manage horse races",
          "canHaveCount": false
        }
      ]
    }
  ]
}