@elizaos/plugin-social-alpha 2.0.3-beta.5 → 2.0.3-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients.d.ts +354 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +670 -0
- package/dist/clients.js.map +1 -0
- package/dist/config.d.ts +144 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/events.d.ts +5 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +426 -0
- package/dist/events.js.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts +6 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.js +59 -0
- package/dist/frontend/LeaderboardView.helpers.js.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts +52 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.js +72 -0
- package/dist/frontend/SocialAlphaSpatialView.js.map +1 -0
- package/dist/frontend/SocialAlphaView.d.ts +35 -0
- package/dist/frontend/SocialAlphaView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaView.js +125 -0
- package/dist/frontend/SocialAlphaView.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/mockPriceService.d.ts +22 -0
- package/dist/mockPriceService.d.ts.map +1 -0
- package/dist/mockPriceService.js +21 -0
- package/dist/mockPriceService.js.map +1 -0
- package/dist/providers/socialAlphaProvider.d.ts +15 -0
- package/dist/providers/socialAlphaProvider.d.ts.map +1 -0
- package/dist/providers/socialAlphaProvider.js +261 -0
- package/dist/providers/socialAlphaProvider.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +21 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +10 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/reports.d.ts +57 -0
- package/dist/reports.d.ts.map +1 -0
- package/dist/reports.js +455 -0
- package/dist/reports.js.map +1 -0
- package/dist/routes.d.ts +3 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +59 -0
- package/dist/routes.js.map +1 -0
- package/dist/schemas.d.ts +151 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +258 -0
- package/dist/schemas.js.map +1 -0
- package/dist/service.d.ts +306 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +3078 -0
- package/dist/service.js.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts +61 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.js +207 -0
- package/dist/services/balancedTrustScoreCalculator.js.map +1 -0
- package/dist/services/historicalPriceService.d.ts +59 -0
- package/dist/services/historicalPriceService.d.ts.map +1 -0
- package/dist/services/historicalPriceService.js +291 -0
- package/dist/services/historicalPriceService.js.map +1 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +17 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/priceEnrichmentService.d.ts +109 -0
- package/dist/services/priceEnrichmentService.d.ts.map +1 -0
- package/dist/services/priceEnrichmentService.js +780 -0
- package/dist/services/priceEnrichmentService.js.map +1 -0
- package/dist/services/simulationActorsV2.d.ts +54 -0
- package/dist/services/simulationActorsV2.d.ts.map +1 -0
- package/dist/services/simulationActorsV2.js +362 -0
- package/dist/services/simulationActorsV2.js.map +1 -0
- package/dist/services/simulationRunner.d.ts +113 -0
- package/dist/services/simulationRunner.d.ts.map +1 -0
- package/dist/services/simulationRunner.js +771 -0
- package/dist/services/simulationRunner.js.map +1 -0
- package/dist/services/tokenSimulationService.d.ts +34 -0
- package/dist/services/tokenSimulationService.d.ts.map +1 -0
- package/dist/services/tokenSimulationService.js +297 -0
- package/dist/services/tokenSimulationService.js.map +1 -0
- package/dist/services/trustScoreOptimizer.d.ts +110 -0
- package/dist/services/trustScoreOptimizer.d.ts.map +1 -0
- package/dist/services/trustScoreOptimizer.js +635 -0
- package/dist/services/trustScoreOptimizer.js.map +1 -0
- package/dist/simulationActors.d.ts +35 -0
- package/dist/simulationActors.d.ts.map +1 -0
- package/dist/simulationActors.js +160 -0
- package/dist/simulationActors.js.map +1 -0
- package/dist/social-alpha-view-bundle.d.ts +2 -0
- package/dist/social-alpha-view-bundle.d.ts.map +1 -0
- package/dist/social-alpha-view-bundle.js +5 -0
- package/dist/social-alpha-view-bundle.js.map +1 -0
- package/dist/types.d.ts +937 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +46 -0
- package/dist/types.js.map +1 -0
- package/dist/views/brand/background/clouds_background.jpg +0 -0
- package/dist/views/brand/banners/eliza_banner.svg +20 -0
- package/dist/views/brand/banners/elizacloud_banner.svg +20 -0
- package/dist/views/brand/banners/elizaos_banner.svg +20 -0
- package/dist/views/brand/concepts/billboard_concept_1200.jpg +0 -0
- package/dist/views/brand/concepts/chibi_usb_concept_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_minipc_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_phone_800.jpg +0 -0
- package/dist/views/brand/concepts/concept_usbdrive_900.jpg +0 -0
- package/dist/views/brand/favicons/android-chrome-192x192.png +0 -0
- package/dist/views/brand/favicons/android-chrome-512x512.png +0 -0
- package/dist/views/brand/favicons/apple-touch-icon.png +0 -0
- package/dist/views/brand/favicons/favicon-16x16.png +0 -0
- package/dist/views/brand/favicons/favicon-32x32.png +0 -0
- package/dist/views/brand/favicons/favicon.ico +0 -0
- package/dist/views/brand/favicons/favicon.svg +17 -0
- package/dist/views/brand/logos/elizaOS_text_black.svg +3 -0
- package/dist/views/brand/logos/elizaOS_text_white.svg +3 -0
- package/dist/views/brand/logos/eliza_logotext.svg +26 -0
- package/dist/views/brand/logos/eliza_logotext_black.svg +26 -0
- package/dist/views/brand/logos/eliza_text_black.svg +3 -0
- package/dist/views/brand/logos/eliza_text_white.svg +3 -0
- package/dist/views/brand/logos/elizacloud_logotext.svg +26 -0
- package/dist/views/brand/logos/elizacloud_logotext_black.svg +26 -0
- package/dist/views/brand/logos/elizacloud_text_black.svg +3 -0
- package/dist/views/brand/logos/elizacloud_text_white.svg +3 -0
- package/dist/views/brand/logos/elizaos_logotext.svg +26 -0
- package/dist/views/brand/logos/elizaos_logotext_black.svg +26 -0
- package/dist/views/brand/logos/logo_blue_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_blue_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_orange_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_orange_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_white_blackbg.svg +25 -0
- package/dist/views/brand/logos/logo_white_bluebg.svg +25 -0
- package/dist/views/brand/logos/logo_white_graybg.svg +18 -0
- package/dist/views/brand/logos/logo_white_nobg.svg +24 -0
- package/dist/views/brand/logos/logo_white_orangebg.svg +25 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.svg +20 -0
- package/dist/views/bundle.js +268 -0
- package/dist/views/bundle.js.map +1 -0
- package/dist/views/site.webmanifest +19 -0
- package/package.json +5 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/simulationRunner.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { UUID } from \"@elizaos/core\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { Conviction, SupportedChain } from \"../types.js\";\nimport type { SimulatedActorV2 } from \"./simulationActorsV2.js\";\nimport {\n\ttype TokenScenario as TokenScenarioInterface,\n\tTokenSimulationService,\n} from \"./tokenSimulationService.js\";\n\n// Create enum from the token scenario types\nexport enum TokenScenario {\n\tRUG_PULL_FAST = \"rug_fast\",\n\tRUG_PULL_SLOW = \"rug_slow\",\n\tSCAM_TOKEN = \"scam\",\n\tRUNNER_MOON = \"runner_moon\",\n\tRUNNER_STEADY = \"runner_steady\",\n\tSUCCESSFUL = \"successful\",\n\tMEDIOCRE = \"mediocre\",\n\tSTAGNANT = \"stagnant\",\n\tBLUE_CHIP = \"bluechip\",\n\tPUMP_AND_DUMP = \"pump_dump\",\n\tSLOW_BLEED = \"slow_bleed\",\n}\n\n// Define the price data structure\nexport interface TokenPrice {\n\ttimestamp: Date;\n\tprice: number;\n\tvolume: number;\n\tliquidity: number;\n\tmarketCap: number;\n}\n\n// Actor configuration for simulation\nexport interface ActorConfig {\n\tid: UUID;\n\tusername: string;\n\tarchetype:\n\t\t| \"elite_analyst\"\n\t\t| \"skilled_trader\"\n\t\t| \"pump_chaser\"\n\t\t| \"rug_promoter\"\n\t\t| \"fomo_trader\"\n\t\t| \"contrarian\"\n\t\t| \"technical_analyst\"\n\t\t| \"newbie\"\n\t\t| \"bot_spammer\";\n\texpectedTrustScore: number;\n\ttokenPreferences: TokenScenario[];\n\tcallFrequency: \"high\" | \"medium\" | \"low\";\n\ttimingBias: \"early\" | \"middle\" | \"late\" | \"random\";\n}\n\n// Types matching the real EnrichedCallData format\nexport interface SimulatedCallData {\n\tcallId: UUID;\n\toriginalMessageId: string;\n\tuserId: string;\n\tusername: string;\n\ttimestamp: number;\n\tcontent: string;\n\tnameMentioned?: string;\n\ttokenMentioned?: string;\n\tcaMentioned?: string;\n\tchain: SupportedChain | \"unknown\";\n\tsentiment: \"positive\" | \"negative\" | \"neutral\";\n\tconviction: Conviction;\n\tllmReasoning: string;\n\tcertainty: \"high\" | \"medium\" | \"low\";\n\tfileSource: string;\n\t// Simulation metadata\n\tsimulationMetadata: {\n\t\ttokenScenario: TokenScenario;\n\t\tactorArchetype: string;\n\t\tpriceAtCall: number;\n\t\tmarketCapAtCall: number;\n\t\tliquidityAtCall: number;\n\t\texpectedOutcome: \"profit\" | \"loss\" | \"neutral\";\n\t\tactualProfit?: number; // Calculated at end of simulation\n\t};\n}\n\nexport interface SimulationToken {\n\taddress: string;\n\tsymbol: string;\n\tname: string;\n\tscenario: TokenScenario;\n\tlaunchTime: Date;\n\tinitialPrice: number;\n\tinitialMarketCap: number;\n\tinitialLiquidity: number;\n\tpriceTrajectory?: (step: number) => number;\n}\n\nexport interface SimulationConfig {\n\t// Time settings\n\tstartTime: Date;\n\tendTime: Date;\n\ttimeStepMinutes: number;\n\n\t// Token generation\n\ttokenCount: number;\n\ttokenScenarioDistribution?: Partial<Record<TokenScenario, number>>; // Weights\n\n\t// Actor configuration\n\tactors: ActorConfig[];\n\n\t// Output settings\n\toutputDir: string;\n\tcacheResults: boolean;\n}\n\nexport interface SimulationResult {\n\tcalls: SimulatedCallData[];\n\ttokens: Map<string, SimulationToken>;\n\tpriceHistory: Map<string, TokenPrice[]>;\n\tactorPerformance: Map<\n\t\tstring,\n\t\t{\n\t\t\ttotalCalls: number;\n\t\t\tprofitableCalls: number;\n\t\t\ttotalProfit: number;\n\t\t\taverageProfit: number;\n\t\t\ttrustScore?: number;\n\t\t}\n\t>;\n}\n\nexport class SimulationRunner {\n\tprivate tokenService: TokenSimulationService;\n\n\tconstructor() {\n\t\tthis.tokenService = new TokenSimulationService();\n\t}\n\n\tasync runSimulation(config: SimulationConfig): Promise<SimulationResult> {\n\t\tconsole.log(\"🚀 Starting comprehensive market simulation...\");\n\n\t\t// Initialize result containers\n\t\tconst calls: SimulatedCallData[] = [];\n\t\tconst tokens = new Map<string, SimulationToken>();\n\t\tconst priceHistory = new Map<string, TokenPrice[]>();\n\t\tconst actorPerformance = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\ttotalCalls: number;\n\t\t\t\tprofitableCalls: number;\n\t\t\t\ttotalProfit: number;\n\t\t\t\taverageProfit: number;\n\t\t\t}\n\t\t>();\n\n\t\t// Initialize actors\n\t\tfor (const actor of config.actors) {\n\t\t\t// Convert ActorConfig to SimulatedActorV2\n\t\t\tconst _simulatedActor: SimulatedActorV2 = {\n\t\t\t\tid: actor.id,\n\t\t\t\tusername: actor.username,\n\t\t\t\tarchetype: actor.archetype,\n\t\t\t\ttrustScore: actor.expectedTrustScore,\n\t\t\t\tcallHistory: [],\n\t\t\t\tpreferences: {\n\t\t\t\t\tfavoriteTokenTypes: this.mapScenarioToTypes(actor.tokenPreferences),\n\t\t\t\t\tcallFrequency: actor.callFrequency,\n\t\t\t\t\ttimingBias: actor.timingBias,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tactorPerformance.set(actor.id, {\n\t\t\t\ttotalCalls: 0,\n\t\t\t\tprofitableCalls: 0,\n\t\t\t\ttotalProfit: 0,\n\t\t\t\taverageProfit: 0,\n\t\t\t});\n\t\t}\n\n\t\t// Generate tokens with scenarios\n\t\tconst generatedTokens = this.generateTokens(config);\n\t\tfor (const token of generatedTokens) {\n\t\t\ttokens.set(token.address, token);\n\t\t\tpriceHistory.set(token.address, []);\n\t\t}\n\n\t\t// Run simulation time steps\n\t\tlet currentTime = new Date(config.startTime);\n\t\tconst endTime = new Date(config.endTime);\n\t\tlet stepCount = 0;\n\n\t\twhile (currentTime <= endTime) {\n\t\t\tstepCount++;\n\n\t\t\t// Update token prices for current time\n\t\t\tfor (const [address, token] of tokens) {\n\t\t\t\tconst timeSinceLaunch =\n\t\t\t\t\t(currentTime.getTime() - token.launchTime.getTime()) /\n\t\t\t\t\t(1000 * 60 * 60);\n\n\t\t\t\tif (timeSinceLaunch >= 0) {\n\t\t\t\t\tconst price = this.calculateTokenPrice(token, timeSinceLaunch);\n\n\t\t\t\t\tpriceHistory.get(address)?.push({\n\t\t\t\t\t\ttimestamp: currentTime,\n\t\t\t\t\t\tprice: price.price,\n\t\t\t\t\t\tvolume: price.volume,\n\t\t\t\t\t\tliquidity: price.liquidity,\n\t\t\t\t\t\tmarketCap: price.marketCap,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Generate actor calls for this time step\n\t\t\tconst stepCalls = this.generateCallsForTimeStep(\n\t\t\t\tcurrentTime,\n\t\t\t\ttokens,\n\t\t\t\tpriceHistory,\n\t\t\t\tconfig,\n\t\t\t);\n\n\t\t\tcalls.push(...stepCalls);\n\n\t\t\t// Advance time\n\t\t\tcurrentTime = new Date(\n\t\t\t\tcurrentTime.getTime() + config.timeStepMinutes * 60 * 1000,\n\t\t\t);\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`✅ Simulation complete: ${stepCount} time steps, ${calls.length} calls generated`,\n\t\t);\n\n\t\t// Calculate actual profits for each call\n\t\tawait this.calculateActualProfits(calls, tokens, priceHistory);\n\n\t\t// Update actor performance metrics\n\t\tfor (const call of calls) {\n\t\t\tconst perf = actorPerformance.get(call.userId);\n\t\t\tif (!perf) continue;\n\t\t\tperf.totalCalls++;\n\n\t\t\tif (\n\t\t\t\tcall.simulationMetadata.actualProfit &&\n\t\t\t\tcall.simulationMetadata.actualProfit > 0\n\t\t\t) {\n\t\t\t\tperf.profitableCalls++;\n\t\t\t}\n\n\t\t\tperf.totalProfit += call.simulationMetadata.actualProfit || 0;\n\t\t}\n\n\t\t// Calculate average profits\n\t\tfor (const [_actorId, perf] of actorPerformance) {\n\t\t\tperf.averageProfit =\n\t\t\t\tperf.totalCalls > 0 ? perf.totalProfit / perf.totalCalls : 0;\n\t\t}\n\n\t\tconst result: SimulationResult = {\n\t\t\tcalls,\n\t\t\ttokens,\n\t\t\tpriceHistory,\n\t\t\tactorPerformance,\n\t\t};\n\n\t\t// Cache results if requested\n\t\tif (config.cacheResults) {\n\t\t\tawait this.cacheResults(result, config);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprivate calculateTokenPrice(\n\t\ttoken: SimulationToken,\n\t\thoursSinceLaunch: number,\n\t): TokenPrice {\n\t\t// Use price trajectory if available\n\t\tlet price = token.initialPrice;\n\t\tif (token.priceTrajectory) {\n\t\t\t// Convert hours to steps (assuming 1 step = 1 day)\n\t\t\tconst step = Math.floor(hoursSinceLaunch / 24);\n\t\t\tprice = token.priceTrajectory(step);\n\t\t}\n\n\t\t// Calculate other metrics based on price movement\n\t\tconst priceRatio = price / token.initialPrice;\n\t\tconst marketCap = token.initialMarketCap * priceRatio;\n\t\tconst liquidity = token.initialLiquidity * Math.sqrt(priceRatio); // Liquidity grows slower\n\t\tconst volume = marketCap * 0.1 * (1 + Math.random() * 0.5); // 10-15% of market cap\n\n\t\treturn {\n\t\t\ttimestamp: new Date(),\n\t\t\tprice,\n\t\t\tvolume,\n\t\t\tliquidity,\n\t\t\tmarketCap,\n\t\t};\n\t}\n\n\tprivate mapScenarioToTypes(\n\t\tscenarios: TokenScenario[],\n\t): TokenScenarioInterface[\"type\"][] {\n\t\tconst mapping: Record<TokenScenario, TokenScenarioInterface[\"type\"]> = {\n\t\t\t[TokenScenario.RUG_PULL_FAST]: \"rug\",\n\t\t\t[TokenScenario.RUG_PULL_SLOW]: \"rug\",\n\t\t\t[TokenScenario.SCAM_TOKEN]: \"scam\",\n\t\t\t[TokenScenario.RUNNER_MOON]: \"runner\",\n\t\t\t[TokenScenario.RUNNER_STEADY]: \"runner\",\n\t\t\t[TokenScenario.SUCCESSFUL]: \"successful\",\n\t\t\t[TokenScenario.MEDIOCRE]: \"mediocre\",\n\t\t\t[TokenScenario.STAGNANT]: \"stagnant\",\n\t\t\t[TokenScenario.BLUE_CHIP]: \"bluechip\",\n\t\t\t[TokenScenario.PUMP_AND_DUMP]: \"pump_dump\",\n\t\t\t[TokenScenario.SLOW_BLEED]: \"slow_bleed\",\n\t\t};\n\n\t\treturn scenarios.map((s) => mapping[s]);\n\t}\n\n\tprivate generateTokens(config: SimulationConfig): SimulationToken[] {\n\t\tconst tokens: SimulationToken[] = [];\n\n\t\t// Default distribution if not provided\n\t\tconst distribution = config.tokenScenarioDistribution || {\n\t\t\t[TokenScenario.RUG_PULL_FAST]: 0.15,\n\t\t\t[TokenScenario.RUG_PULL_SLOW]: 0.1,\n\t\t\t[TokenScenario.SCAM_TOKEN]: 0.1,\n\t\t\t[TokenScenario.PUMP_AND_DUMP]: 0.15,\n\t\t\t[TokenScenario.MEDIOCRE]: 0.2,\n\t\t\t[TokenScenario.SUCCESSFUL]: 0.15,\n\t\t\t[TokenScenario.RUNNER_MOON]: 0.05,\n\t\t\t[TokenScenario.BLUE_CHIP]: 0.05,\n\t\t\t[TokenScenario.SLOW_BLEED]: 0.05,\n\t\t};\n\n\t\t// Generate tokens based on distribution\n\t\tfor (let i = 0; i < config.tokenCount; i++) {\n\t\t\tconst scenario = this.selectScenarioByWeight(distribution);\n\t\t\tconst token = this.createToken(scenario, i, config);\n\t\t\ttokens.push(token);\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`📊 Generated ${tokens.length} tokens with scenarios:`,\n\t\t\ttokens.reduce(\n\t\t\t\t(acc, t) => {\n\t\t\t\t\tacc[t.scenario] = (acc[t.scenario] || 0) + 1;\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{} as Record<string, number>,\n\t\t\t),\n\t\t);\n\n\t\treturn tokens;\n\t}\n\n\tprivate selectScenarioByWeight(\n\t\tdistribution: Partial<Record<TokenScenario, number>>,\n\t): TokenScenario {\n\t\tconst entries = Object.entries(distribution) as [TokenScenario, number][];\n\t\tconst totalWeight = entries.reduce((sum, [_, weight]) => sum + weight, 0);\n\t\tlet random = Math.random() * totalWeight;\n\n\t\tfor (const [scenario, weight] of entries) {\n\t\t\trandom -= weight;\n\t\t\tif (random <= 0) {\n\t\t\t\treturn scenario;\n\t\t\t}\n\t\t}\n\n\t\treturn TokenScenario.MEDIOCRE; // Fallback\n\t}\n\n\tprivate createToken(\n\t\tscenario: TokenScenario,\n\t\tindex: number,\n\t\tconfig: SimulationConfig,\n\t): SimulationToken {\n\t\t// Spread token launches across simulation time\n\t\tconst launchSpread = config.endTime.getTime() - config.startTime.getTime();\n\t\tconst launchOffset = Math.random() * launchSpread * 0.8; // Launch in first 80% of simulation\n\n\t\t// Create appropriate scenario from token service\n\t\tconst scenarioConfig = this.getScenarioConfig(scenario);\n\t\tconst tokenFromService =\n\t\t\tthis.tokenService.createTokenFromScenario(scenarioConfig);\n\n\t\treturn {\n\t\t\taddress: `0x${uuidv4().replace(/-/g, \"\")}${index.toString().padStart(8, \"0\")}`,\n\t\t\tsymbol: `SIM${scenario.substring(0, 3).toUpperCase()}${index}`,\n\t\t\tname: `Simulated ${scenario.replace(/_/g, \" \")} Token ${index}`,\n\t\t\tscenario,\n\t\t\tlaunchTime: new Date(config.startTime.getTime() + launchOffset),\n\t\t\tinitialPrice: 0.00001 + Math.random() * 0.0001, // $0.00001 - $0.0001\n\t\t\tinitialMarketCap: 10000 + Math.random() * 90000, // $10k - $100k\n\t\t\tinitialLiquidity: 5000 + Math.random() * 45000, // $5k - $50k\n\t\t\tpriceTrajectory: tokenFromService.priceTrajectory,\n\t\t};\n\t}\n\n\tprivate getScenarioConfig(scenario: TokenScenario): TokenScenarioInterface {\n\t\tconst configs: Record<TokenScenario, TokenScenarioInterface> = {\n\t\t\t[TokenScenario.RUG_PULL_FAST]: {\n\t\t\t\ttype: \"rug\",\n\t\t\t\tname: \"FastRug Token\",\n\t\t\t\tsymbol: \"FRUG\",\n\t\t\t\tdescription: \"Rugs within 2 days\",\n\t\t\t\tinitialPrice: 0.00001,\n\t\t\t\tinitialLiquidity: 5000,\n\t\t\t\tinitialMarketCap: 10000,\n\t\t\t\trugTiming: 2,\n\t\t\t},\n\t\t\t[TokenScenario.RUG_PULL_SLOW]: {\n\t\t\t\ttype: \"rug\",\n\t\t\t\tname: \"SlowRug Token\",\n\t\t\t\tsymbol: \"SRUG\",\n\t\t\t\tdescription: \"Builds trust then rugs\",\n\t\t\t\tinitialPrice: 0.00005,\n\t\t\t\tinitialLiquidity: 20000,\n\t\t\t\tinitialMarketCap: 50000,\n\t\t\t\trugTiming: 10,\n\t\t\t},\n\t\t\t[TokenScenario.SCAM_TOKEN]: {\n\t\t\t\ttype: \"scam\",\n\t\t\t\tname: \"Scam Token\",\n\t\t\t\tsymbol: \"SCAM\",\n\t\t\t\tdescription: \"Low liquidity scam\",\n\t\t\t\tinitialPrice: 0.001,\n\t\t\t\tinitialLiquidity: 500,\n\t\t\t\tinitialMarketCap: 5000,\n\t\t\t},\n\t\t\t[TokenScenario.RUNNER_MOON]: {\n\t\t\t\ttype: \"runner\",\n\t\t\t\tname: \"MoonShot Token\",\n\t\t\t\tsymbol: \"MOON\",\n\t\t\t\tdescription: \"50x growth potential\",\n\t\t\t\tinitialPrice: 0.00001,\n\t\t\t\tinitialLiquidity: 50000,\n\t\t\t\tinitialMarketCap: 100000,\n\t\t\t},\n\t\t\t[TokenScenario.RUNNER_STEADY]: {\n\t\t\t\ttype: \"runner\",\n\t\t\t\tname: \"SteadyGains Token\",\n\t\t\t\tsymbol: \"GAIN\",\n\t\t\t\tdescription: \"10x steady growth\",\n\t\t\t\tinitialPrice: 0.0001,\n\t\t\t\tinitialLiquidity: 30000,\n\t\t\t\tinitialMarketCap: 200000,\n\t\t\t},\n\t\t\t[TokenScenario.SUCCESSFUL]: {\n\t\t\t\ttype: \"successful\",\n\t\t\t\tname: \"Solid Project\",\n\t\t\t\tsymbol: \"SOLID\",\n\t\t\t\tdescription: \"3x growth\",\n\t\t\t\tinitialPrice: 0.001,\n\t\t\t\tinitialLiquidity: 100000,\n\t\t\t\tinitialMarketCap: 500000,\n\t\t\t},\n\t\t\t[TokenScenario.MEDIOCRE]: {\n\t\t\t\ttype: \"mediocre\",\n\t\t\t\tname: \"Crabwalk Token\",\n\t\t\t\tsymbol: \"CRAB\",\n\t\t\t\tdescription: \"Sideways movement\",\n\t\t\t\tinitialPrice: 0.01,\n\t\t\t\tinitialLiquidity: 50000,\n\t\t\t\tinitialMarketCap: 300000,\n\t\t\t},\n\t\t\t[TokenScenario.STAGNANT]: {\n\t\t\t\ttype: \"stagnant\",\n\t\t\t\tname: \"Dead Project\",\n\t\t\t\tsymbol: \"DEAD\",\n\t\t\t\tdescription: \"No volume\",\n\t\t\t\tinitialPrice: 0.005,\n\t\t\t\tinitialLiquidity: 10000,\n\t\t\t\tinitialMarketCap: 50000,\n\t\t\t},\n\t\t\t[TokenScenario.BLUE_CHIP]: {\n\t\t\t\ttype: \"bluechip\",\n\t\t\t\tname: \"Established Token\",\n\t\t\t\tsymbol: \"BLUE\",\n\t\t\t\tdescription: \"Stable growth\",\n\t\t\t\tinitialPrice: 10.0,\n\t\t\t\tinitialLiquidity: 5000000,\n\t\t\t\tinitialMarketCap: 100000000,\n\t\t\t},\n\t\t\t[TokenScenario.PUMP_AND_DUMP]: {\n\t\t\t\ttype: \"pump_dump\",\n\t\t\t\tname: \"PumpDump Token\",\n\t\t\t\tsymbol: \"PUMP\",\n\t\t\t\tdescription: \"20x then dump\",\n\t\t\t\tinitialPrice: 0.00001,\n\t\t\t\tinitialLiquidity: 15000,\n\t\t\t\tinitialMarketCap: 20000,\n\t\t\t\tpumpTiming: 3,\n\t\t\t\tdumpTiming: 5,\n\t\t\t},\n\t\t\t[TokenScenario.SLOW_BLEED]: {\n\t\t\t\ttype: \"slow_bleed\",\n\t\t\t\tname: \"BleedOut Token\",\n\t\t\t\tsymbol: \"BLEED\",\n\t\t\t\tdescription: \"Slow decline\",\n\t\t\t\tinitialPrice: 0.01,\n\t\t\t\tinitialLiquidity: 40000,\n\t\t\t\tinitialMarketCap: 200000,\n\t\t\t},\n\t\t};\n\n\t\treturn configs[scenario];\n\t}\n\n\tprivate generateCallsForTimeStep(\n\t\tcurrentTime: Date,\n\t\ttokens: Map<string, SimulationToken>,\n\t\tpriceHistory: Map<string, TokenPrice[]>,\n\t\tconfig: SimulationConfig,\n\t): SimulatedCallData[] {\n\t\tconst calls: SimulatedCallData[] = [];\n\n\t\t// Get active tokens (launched but not dead)\n\t\tconst activeTokens = Array.from(tokens.values()).filter((token) => {\n\t\t\tconst isLaunched = token.launchTime <= currentTime;\n\t\t\tconst history = priceHistory.get(token.address) || [];\n\t\t\tconst latestPrice = history[history.length - 1];\n\t\t\tconst isDead =\n\t\t\t\tlatestPrice && latestPrice.price < token.initialPrice * 0.01;\n\n\t\t\treturn isLaunched && !isDead;\n\t\t});\n\n\t\tif (activeTokens.length === 0) return calls;\n\n\t\t// Each actor makes decisions\n\t\tfor (const actor of config.actors) {\n\t\t\t// Check if actor should make a call this time step\n\t\t\tconst shouldCall = this.shouldActorCall(actor, currentTime);\n\t\t\tif (!shouldCall) continue;\n\n\t\t\t// Select tokens based on actor preferences\n\t\t\tconst targetTokens = this.selectTokensForActor(\n\t\t\t\tactor,\n\t\t\t\tactiveTokens,\n\t\t\t\tpriceHistory,\n\t\t\t\tcurrentTime,\n\t\t\t);\n\n\t\t\tfor (const token of targetTokens) {\n\t\t\t\tconst tokenPriceHistory = priceHistory.get(token.address);\n\t\t\t\tif (!tokenPriceHistory) continue;\n\t\t\t\tconst call = this.generateActorCall(\n\t\t\t\t\tactor,\n\t\t\t\t\ttoken,\n\t\t\t\t\ttokenPriceHistory,\n\t\t\t\t\tcurrentTime,\n\t\t\t\t);\n\n\t\t\t\tif (call) {\n\t\t\t\t\tcalls.push(call);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn calls;\n\t}\n\n\tprivate shouldActorCall(actor: ActorConfig, _currentTime: Date): boolean {\n\t\t// Base frequency on actor's call frequency setting - increased for better simulation\n\t\tconst frequencyMultiplier = {\n\t\t\thigh: 0.7, // Increased from 0.3\n\t\t\tmedium: 0.4, // Increased from 0.1\n\t\t\tlow: 0.15, // Increased from 0.03\n\t\t}[actor.callFrequency];\n\n\t\treturn Math.random() < frequencyMultiplier;\n\t}\n\n\tprivate selectTokensForActor(\n\t\tactor: ActorConfig,\n\t\tactiveTokens: SimulationToken[],\n\t\tpriceHistory: Map<string, TokenPrice[]>,\n\t\tcurrentTime: Date,\n\t): SimulationToken[] {\n\t\t// Filter tokens based on actor preferences\n\t\tlet candidateTokens = activeTokens;\n\n\t\t// Elite analysts and skilled traders should identify good tokens early\n\t\tif ([\"elite_analyst\", \"skilled_trader\"].includes(actor.archetype)) {\n\t\t\tcandidateTokens = activeTokens.filter((token) => {\n\t\t\t\tconst _history = priceHistory.get(token.address) || [];\n\t\t\t\tconst timeSinceLaunch =\n\t\t\t\t\t(currentTime.getTime() - token.launchTime.getTime()) /\n\t\t\t\t\t(1000 * 60 * 60);\n\n\t\t\t\t// Focus on quality tokens in early stages\n\t\t\t\tif (actor.archetype === \"elite_analyst\") {\n\t\t\t\t\t// Elite analysts avoid rugs and scams entirely\n\t\t\t\t\tif (\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tTokenScenario.RUG_PULL_FAST,\n\t\t\t\t\t\t\tTokenScenario.RUG_PULL_SLOW,\n\t\t\t\t\t\t\tTokenScenario.SCAM_TOKEN,\n\t\t\t\t\t\t].includes(token.scenario)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\t// Focus on early-stage quality tokens\n\t\t\t\t\treturn (\n\t\t\t\t\t\ttimeSinceLaunch < 48 && // Within 2 days of launch\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tTokenScenario.SUCCESSFUL,\n\t\t\t\t\t\t\tTokenScenario.RUNNER_MOON,\n\t\t\t\t\t\t\tTokenScenario.RUNNER_STEADY,\n\t\t\t\t\t\t\tTokenScenario.BLUE_CHIP,\n\t\t\t\t\t\t].includes(token.scenario)\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Skilled traders might catch some pumps but avoid obvious scams\n\t\t\t\t\treturn (\n\t\t\t\t\t\ttimeSinceLaunch < 72 && // Within 3 days\n\t\t\t\t\t\t![TokenScenario.SCAM_TOKEN].includes(token.scenario)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// FOMO traders chase pumps that have already happened\n\t\telse if (actor.archetype === \"fomo_trader\") {\n\t\t\tcandidateTokens = activeTokens.filter((token) => {\n\t\t\t\tconst history = priceHistory.get(token.address) || [];\n\t\t\t\tif (history.length < 10) return false;\n\n\t\t\t\t// Look for tokens that have already pumped significantly\n\t\t\t\tconst recentGain =\n\t\t\t\t\thistory[history.length - 1].price /\n\t\t\t\t\t\thistory[history.length - 10].price -\n\t\t\t\t\t1;\n\t\t\t\treturn recentGain > 0.5; // Already up 50%+\n\t\t\t});\n\t\t}\n\n\t\t// Pump chasers specifically target pump scenarios\n\t\telse if (actor.archetype === \"pump_chaser\") {\n\t\t\tcandidateTokens = activeTokens.filter((token) => {\n\t\t\t\tconst history = priceHistory.get(token.address) || [];\n\t\t\t\tif (history.length < 5) return false;\n\n\t\t\t\t// Look for rapid price increases\n\t\t\t\tconst recentGain =\n\t\t\t\t\thistory[history.length - 1].price /\n\t\t\t\t\t\thistory[history.length - 5].price -\n\t\t\t\t\t1;\n\t\t\t\treturn recentGain > 0.3; // Up 30%+ recently\n\t\t\t});\n\t\t}\n\n\t\t// Rug promoters target their preferred scam tokens\n\t\telse if (actor.archetype === \"rug_promoter\") {\n\t\t\tcandidateTokens = activeTokens.filter(\n\t\t\t\t(token) =>\n\t\t\t\t\tactor.tokenPreferences.includes(token.scenario) &&\n\t\t\t\t\ttoken.scenario !== TokenScenario.BLUE_CHIP, // Even rug promoters avoid obvious blue chips\n\t\t\t);\n\t\t}\n\n\t\t// Apply general token preferences if we still have candidates\n\t\tif (candidateTokens.length === 0) {\n\t\t\tcandidateTokens = activeTokens.filter((token) =>\n\t\t\t\tactor.tokenPreferences.includes(token.scenario),\n\t\t\t);\n\t\t}\n\n\t\tif (candidateTokens.length === 0) return [];\n\n\t\t// Apply timing bias to the candidate tokens\n\t\tconst timedTokens = candidateTokens.filter((token) => {\n\t\t\tconst _history = priceHistory.get(token.address) || [];\n\t\t\tconst timeSinceLaunch =\n\t\t\t\t(currentTime.getTime() - token.launchTime.getTime()) / (1000 * 60 * 60);\n\n\t\t\tswitch (actor.timingBias) {\n\t\t\t\tcase \"early\":\n\t\t\t\t\treturn timeSinceLaunch < 24; // First day only\n\t\t\t\tcase \"middle\":\n\t\t\t\t\treturn timeSinceLaunch >= 24 && timeSinceLaunch < 120; // Day 1-5\n\t\t\t\tcase \"late\":\n\t\t\t\t\treturn timeSinceLaunch >= 72; // After 3 days\n\t\t\t\tdefault:\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\n\t\tconst finalTokens = timedTokens.length > 0 ? timedTokens : candidateTokens;\n\n\t\t// Select 1-2 tokens (elite analysts are more selective)\n\t\tconst maxTokens = actor.archetype === \"elite_analyst\" ? 1 : 2;\n\t\tconst numTokens = Math.min(\n\t\t\tfinalTokens.length,\n\t\t\tMath.floor(Math.random() * maxTokens) + 1,\n\t\t);\n\n\t\treturn finalTokens.sort(() => Math.random() - 0.5).slice(0, numTokens);\n\t}\n\n\tprivate generateActorCall(\n\t\tactor: ActorConfig,\n\t\ttoken: SimulationToken,\n\t\tpriceHistory: TokenPrice[],\n\t\tcurrentTime: Date,\n\t): SimulatedCallData | null {\n\t\tconst latestPrice = priceHistory[priceHistory.length - 1];\n\t\tif (!latestPrice) return null;\n\n\t\t// Generate message based on actor archetype\n\t\tconst message = this.generateMessage(\n\t\t\tactor,\n\t\t\ttoken.symbol,\n\t\t\ttoken.scenario,\n\t\t\t\"positive\", // Will be overridden based on actor logic\n\t\t);\n\n\t\tif (!message) return null;\n\n\t\t// Determine sentiment based on actor type and market conditions\n\t\tconst sentiment = this.determineActorSentiment(actor, token, priceHistory);\n\n\t\t// Determine conviction based on actor confidence\n\t\tconst conviction = this.determineActorConviction(\n\t\t\tactor,\n\t\t\ttoken,\n\t\t\tpriceHistory,\n\t\t);\n\n\t\treturn {\n\t\t\tcallId: uuidv4() as UUID,\n\t\t\toriginalMessageId: `sim_msg_${uuidv4()}`,\n\t\t\tuserId: actor.id,\n\t\t\tusername: actor.username,\n\t\t\ttimestamp: currentTime.getTime(),\n\t\t\tcontent: message,\n\t\t\ttokenMentioned: token.symbol,\n\t\t\tnameMentioned: token.name,\n\t\t\tcaMentioned: token.address,\n\t\t\tchain: SupportedChain.SOLANA,\n\t\t\tsentiment,\n\t\t\tconviction,\n\t\t\tllmReasoning: `${actor.username} (${actor.archetype}) analyzing ${token.symbol}`,\n\t\t\tcertainty: \"high\",\n\t\t\tfileSource: \"simulation\",\n\t\t\tsimulationMetadata: {\n\t\t\t\ttokenScenario: token.scenario,\n\t\t\t\tactorArchetype: actor.archetype,\n\t\t\t\tpriceAtCall: latestPrice.price,\n\t\t\t\tmarketCapAtCall: latestPrice.marketCap,\n\t\t\t\tliquidityAtCall: latestPrice.liquidity,\n\t\t\t\texpectedOutcome: this.predictOutcome(actor, token),\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate generateMessage(\n\t\tactor: ActorConfig,\n\t\ttokenSymbol: string,\n\t\t_scenario: TokenScenario,\n\t\t_sentiment: string,\n\t): string {\n\t\t// Simple message templates based on archetype\n\t\tconst templates: Record<ActorConfig[\"archetype\"], string[]> = {\n\t\t\telite_analyst: [\n\t\t\t\t`$${tokenSymbol} showing strong fundamentals. This is a long-term hold.`,\n\t\t\t\t`Been researching $${tokenSymbol} - solid team and execution plan. Accumulating here.`,\n\t\t\t],\n\t\t\tskilled_trader: [\n\t\t\t\t`$${tokenSymbol} looking strong here. Adding to position.`,\n\t\t\t\t`Good entry point for $${tokenSymbol}. Risk/reward favorable.`,\n\t\t\t],\n\t\t\tpump_chaser: [\n\t\t\t\t`$${tokenSymbol} is pumping hard! Just aped in!`,\n\t\t\t\t`Holy shit $${tokenSymbol} is flying! This is going to $1!`,\n\t\t\t],\n\t\t\trug_promoter: [\n\t\t\t\t`🚀🚀 $${tokenSymbol} TO THE MOON! 1000X GEM! GET IN NOW! 🚀🚀`,\n\t\t\t\t`$${tokenSymbol} NEXT 100X!!! DEV DOXXED! LIQUIDITY LOCKED! SAFU! 💎💎`,\n\t\t\t],\n\t\t\tfomo_trader: [\n\t\t\t\t`Everyone buying $${tokenSymbol}! I'm in!`,\n\t\t\t\t`$${tokenSymbol} trending everywhere! Don't want to miss this!`,\n\t\t\t],\n\t\t\tcontrarian: [\n\t\t\t\t`$${tokenSymbol} overhyped. Taking opposite position.`,\n\t\t\t\t`While everyone's bullish on $${tokenSymbol}, I see weakness.`,\n\t\t\t],\n\t\t\ttechnical_analyst: [\n\t\t\t\t`$${tokenSymbol} breaking key resistance. Chart looks bullish.`,\n\t\t\t\t`RSI oversold on $${tokenSymbol}. Bounce incoming.`,\n\t\t\t],\n\t\t\tnewbie: [\n\t\t\t\t`Is $${tokenSymbol} a good buy? Thinking about getting some.`,\n\t\t\t\t`Just bought my first $${tokenSymbol}! Hope it goes up!`,\n\t\t\t],\n\t\t\tbot_spammer: [\n\t\t\t\t`💎 $${tokenSymbol} 💎 BUY NOW 💎`,\n\t\t\t\t`$${tokenSymbol} $${tokenSymbol} $${tokenSymbol} 🚀🚀🚀`,\n\t\t\t],\n\t\t};\n\n\t\tconst archetypeTemplates = templates[actor.archetype];\n\t\treturn archetypeTemplates[\n\t\t\tMath.floor(Math.random() * archetypeTemplates.length)\n\t\t];\n\t}\n\n\tprivate determineActorSentiment(\n\t\tactor: ActorConfig,\n\t\ttoken: SimulationToken,\n\t\tpriceHistory: TokenPrice[],\n\t): \"positive\" | \"negative\" | \"neutral\" {\n\t\t// Elite analysts correctly identify token quality\n\t\tif (actor.archetype === \"elite_analyst\") {\n\t\t\t// Positive on good tokens\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\tTokenScenario.SUCCESSFUL,\n\t\t\t\t\tTokenScenario.RUNNER_MOON,\n\t\t\t\t\tTokenScenario.RUNNER_STEADY,\n\t\t\t\t\tTokenScenario.BLUE_CHIP,\n\t\t\t\t].includes(token.scenario)\n\t\t\t) {\n\t\t\t\treturn \"positive\";\n\t\t\t}\n\t\t\t// Negative on bad tokens (warnings)\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\tTokenScenario.RUG_PULL_FAST,\n\t\t\t\t\tTokenScenario.RUG_PULL_SLOW,\n\t\t\t\t\tTokenScenario.SCAM_TOKEN,\n\t\t\t\t].includes(token.scenario)\n\t\t\t) {\n\t\t\t\treturn \"negative\";\n\t\t\t}\n\t\t\treturn \"neutral\";\n\t\t}\n\n\t\t// Skilled traders mostly get it right but can be fooled by pump and dumps\n\t\tif (actor.archetype === \"skilled_trader\") {\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\tTokenScenario.SUCCESSFUL,\n\t\t\t\t\tTokenScenario.RUNNER_MOON,\n\t\t\t\t\tTokenScenario.RUNNER_STEADY,\n\t\t\t\t].includes(token.scenario)\n\t\t\t) {\n\t\t\t\treturn \"positive\";\n\t\t\t}\n\t\t\tif (\n\t\t\t\t[TokenScenario.RUG_PULL_FAST, TokenScenario.SCAM_TOKEN].includes(\n\t\t\t\t\ttoken.scenario,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn Math.random() < 0.7 ? \"negative\" : \"positive\"; // 70% chance to identify scams\n\t\t\t}\n\t\t\tif (token.scenario === TokenScenario.PUMP_AND_DUMP) {\n\t\t\t\t// Might catch the pump\n\t\t\t\tconst timeSinceLaunch = priceHistory.length;\n\t\t\t\treturn timeSinceLaunch < 5 ? \"positive\" : \"negative\";\n\t\t\t}\n\t\t\treturn \"neutral\";\n\t\t}\n\n\t\t// Rug promoters always positive on rugs\n\t\tif (actor.archetype === \"rug_promoter\") {\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\tTokenScenario.RUG_PULL_FAST,\n\t\t\t\t\tTokenScenario.RUG_PULL_SLOW,\n\t\t\t\t\tTokenScenario.SCAM_TOKEN,\n\t\t\t\t].includes(token.scenario)\n\t\t\t) {\n\t\t\t\treturn \"positive\"; // Shilling scams\n\t\t\t}\n\t\t\treturn \"neutral\";\n\t\t}\n\n\t\t// FOMO traders are always positive when chasing\n\t\tif (actor.archetype === \"fomo_trader\") {\n\t\t\treturn \"positive\"; // Always bullish when FOMOing\n\t\t}\n\n\t\t// Pump chasers are positive on anything moving up\n\t\tif (actor.archetype === \"pump_chaser\") {\n\t\t\tconst priceChange =\n\t\t\t\tpriceHistory.length > 5\n\t\t\t\t\t? priceHistory[priceHistory.length - 1].price /\n\t\t\t\t\t\t\tpriceHistory[priceHistory.length - 5].price -\n\t\t\t\t\t\t1\n\t\t\t\t\t: 0;\n\t\t\treturn priceChange > 0.1 ? \"positive\" : \"neutral\";\n\t\t}\n\n\t\t// Contrarians go against recent price action\n\t\tif (actor.archetype === \"contrarian\") {\n\t\t\tconst priceChange =\n\t\t\t\tpriceHistory.length > 10\n\t\t\t\t\t? priceHistory[priceHistory.length - 1].price /\n\t\t\t\t\t\t\tpriceHistory[priceHistory.length - 10].price -\n\t\t\t\t\t\t1\n\t\t\t\t\t: 0;\n\t\t\treturn priceChange > 0.2 ? \"negative\" : \"positive\";\n\t\t}\n\n\t\t// Default\n\t\treturn actor.tokenPreferences.includes(token.scenario)\n\t\t\t? \"positive\"\n\t\t\t: \"neutral\";\n\t}\n\n\tprivate determineActorConviction(\n\t\tactor: ActorConfig,\n\t\t_token: SimulationToken,\n\t\tpriceHistory: TokenPrice[],\n\t): Conviction {\n\t\t// Base conviction on actor archetype\n\t\tconst baseConviction =\n\t\t\t{\n\t\t\t\telite_analyst: Conviction.HIGH,\n\t\t\t\tskilled_trader: Conviction.MEDIUM,\n\t\t\t\tpump_chaser: Conviction.HIGH,\n\t\t\t\trug_promoter: Conviction.VERY_HIGH,\n\t\t\t\tfomo_trader: Conviction.MEDIUM,\n\t\t\t\tcontrarian: Conviction.MEDIUM,\n\t\t\t\ttechnical_analyst: Conviction.MEDIUM,\n\t\t\t\tnewbie: Conviction.LOW,\n\t\t\t\tbot_spammer: Conviction.LOW,\n\t\t\t}[actor.archetype] || Conviction.MEDIUM;\n\n\t\t// Adjust based on price action for some archetypes\n\t\tif ([\"pump_chaser\", \"fomo_trader\"].includes(actor.archetype)) {\n\t\t\tconst recentGain =\n\t\t\t\tpriceHistory.length > 5\n\t\t\t\t\t? priceHistory[priceHistory.length - 1].price /\n\t\t\t\t\t\t\tpriceHistory[priceHistory.length - 5].price -\n\t\t\t\t\t\t1\n\t\t\t\t\t: 0;\n\n\t\t\tif (recentGain > 0.5) {\n\t\t\t\treturn Conviction.VERY_HIGH;\n\t\t\t}\n\t\t}\n\n\t\treturn baseConviction;\n\t}\n\n\tprivate predictOutcome(\n\t\tactor: ActorConfig,\n\t\ttoken: SimulationToken,\n\t): \"profit\" | \"loss\" | \"neutral\" {\n\t\t// Predict based on actor skill and token type\n\t\tconst successfulScenarios = [\n\t\t\tTokenScenario.SUCCESSFUL,\n\t\t\tTokenScenario.RUNNER_MOON,\n\t\t\tTokenScenario.BLUE_CHIP,\n\t\t];\n\n\t\tconst isGoodToken = successfulScenarios.includes(token.scenario);\n\t\tconst isSkilled = [\n\t\t\t\"elite_analyst\",\n\t\t\t\"skilled_trader\",\n\t\t\t\"contrarian\",\n\t\t].includes(actor.archetype);\n\n\t\tif (isSkilled && isGoodToken) return \"profit\";\n\t\tif (!isSkilled && !isGoodToken) return \"loss\";\n\t\tif (actor.archetype === \"rug_promoter\" && !isGoodToken) return \"loss\";\n\n\t\treturn \"neutral\";\n\t}\n\n\tprivate calculateActualProfits(\n\t\tcalls: SimulatedCallData[],\n\t\ttokens: Map<string, SimulationToken>,\n\t\tpriceHistory: Map<string, TokenPrice[]>,\n\t): Promise<void> {\n\t\tfor (const call of calls) {\n\t\t\tconst token = tokens.get(call.caMentioned || \"\");\n\t\t\tif (!token) continue;\n\n\t\t\tconst history = priceHistory.get(token.address) || [];\n\t\t\tconst callIndex = history.findIndex(\n\t\t\t\t(p) => p.timestamp.getTime() === call.timestamp,\n\t\t\t);\n\n\t\t\tif (callIndex === -1 || callIndex === history.length - 1) {\n\t\t\t\tcall.simulationMetadata.actualProfit = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// For negative sentiment calls, calculate profit inversely (profit from price going down)\n\t\t\tif (call.sentiment === \"negative\") {\n\t\t\t\tconst entryPrice = history[callIndex].price;\n\t\t\t\tconst exitIndex = Math.min(callIndex + 24, history.length - 1);\n\t\t\t\tconst exitPrice = history[exitIndex].price;\n\n\t\t\t\t// Profit from warning about bad tokens (short position simulation)\n\t\t\t\tconst priceDropPercent = ((entryPrice - exitPrice) / entryPrice) * 100;\n\t\t\t\tcall.simulationMetadata.actualProfit = priceDropPercent;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// For positive sentiment calls\n\t\t\tlet exitIndex: number;\n\t\t\tlet forcedExit = false;\n\n\t\t\t// Check for rug pulls or dumps\n\t\t\tif (\n\t\t\t\t[\n\t\t\t\t\tTokenScenario.RUG_PULL_FAST,\n\t\t\t\t\tTokenScenario.RUG_PULL_SLOW,\n\t\t\t\t\tTokenScenario.SCAM_TOKEN,\n\t\t\t\t].includes(token.scenario)\n\t\t\t) {\n\t\t\t\t// Find when the rug happens\n\t\t\t\tlet rugIndex = callIndex;\n\t\t\t\tfor (let i = callIndex + 1; i < history.length; i++) {\n\t\t\t\t\tif (history[i].price < history[callIndex].price * 0.1) {\n\t\t\t\t\t\t// 90% drop = rug\n\t\t\t\t\t\trugIndex = i;\n\t\t\t\t\t\tforcedExit = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\texitIndex = rugIndex;\n\t\t\t} else if (token.scenario === TokenScenario.PUMP_AND_DUMP) {\n\t\t\t\t// Find the dump\n\t\t\t\tlet dumpIndex = callIndex;\n\t\t\t\tlet peakPrice = history[callIndex].price;\n\t\t\t\tfor (let i = callIndex + 1; i < history.length; i++) {\n\t\t\t\t\tif (history[i].price > peakPrice) {\n\t\t\t\t\t\tpeakPrice = history[i].price;\n\t\t\t\t\t} else if (history[i].price < peakPrice * 0.3) {\n\t\t\t\t\t\t// 70% drop from peak = dump\n\t\t\t\t\t\tdumpIndex = i;\n\t\t\t\t\t\tforcedExit = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\texitIndex = dumpIndex;\n\t\t\t} else {\n\t\t\t\t// Normal exit strategies based on actor type\n\t\t\t\tif (call.simulationMetadata.actorArchetype === \"elite_analyst\") {\n\t\t\t\t\t// Elite analysts hold quality tokens longer\n\t\t\t\t\texitIndex = Math.min(callIndex + 72, history.length - 1); // 3 days\n\t\t\t\t} else if (\n\t\t\t\t\tcall.simulationMetadata.actorArchetype === \"skilled_trader\"\n\t\t\t\t) {\n\t\t\t\t\t// Skilled traders take profits at reasonable times\n\t\t\t\t\texitIndex = Math.min(callIndex + 48, history.length - 1); // 2 days\n\t\t\t\t} else if (\n\t\t\t\t\t[\"pump_chaser\", \"fomo_trader\"].includes(\n\t\t\t\t\t\tcall.simulationMetadata.actorArchetype,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// These actors often hold too long and miss the exit\n\t\t\t\t\texitIndex = Math.min(callIndex + 24, history.length - 1); // 1 day\n\t\t\t\t} else {\n\t\t\t\t\t// Default: 24 hour hold\n\t\t\t\t\texitIndex = Math.min(callIndex + 24, history.length - 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst entryPrice = history[callIndex].price;\n\t\t\tconst exitPrice = history[exitIndex].price;\n\n\t\t\t// Apply realistic entry slippage based on actor type\n\t\t\tlet effectiveEntryPrice = entryPrice;\n\n\t\t\tif (\n\t\t\t\t[\"fomo_trader\", \"pump_chaser\"].includes(\n\t\t\t\t\tcall.simulationMetadata.actorArchetype,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\t// FOMO traders buy after the pump, paying premium\n\t\t\t\teffectiveEntryPrice = entryPrice * 1.15; // 15% slippage\n\t\t\t} else if (call.simulationMetadata.actorArchetype === \"rug_promoter\") {\n\t\t\t\t// Rug promoters often buy at terrible prices or don't actually buy\n\t\t\t\tif (\n\t\t\t\t\t[\n\t\t\t\t\t\tTokenScenario.RUG_PULL_FAST,\n\t\t\t\t\t\tTokenScenario.RUG_PULL_SLOW,\n\t\t\t\t\t\tTokenScenario.SCAM_TOKEN,\n\t\t\t\t\t].includes(token.scenario)\n\t\t\t\t) {\n\t\t\t\t\t// They're promoting rugs - assume they either don't buy or get rugged\n\t\t\t\t\teffectiveEntryPrice = entryPrice * 1.2; // 20% slippage if they buy\n\t\t\t\t}\n\t\t\t} else if (call.simulationMetadata.actorArchetype === \"elite_analyst\") {\n\t\t\t\t// Elite analysts get good entries\n\t\t\t\teffectiveEntryPrice = entryPrice * 0.98; // 2% better than market\n\t\t\t}\n\n\t\t\t// Apply exit slippage for forced exits (panic selling)\n\t\t\tlet effectiveExitPrice = exitPrice;\n\t\t\tif (\n\t\t\t\tforcedExit &&\n\t\t\t\t[\"pump_chaser\", \"fomo_trader\", \"rug_promoter\"].includes(\n\t\t\t\t\tcall.simulationMetadata.actorArchetype,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\teffectiveExitPrice = exitPrice * 0.9; // 10% slippage on panic sell\n\t\t\t}\n\n\t\t\tconst profitPercent =\n\t\t\t\t((effectiveExitPrice - effectiveEntryPrice) / effectiveEntryPrice) *\n\t\t\t\t100;\n\n\t\t\tcall.simulationMetadata.actualProfit = profitPercent;\n\t\t}\n\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate async cacheResults(\n\t\tresult: SimulationResult,\n\t\tconfig: SimulationConfig,\n\t): Promise<void> {\n\t\tconst outputDir = config.outputDir;\n\t\tawait fs.mkdir(outputDir, { recursive: true });\n\n\t\t// Save calls\n\t\tconst callsPath = path.join(outputDir, \"simulated_calls.json\");\n\t\tawait fs.writeFile(callsPath, JSON.stringify(result.calls, null, 2));\n\n\t\t// Save tokens\n\t\tconst tokensPath = path.join(outputDir, \"simulated_tokens.json\");\n\t\tawait fs.writeFile(\n\t\t\ttokensPath,\n\t\t\tJSON.stringify(Array.from(result.tokens.entries()), null, 2),\n\t\t);\n\n\t\t// Save price history\n\t\tconst pricesPath = path.join(outputDir, \"price_history.json\");\n\t\tawait fs.writeFile(\n\t\t\tpricesPath,\n\t\t\tJSON.stringify(Array.from(result.priceHistory.entries()), null, 2),\n\t\t);\n\n\t\t// Save performance summary\n\t\tconst perfPath = path.join(outputDir, \"actor_performance.json\");\n\t\tawait fs.writeFile(\n\t\t\tperfPath,\n\t\t\tJSON.stringify(Array.from(result.actorPerformance.entries()), null, 2),\n\t\t);\n\n\t\tconsole.log(`📁 Results cached to ${outputDir}`);\n\t}\n\n\tasync loadCachedSimulation(\n\t\toutputDir: string,\n\t): Promise<SimulationResult | null> {\n\t\ttry {\n\t\t\tconst callsData = await fs.readFile(\n\t\t\t\tpath.join(outputDir, \"simulated_calls.json\"),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tconst tokensData = await fs.readFile(\n\t\t\t\tpath.join(outputDir, \"simulated_tokens.json\"),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tconst pricesData = await fs.readFile(\n\t\t\t\tpath.join(outputDir, \"price_history.json\"),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t\tconst perfData = await fs.readFile(\n\t\t\t\tpath.join(outputDir, \"actor_performance.json\"),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tcalls: JSON.parse(callsData),\n\t\t\t\ttokens: new Map(JSON.parse(tokensData)),\n\t\t\t\tpriceHistory: new Map(JSON.parse(pricesData)),\n\t\t\t\tactorPerformance: new Map(JSON.parse(perfData)),\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to load cached simulation:\", error);\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"],"mappings":"AAAA,YAAY,QAAQ;AACpB,YAAY,UAAU;AAEtB,SAAS,MAAM,cAAc;AAC7B,SAAS,YAAY,sBAAsB;AAE3C;AAAA,EAEC;AAAA,OACM;AAGA,IAAK,gBAAL,kBAAKA,mBAAL;AACN,EAAAA,eAAA,mBAAgB;AAChB,EAAAA,eAAA,mBAAgB;AAChB,EAAAA,eAAA,gBAAa;AACb,EAAAA,eAAA,iBAAc;AACd,EAAAA,eAAA,mBAAgB;AAChB,EAAAA,eAAA,gBAAa;AACb,EAAAA,eAAA,cAAW;AACX,EAAAA,eAAA,cAAW;AACX,EAAAA,eAAA,eAAY;AACZ,EAAAA,eAAA,mBAAgB;AAChB,EAAAA,eAAA,gBAAa;AAXF,SAAAA;AAAA,GAAA;AAsHL,MAAM,iBAAiB;AAAA,EACrB;AAAA,EAER,cAAc;AACb,SAAK,eAAe,IAAI,uBAAuB;AAAA,EAChD;AAAA,EAEA,MAAM,cAAc,QAAqD;AACxE,YAAQ,IAAI,uDAAgD;AAG5D,UAAM,QAA6B,CAAC;AACpC,UAAM,SAAS,oBAAI,IAA6B;AAChD,UAAM,eAAe,oBAAI,IAA0B;AACnD,UAAM,mBAAmB,oBAAI,IAQ3B;AAGF,eAAW,SAAS,OAAO,QAAQ;AAElC,YAAM,kBAAoC;AAAA,QACzC,IAAI,MAAM;AAAA,QACV,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,YAAY,MAAM;AAAA,QAClB,aAAa,CAAC;AAAA,QACd,aAAa;AAAA,UACZ,oBAAoB,KAAK,mBAAmB,MAAM,gBAAgB;AAAA,UAClE,eAAe,MAAM;AAAA,UACrB,YAAY,MAAM;AAAA,QACnB;AAAA,MACD;AAEA,uBAAiB,IAAI,MAAM,IAAI;AAAA,QAC9B,YAAY;AAAA,QACZ,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,eAAe;AAAA,MAChB,CAAC;AAAA,IACF;AAGA,UAAM,kBAAkB,KAAK,eAAe,MAAM;AAClD,eAAW,SAAS,iBAAiB;AACpC,aAAO,IAAI,MAAM,SAAS,KAAK;AAC/B,mBAAa,IAAI,MAAM,SAAS,CAAC,CAAC;AAAA,IACnC;AAGA,QAAI,cAAc,IAAI,KAAK,OAAO,SAAS;AAC3C,UAAM,UAAU,IAAI,KAAK,OAAO,OAAO;AACvC,QAAI,YAAY;AAEhB,WAAO,eAAe,SAAS;AAC9B;AAGA,iBAAW,CAAC,SAAS,KAAK,KAAK,QAAQ;AACtC,cAAM,mBACJ,YAAY,QAAQ,IAAI,MAAM,WAAW,QAAQ,MACjD,MAAO,KAAK;AAEd,YAAI,mBAAmB,GAAG;AACzB,gBAAM,QAAQ,KAAK,oBAAoB,OAAO,eAAe;AAE7D,uBAAa,IAAI,OAAO,GAAG,KAAK;AAAA,YAC/B,WAAW;AAAA,YACX,OAAO,MAAM;AAAA,YACb,QAAQ,MAAM;AAAA,YACd,WAAW,MAAM;AAAA,YACjB,WAAW,MAAM;AAAA,UAClB,CAAC;AAAA,QACF;AAAA,MACD;AAGA,YAAM,YAAY,KAAK;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,YAAM,KAAK,GAAG,SAAS;AAGvB,oBAAc,IAAI;AAAA,QACjB,YAAY,QAAQ,IAAI,OAAO,kBAAkB,KAAK;AAAA,MACvD;AAAA,IACD;AAEA,YAAQ;AAAA,MACP,+BAA0B,SAAS,gBAAgB,MAAM,MAAM;AAAA,IAChE;AAGA,UAAM,KAAK,uBAAuB,OAAO,QAAQ,YAAY;AAG7D,eAAW,QAAQ,OAAO;AACzB,YAAM,OAAO,iBAAiB,IAAI,KAAK,MAAM;AAC7C,UAAI,CAAC,KAAM;AACX,WAAK;AAEL,UACC,KAAK,mBAAmB,gBACxB,KAAK,mBAAmB,eAAe,GACtC;AACD,aAAK;AAAA,MACN;AAEA,WAAK,eAAe,KAAK,mBAAmB,gBAAgB;AAAA,IAC7D;AAGA,eAAW,CAAC,UAAU,IAAI,KAAK,kBAAkB;AAChD,WAAK,gBACJ,KAAK,aAAa,IAAI,KAAK,cAAc,KAAK,aAAa;AAAA,IAC7D;AAEA,UAAM,SAA2B;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAGA,QAAI,OAAO,cAAc;AACxB,YAAM,KAAK,aAAa,QAAQ,MAAM;AAAA,IACvC;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,oBACP,OACA,kBACa;AAEb,QAAI,QAAQ,MAAM;AAClB,QAAI,MAAM,iBAAiB;AAE1B,YAAM,OAAO,KAAK,MAAM,mBAAmB,EAAE;AAC7C,cAAQ,MAAM,gBAAgB,IAAI;AAAA,IACnC;AAGA,UAAM,aAAa,QAAQ,MAAM;AACjC,UAAM,YAAY,MAAM,mBAAmB;AAC3C,UAAM,YAAY,MAAM,mBAAmB,KAAK,KAAK,UAAU;AAC/D,UAAM,SAAS,YAAY,OAAO,IAAI,KAAK,OAAO,IAAI;AAEtD,WAAO;AAAA,MACN,WAAW,oBAAI,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,mBACP,WACmC;AACnC,UAAM,UAAiE;AAAA,MACtE,CAAC,8BAA2B,GAAG;AAAA,MAC/B,CAAC,8BAA2B,GAAG;AAAA,MAC/B,CAAC,uBAAwB,GAAG;AAAA,MAC5B,CAAC,+BAAyB,GAAG;AAAA,MAC7B,CAAC,mCAA2B,GAAG;AAAA,MAC/B,CAAC,6BAAwB,GAAG;AAAA,MAC5B,CAAC,yBAAsB,GAAG;AAAA,MAC1B,CAAC,yBAAsB,GAAG;AAAA,MAC1B,CAAC,0BAAuB,GAAG;AAAA,MAC3B,CAAC,+BAA2B,GAAG;AAAA,MAC/B,CAAC,6BAAwB,GAAG;AAAA,IAC7B;AAEA,WAAO,UAAU,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC;AAAA,EACvC;AAAA,EAEQ,eAAe,QAA6C;AACnE,UAAM,SAA4B,CAAC;AAGnC,UAAM,eAAe,OAAO,6BAA6B;AAAA,MACxD,CAAC,8BAA2B,GAAG;AAAA,MAC/B,CAAC,8BAA2B,GAAG;AAAA,MAC/B,CAAC,uBAAwB,GAAG;AAAA,MAC5B,CAAC,+BAA2B,GAAG;AAAA,MAC/B,CAAC,yBAAsB,GAAG;AAAA,MAC1B,CAAC,6BAAwB,GAAG;AAAA,MAC5B,CAAC,+BAAyB,GAAG;AAAA,MAC7B,CAAC,0BAAuB,GAAG;AAAA,MAC3B,CAAC,6BAAwB,GAAG;AAAA,IAC7B;AAGA,aAAS,IAAI,GAAG,IAAI,OAAO,YAAY,KAAK;AAC3C,YAAM,WAAW,KAAK,uBAAuB,YAAY;AACzD,YAAM,QAAQ,KAAK,YAAY,UAAU,GAAG,MAAM;AAClD,aAAO,KAAK,KAAK;AAAA,IAClB;AAEA,YAAQ;AAAA,MACP,uBAAgB,OAAO,MAAM;AAAA,MAC7B,OAAO;AAAA,QACN,CAAC,KAAK,MAAM;AACX,cAAI,EAAE,QAAQ,KAAK,IAAI,EAAE,QAAQ,KAAK,KAAK;AAC3C,iBAAO;AAAA,QACR;AAAA,QACA,CAAC;AAAA,MACF;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,uBACP,cACgB;AAChB,UAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,UAAM,cAAc,QAAQ,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,MAAM,MAAM,QAAQ,CAAC;AACxE,QAAI,SAAS,KAAK,OAAO,IAAI;AAE7B,eAAW,CAAC,UAAU,MAAM,KAAK,SAAS;AACzC,gBAAU;AACV,UAAI,UAAU,GAAG;AAChB,eAAO;AAAA,MACR;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,YACP,UACA,OACA,QACkB;AAElB,UAAM,eAAe,OAAO,QAAQ,QAAQ,IAAI,OAAO,UAAU,QAAQ;AACzE,UAAM,eAAe,KAAK,OAAO,IAAI,eAAe;AAGpD,UAAM,iBAAiB,KAAK,kBAAkB,QAAQ;AACtD,UAAM,mBACL,KAAK,aAAa,wBAAwB,cAAc;AAEzD,WAAO;AAAA,MACN,SAAS,KAAK,OAAO,EAAE,QAAQ,MAAM,EAAE,CAAC,GAAG,MAAM,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,MAC5E,QAAQ,MAAM,SAAS,UAAU,GAAG,CAAC,EAAE,YAAY,CAAC,GAAG,KAAK;AAAA,MAC5D,MAAM,aAAa,SAAS,QAAQ,MAAM,GAAG,CAAC,UAAU,KAAK;AAAA,MAC7D;AAAA,MACA,YAAY,IAAI,KAAK,OAAO,UAAU,QAAQ,IAAI,YAAY;AAAA,MAC9D,cAAc,OAAU,KAAK,OAAO,IAAI;AAAA;AAAA,MACxC,kBAAkB,MAAQ,KAAK,OAAO,IAAI;AAAA;AAAA,MAC1C,kBAAkB,MAAO,KAAK,OAAO,IAAI;AAAA;AAAA,MACzC,iBAAiB,iBAAiB;AAAA,IACnC;AAAA,EACD;AAAA,EAEQ,kBAAkB,UAAiD;AAC1E,UAAM,UAAyD;AAAA,MAC9D,CAAC,8BAA2B,GAAG;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,WAAW;AAAA,MACZ;AAAA,MACA,CAAC,8BAA2B,GAAG;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,WAAW;AAAA,MACZ;AAAA,MACA,CAAC,uBAAwB,GAAG;AAAA,QAC3B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,+BAAyB,GAAG;AAAA,QAC5B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,mCAA2B,GAAG;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,6BAAwB,GAAG;AAAA,QAC3B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,yBAAsB,GAAG;AAAA,QACzB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,yBAAsB,GAAG;AAAA,QACzB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,0BAAuB,GAAG;AAAA,QAC1B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,MACA,CAAC,+BAA2B,GAAG;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,YAAY;AAAA,QACZ,YAAY;AAAA,MACb;AAAA,MACA,CAAC,6BAAwB,GAAG;AAAA,QAC3B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,QACd,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MACnB;AAAA,IACD;AAEA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA,EAEQ,yBACP,aACA,QACA,cACA,QACsB;AACtB,UAAM,QAA6B,CAAC;AAGpC,UAAM,eAAe,MAAM,KAAK,OAAO,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU;AAClE,YAAM,aAAa,MAAM,cAAc;AACvC,YAAM,UAAU,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACpD,YAAM,cAAc,QAAQ,QAAQ,SAAS,CAAC;AAC9C,YAAM,SACL,eAAe,YAAY,QAAQ,MAAM,eAAe;AAEzD,aAAO,cAAc,CAAC;AAAA,IACvB,CAAC;AAED,QAAI,aAAa,WAAW,EAAG,QAAO;AAGtC,eAAW,SAAS,OAAO,QAAQ;AAElC,YAAM,aAAa,KAAK,gBAAgB,OAAO,WAAW;AAC1D,UAAI,CAAC,WAAY;AAGjB,YAAM,eAAe,KAAK;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,iBAAW,SAAS,cAAc;AACjC,cAAM,oBAAoB,aAAa,IAAI,MAAM,OAAO;AACxD,YAAI,CAAC,kBAAmB;AACxB,cAAM,OAAO,KAAK;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAEA,YAAI,MAAM;AACT,gBAAM,KAAK,IAAI;AAAA,QAChB;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,gBAAgB,OAAoB,cAA6B;AAExE,UAAM,sBAAsB;AAAA,MAC3B,MAAM;AAAA;AAAA,MACN,QAAQ;AAAA;AAAA,MACR,KAAK;AAAA;AAAA,IACN,EAAE,MAAM,aAAa;AAErB,WAAO,KAAK,OAAO,IAAI;AAAA,EACxB;AAAA,EAEQ,qBACP,OACA,cACA,cACA,aACoB;AAEpB,QAAI,kBAAkB;AAGtB,QAAI,CAAC,iBAAiB,gBAAgB,EAAE,SAAS,MAAM,SAAS,GAAG;AAClE,wBAAkB,aAAa,OAAO,CAAC,UAAU;AAChD,cAAM,WAAW,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACrD,cAAM,mBACJ,YAAY,QAAQ,IAAI,MAAM,WAAW,QAAQ,MACjD,MAAO,KAAK;AAGd,YAAI,MAAM,cAAc,iBAAiB;AAExC,cACC;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,UACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AACD,mBAAO;AAAA,UACR;AAEA,iBACC,kBAAkB;AAAA,UAClB;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD,EAAE,SAAS,MAAM,QAAQ;AAAA,QAE3B,OAAO;AAEN,iBACC,kBAAkB;AAAA,UAClB,CAAC,CAAC,uBAAwB,EAAE,SAAS,MAAM,QAAQ;AAAA,QAErD;AAAA,MACD,CAAC;AAAA,IACF,WAGS,MAAM,cAAc,eAAe;AAC3C,wBAAkB,aAAa,OAAO,CAAC,UAAU;AAChD,cAAM,UAAU,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACpD,YAAI,QAAQ,SAAS,GAAI,QAAO;AAGhC,cAAM,aACL,QAAQ,QAAQ,SAAS,CAAC,EAAE,QAC3B,QAAQ,QAAQ,SAAS,EAAE,EAAE,QAC9B;AACD,eAAO,aAAa;AAAA,MACrB,CAAC;AAAA,IACF,WAGS,MAAM,cAAc,eAAe;AAC3C,wBAAkB,aAAa,OAAO,CAAC,UAAU;AAChD,cAAM,UAAU,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACpD,YAAI,QAAQ,SAAS,EAAG,QAAO;AAG/B,cAAM,aACL,QAAQ,QAAQ,SAAS,CAAC,EAAE,QAC3B,QAAQ,QAAQ,SAAS,CAAC,EAAE,QAC7B;AACD,eAAO,aAAa;AAAA,MACrB,CAAC;AAAA,IACF,WAGS,MAAM,cAAc,gBAAgB;AAC5C,wBAAkB,aAAa;AAAA,QAC9B,CAAC,UACA,MAAM,iBAAiB,SAAS,MAAM,QAAQ,KAC9C,MAAM,aAAa;AAAA;AAAA,MACrB;AAAA,IACD;AAGA,QAAI,gBAAgB,WAAW,GAAG;AACjC,wBAAkB,aAAa;AAAA,QAAO,CAAC,UACtC,MAAM,iBAAiB,SAAS,MAAM,QAAQ;AAAA,MAC/C;AAAA,IACD;AAEA,QAAI,gBAAgB,WAAW,EAAG,QAAO,CAAC;AAG1C,UAAM,cAAc,gBAAgB,OAAO,CAAC,UAAU;AACrD,YAAM,WAAW,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACrD,YAAM,mBACJ,YAAY,QAAQ,IAAI,MAAM,WAAW,QAAQ,MAAM,MAAO,KAAK;AAErE,cAAQ,MAAM,YAAY;AAAA,QACzB,KAAK;AACJ,iBAAO,kBAAkB;AAAA;AAAA,QAC1B,KAAK;AACJ,iBAAO,mBAAmB,MAAM,kBAAkB;AAAA;AAAA,QACnD,KAAK;AACJ,iBAAO,mBAAmB;AAAA;AAAA,QAC3B;AACC,iBAAO;AAAA,MACT;AAAA,IACD,CAAC;AAED,UAAM,cAAc,YAAY,SAAS,IAAI,cAAc;AAG3D,UAAM,YAAY,MAAM,cAAc,kBAAkB,IAAI;AAC5D,UAAM,YAAY,KAAK;AAAA,MACtB,YAAY;AAAA,MACZ,KAAK,MAAM,KAAK,OAAO,IAAI,SAAS,IAAI;AAAA,IACzC;AAEA,WAAO,YAAY,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG,EAAE,MAAM,GAAG,SAAS;AAAA,EACtE;AAAA,EAEQ,kBACP,OACA,OACA,cACA,aAC2B;AAC3B,UAAM,cAAc,aAAa,aAAa,SAAS,CAAC;AACxD,QAAI,CAAC,YAAa,QAAO;AAGzB,UAAM,UAAU,KAAK;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA;AAAA,IACD;AAEA,QAAI,CAAC,QAAS,QAAO;AAGrB,UAAM,YAAY,KAAK,wBAAwB,OAAO,OAAO,YAAY;AAGzE,UAAM,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,WAAO;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,mBAAmB,WAAW,OAAO,CAAC;AAAA,MACtC,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM;AAAA,MAChB,WAAW,YAAY,QAAQ;AAAA,MAC/B,SAAS;AAAA,MACT,gBAAgB,MAAM;AAAA,MACtB,eAAe,MAAM;AAAA,MACrB,aAAa,MAAM;AAAA,MACnB,OAAO,eAAe;AAAA,MACtB;AAAA,MACA;AAAA,MACA,cAAc,GAAG,MAAM,QAAQ,KAAK,MAAM,SAAS,eAAe,MAAM,MAAM;AAAA,MAC9E,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,oBAAoB;AAAA,QACnB,eAAe,MAAM;AAAA,QACrB,gBAAgB,MAAM;AAAA,QACtB,aAAa,YAAY;AAAA,QACzB,iBAAiB,YAAY;AAAA,QAC7B,iBAAiB,YAAY;AAAA,QAC7B,iBAAiB,KAAK,eAAe,OAAO,KAAK;AAAA,MAClD;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,gBACP,OACA,aACA,WACA,YACS;AAET,UAAM,YAAwD;AAAA,MAC7D,eAAe;AAAA,QACd,IAAI,WAAW;AAAA,QACf,qBAAqB,WAAW;AAAA,MACjC;AAAA,MACA,gBAAgB;AAAA,QACf,IAAI,WAAW;AAAA,QACf,yBAAyB,WAAW;AAAA,MACrC;AAAA,MACA,aAAa;AAAA,QACZ,IAAI,WAAW;AAAA,QACf,cAAc,WAAW;AAAA,MAC1B;AAAA,MACA,cAAc;AAAA,QACb,uBAAS,WAAW;AAAA,QACpB,IAAI,WAAW;AAAA,MAChB;AAAA,MACA,aAAa;AAAA,QACZ,oBAAoB,WAAW;AAAA,QAC/B,IAAI,WAAW;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,QACX,IAAI,WAAW;AAAA,QACf,gCAAgC,WAAW;AAAA,MAC5C;AAAA,MACA,mBAAmB;AAAA,QAClB,IAAI,WAAW;AAAA,QACf,oBAAoB,WAAW;AAAA,MAChC;AAAA,MACA,QAAQ;AAAA,QACP,OAAO,WAAW;AAAA,QAClB,yBAAyB,WAAW;AAAA,MACrC;AAAA,MACA,aAAa;AAAA,QACZ,cAAO,WAAW;AAAA,QAClB,IAAI,WAAW,KAAK,WAAW,KAAK,WAAW;AAAA,MAChD;AAAA,IACD;AAEA,UAAM,qBAAqB,UAAU,MAAM,SAAS;AACpD,WAAO,mBACN,KAAK,MAAM,KAAK,OAAO,IAAI,mBAAmB,MAAM,CACrD;AAAA,EACD;AAAA,EAEQ,wBACP,OACA,OACA,cACsC;AAEtC,QAAI,MAAM,cAAc,iBAAiB;AAExC,UACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AACD,eAAO;AAAA,MACR;AAEA,UACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AACD,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AAGA,QAAI,MAAM,cAAc,kBAAkB;AACzC,UACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AACD,eAAO;AAAA,MACR;AACA,UACC,CAAC,gCAA6B,uBAAwB,EAAE;AAAA,QACvD,MAAM;AAAA,MACP,GACC;AACD,eAAO,KAAK,OAAO,IAAI,MAAM,aAAa;AAAA,MAC3C;AACA,UAAI,MAAM,aAAa,iCAA6B;AAEnD,cAAM,kBAAkB,aAAa;AACrC,eAAO,kBAAkB,IAAI,aAAa;AAAA,MAC3C;AACA,aAAO;AAAA,IACR;AAGA,QAAI,MAAM,cAAc,gBAAgB;AACvC,UACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AACD,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AAGA,QAAI,MAAM,cAAc,eAAe;AACtC,aAAO;AAAA,IACR;AAGA,QAAI,MAAM,cAAc,eAAe;AACtC,YAAM,cACL,aAAa,SAAS,IACnB,aAAa,aAAa,SAAS,CAAC,EAAE,QACtC,aAAa,aAAa,SAAS,CAAC,EAAE,QACvC,IACC;AACJ,aAAO,cAAc,MAAM,aAAa;AAAA,IACzC;AAGA,QAAI,MAAM,cAAc,cAAc;AACrC,YAAM,cACL,aAAa,SAAS,KACnB,aAAa,aAAa,SAAS,CAAC,EAAE,QACtC,aAAa,aAAa,SAAS,EAAE,EAAE,QACxC,IACC;AACJ,aAAO,cAAc,MAAM,aAAa;AAAA,IACzC;AAGA,WAAO,MAAM,iBAAiB,SAAS,MAAM,QAAQ,IAClD,aACA;AAAA,EACJ;AAAA,EAEQ,yBACP,OACA,QACA,cACa;AAEb,UAAM,iBACL;AAAA,MACC,eAAe,WAAW;AAAA,MAC1B,gBAAgB,WAAW;AAAA,MAC3B,aAAa,WAAW;AAAA,MACxB,cAAc,WAAW;AAAA,MACzB,aAAa,WAAW;AAAA,MACxB,YAAY,WAAW;AAAA,MACvB,mBAAmB,WAAW;AAAA,MAC9B,QAAQ,WAAW;AAAA,MACnB,aAAa,WAAW;AAAA,IACzB,EAAE,MAAM,SAAS,KAAK,WAAW;AAGlC,QAAI,CAAC,eAAe,aAAa,EAAE,SAAS,MAAM,SAAS,GAAG;AAC7D,YAAM,aACL,aAAa,SAAS,IACnB,aAAa,aAAa,SAAS,CAAC,EAAE,QACtC,aAAa,aAAa,SAAS,CAAC,EAAE,QACvC,IACC;AAEJ,UAAI,aAAa,KAAK;AACrB,eAAO,WAAW;AAAA,MACnB;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,eACP,OACA,OACgC;AAEhC,UAAM,sBAAsB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,UAAM,cAAc,oBAAoB,SAAS,MAAM,QAAQ;AAC/D,UAAM,YAAY;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IACD,EAAE,SAAS,MAAM,SAAS;AAE1B,QAAI,aAAa,YAAa,QAAO;AACrC,QAAI,CAAC,aAAa,CAAC,YAAa,QAAO;AACvC,QAAI,MAAM,cAAc,kBAAkB,CAAC,YAAa,QAAO;AAE/D,WAAO;AAAA,EACR;AAAA,EAEQ,uBACP,OACA,QACA,cACgB;AAChB,eAAW,QAAQ,OAAO;AACzB,YAAM,QAAQ,OAAO,IAAI,KAAK,eAAe,EAAE;AAC/C,UAAI,CAAC,MAAO;AAEZ,YAAM,UAAU,aAAa,IAAI,MAAM,OAAO,KAAK,CAAC;AACpD,YAAM,YAAY,QAAQ;AAAA,QACzB,CAAC,MAAM,EAAE,UAAU,QAAQ,MAAM,KAAK;AAAA,MACvC;AAEA,UAAI,cAAc,MAAM,cAAc,QAAQ,SAAS,GAAG;AACzD,aAAK,mBAAmB,eAAe;AACvC;AAAA,MACD;AAGA,UAAI,KAAK,cAAc,YAAY;AAClC,cAAMC,cAAa,QAAQ,SAAS,EAAE;AACtC,cAAMC,aAAY,KAAK,IAAI,YAAY,IAAI,QAAQ,SAAS,CAAC;AAC7D,cAAMC,aAAY,QAAQD,UAAS,EAAE;AAGrC,cAAM,oBAAqBD,cAAaE,cAAaF,cAAc;AACnE,aAAK,mBAAmB,eAAe;AACvC;AAAA,MACD;AAGA,UAAI;AACJ,UAAI,aAAa;AAGjB,UACC;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AAED,YAAI,WAAW;AACf,iBAAS,IAAI,YAAY,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACpD,cAAI,QAAQ,CAAC,EAAE,QAAQ,QAAQ,SAAS,EAAE,QAAQ,KAAK;AAEtD,uBAAW;AACX,yBAAa;AACb;AAAA,UACD;AAAA,QACD;AACA,oBAAY;AAAA,MACb,WAAW,MAAM,aAAa,iCAA6B;AAE1D,YAAI,YAAY;AAChB,YAAI,YAAY,QAAQ,SAAS,EAAE;AACnC,iBAAS,IAAI,YAAY,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACpD,cAAI,QAAQ,CAAC,EAAE,QAAQ,WAAW;AACjC,wBAAY,QAAQ,CAAC,EAAE;AAAA,UACxB,WAAW,QAAQ,CAAC,EAAE,QAAQ,YAAY,KAAK;AAE9C,wBAAY;AACZ,yBAAa;AACb;AAAA,UACD;AAAA,QACD;AACA,oBAAY;AAAA,MACb,OAAO;AAEN,YAAI,KAAK,mBAAmB,mBAAmB,iBAAiB;AAE/D,sBAAY,KAAK,IAAI,YAAY,IAAI,QAAQ,SAAS,CAAC;AAAA,QACxD,WACC,KAAK,mBAAmB,mBAAmB,kBAC1C;AAED,sBAAY,KAAK,IAAI,YAAY,IAAI,QAAQ,SAAS,CAAC;AAAA,QACxD,WACC,CAAC,eAAe,aAAa,EAAE;AAAA,UAC9B,KAAK,mBAAmB;AAAA,QACzB,GACC;AAED,sBAAY,KAAK,IAAI,YAAY,IAAI,QAAQ,SAAS,CAAC;AAAA,QACxD,OAAO;AAEN,sBAAY,KAAK,IAAI,YAAY,IAAI,QAAQ,SAAS,CAAC;AAAA,QACxD;AAAA,MACD;AAEA,YAAM,aAAa,QAAQ,SAAS,EAAE;AACtC,YAAM,YAAY,QAAQ,SAAS,EAAE;AAGrC,UAAI,sBAAsB;AAE1B,UACC,CAAC,eAAe,aAAa,EAAE;AAAA,QAC9B,KAAK,mBAAmB;AAAA,MACzB,GACC;AAED,8BAAsB,aAAa;AAAA,MACpC,WAAW,KAAK,mBAAmB,mBAAmB,gBAAgB;AAErE,YACC;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,QACD,EAAE,SAAS,MAAM,QAAQ,GACxB;AAED,gCAAsB,aAAa;AAAA,QACpC;AAAA,MACD,WAAW,KAAK,mBAAmB,mBAAmB,iBAAiB;AAEtE,8BAAsB,aAAa;AAAA,MACpC;AAGA,UAAI,qBAAqB;AACzB,UACC,cACA,CAAC,eAAe,eAAe,cAAc,EAAE;AAAA,QAC9C,KAAK,mBAAmB;AAAA,MACzB,GACC;AACD,6BAAqB,YAAY;AAAA,MAClC;AAEA,YAAM,iBACH,qBAAqB,uBAAuB,sBAC9C;AAED,WAAK,mBAAmB,eAAe;AAAA,IACxC;AAEA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAc,aACb,QACA,QACgB;AAChB,UAAM,YAAY,OAAO;AACzB,UAAM,GAAG,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAG7C,UAAM,YAAY,KAAK,KAAK,WAAW,sBAAsB;AAC7D,UAAM,GAAG,UAAU,WAAW,KAAK,UAAU,OAAO,OAAO,MAAM,CAAC,CAAC;AAGnE,UAAM,aAAa,KAAK,KAAK,WAAW,uBAAuB;AAC/D,UAAM,GAAG;AAAA,MACR;AAAA,MACA,KAAK,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,IAC5D;AAGA,UAAM,aAAa,KAAK,KAAK,WAAW,oBAAoB;AAC5D,UAAM,GAAG;AAAA,MACR;AAAA,MACA,KAAK,UAAU,MAAM,KAAK,OAAO,aAAa,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,IAClE;AAGA,UAAM,WAAW,KAAK,KAAK,WAAW,wBAAwB;AAC9D,UAAM,GAAG;AAAA,MACR;AAAA,MACA,KAAK,UAAU,MAAM,KAAK,OAAO,iBAAiB,QAAQ,CAAC,GAAG,MAAM,CAAC;AAAA,IACtE;AAEA,YAAQ,IAAI,+BAAwB,SAAS,EAAE;AAAA,EAChD;AAAA,EAEA,MAAM,qBACL,WACmC;AACnC,QAAI;AACH,YAAM,YAAY,MAAM,GAAG;AAAA,QAC1B,KAAK,KAAK,WAAW,sBAAsB;AAAA,QAC3C;AAAA,MACD;AACA,YAAM,aAAa,MAAM,GAAG;AAAA,QAC3B,KAAK,KAAK,WAAW,uBAAuB;AAAA,QAC5C;AAAA,MACD;AACA,YAAM,aAAa,MAAM,GAAG;AAAA,QAC3B,KAAK,KAAK,WAAW,oBAAoB;AAAA,QACzC;AAAA,MACD;AACA,YAAM,WAAW,MAAM,GAAG;AAAA,QACzB,KAAK,KAAK,WAAW,wBAAwB;AAAA,QAC7C;AAAA,MACD;AAEA,aAAO;AAAA,QACN,OAAO,KAAK,MAAM,SAAS;AAAA,QAC3B,QAAQ,IAAI,IAAI,KAAK,MAAM,UAAU,CAAC;AAAA,QACtC,cAAc,IAAI,IAAI,KAAK,MAAM,UAAU,CAAC;AAAA,QAC5C,kBAAkB,IAAI,IAAI,KAAK,MAAM,QAAQ,CAAC;AAAA,MAC/C;AAAA,IACD,SAAS,OAAO;AACf,cAAQ,MAAM,qCAAqC,KAAK;AACxD,aAAO;AAAA,IACR;AAAA,EACD;AACD;","names":["TokenScenario","entryPrice","exitIndex","exitPrice"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type SimulatedToken } from "../mockPriceService";
|
|
2
|
+
export interface TokenScenario {
|
|
3
|
+
type: "rug" | "scam" | "runner" | "successful" | "mediocre" | "stagnant" | "bluechip" | "pump_dump" | "slow_bleed";
|
|
4
|
+
name: string;
|
|
5
|
+
symbol: string;
|
|
6
|
+
description: string;
|
|
7
|
+
initialPrice: number;
|
|
8
|
+
initialLiquidity: number;
|
|
9
|
+
initialMarketCap: number;
|
|
10
|
+
rugTiming?: number;
|
|
11
|
+
pumpTiming?: number;
|
|
12
|
+
dumpTiming?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class TokenSimulationService {
|
|
15
|
+
private scenarios;
|
|
16
|
+
constructor();
|
|
17
|
+
private initializeScenarios;
|
|
18
|
+
private addScenario;
|
|
19
|
+
createTokenFromScenario(scenario: TokenScenario): SimulatedToken;
|
|
20
|
+
private mapScenarioToPerformanceType;
|
|
21
|
+
private createRugTrajectory;
|
|
22
|
+
private createScamTrajectory;
|
|
23
|
+
private createRunnerTrajectory;
|
|
24
|
+
private createSuccessfulTrajectory;
|
|
25
|
+
private createMediocreTrajectory;
|
|
26
|
+
private createStagnantTrajectory;
|
|
27
|
+
private createBluechipTrajectory;
|
|
28
|
+
private createPumpDumpTrajectory;
|
|
29
|
+
private createSlowBleedTrajectory;
|
|
30
|
+
getAllScenarios(): TokenScenario[];
|
|
31
|
+
getScenarioBySymbol(symbol: string): TokenScenario | undefined;
|
|
32
|
+
generateDiverseTokenSet(): SimulatedToken[];
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=tokenSimulationService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenSimulationService.d.ts","sourceRoot":"","sources":["../../src/services/tokenSimulationService.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG5E,MAAM,WAAW,aAAa;IAC7B,IAAI,EACD,KAAK,GACL,MAAM,GACN,QAAQ,GACR,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GACX,YAAY,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,sBAAsB;IAClC,OAAO,CAAC,SAAS,CAAyC;;IAM1D,OAAO,CAAC,mBAAmB;IA6H3B,OAAO,CAAC,WAAW;IAInB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,GAAG,cAAc;IAoDhE,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,wBAAwB;IAwBhC,OAAO,CAAC,yBAAyB;IAejC,eAAe,IAAI,aAAa,EAAE;IAIlC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,uBAAuB,IAAI,cAAc,EAAE;CA2B3C"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from "uuid";
|
|
2
|
+
import { MockPriceService } from "../mockPriceService.js";
|
|
3
|
+
import { SupportedChain } from "../types.js";
|
|
4
|
+
class TokenSimulationService {
|
|
5
|
+
scenarios = /* @__PURE__ */ new Map();
|
|
6
|
+
constructor() {
|
|
7
|
+
this.initializeScenarios();
|
|
8
|
+
}
|
|
9
|
+
initializeScenarios() {
|
|
10
|
+
this.addScenario({
|
|
11
|
+
type: "rug",
|
|
12
|
+
name: "FastRug Token",
|
|
13
|
+
symbol: "FRUG",
|
|
14
|
+
description: "Rugs within 2 days of launch",
|
|
15
|
+
initialPrice: 1e-5,
|
|
16
|
+
initialLiquidity: 5e3,
|
|
17
|
+
initialMarketCap: 1e4,
|
|
18
|
+
rugTiming: 2
|
|
19
|
+
});
|
|
20
|
+
this.addScenario({
|
|
21
|
+
type: "rug",
|
|
22
|
+
name: "SlowRug Token",
|
|
23
|
+
symbol: "SRUG",
|
|
24
|
+
description: "Builds trust then rugs after 10 days",
|
|
25
|
+
initialPrice: 5e-5,
|
|
26
|
+
initialLiquidity: 2e4,
|
|
27
|
+
initialMarketCap: 5e4,
|
|
28
|
+
rugTiming: 10
|
|
29
|
+
});
|
|
30
|
+
this.addScenario({
|
|
31
|
+
type: "scam",
|
|
32
|
+
name: "LowLiq Scam",
|
|
33
|
+
symbol: "SCAM",
|
|
34
|
+
description: "Very low liquidity, manipulated price",
|
|
35
|
+
initialPrice: 1e-3,
|
|
36
|
+
initialLiquidity: 500,
|
|
37
|
+
// Very low
|
|
38
|
+
initialMarketCap: 5e3
|
|
39
|
+
});
|
|
40
|
+
this.addScenario({
|
|
41
|
+
type: "runner",
|
|
42
|
+
name: "MoonShot Token",
|
|
43
|
+
symbol: "MOON",
|
|
44
|
+
description: "Legitimate project with 50x growth",
|
|
45
|
+
initialPrice: 1e-5,
|
|
46
|
+
initialLiquidity: 5e4,
|
|
47
|
+
initialMarketCap: 1e5
|
|
48
|
+
});
|
|
49
|
+
this.addScenario({
|
|
50
|
+
type: "runner",
|
|
51
|
+
name: "SteadyGains Token",
|
|
52
|
+
symbol: "GAIN",
|
|
53
|
+
description: "Consistent 10x growth over time",
|
|
54
|
+
initialPrice: 1e-4,
|
|
55
|
+
initialLiquidity: 3e4,
|
|
56
|
+
initialMarketCap: 2e5
|
|
57
|
+
});
|
|
58
|
+
this.addScenario({
|
|
59
|
+
type: "successful",
|
|
60
|
+
name: "SolidProject Token",
|
|
61
|
+
symbol: "SOLID",
|
|
62
|
+
description: "Good project with 3x growth",
|
|
63
|
+
initialPrice: 1e-3,
|
|
64
|
+
initialLiquidity: 1e5,
|
|
65
|
+
initialMarketCap: 5e5
|
|
66
|
+
});
|
|
67
|
+
this.addScenario({
|
|
68
|
+
type: "mediocre",
|
|
69
|
+
name: "CrabWalk Token",
|
|
70
|
+
symbol: "CRAB",
|
|
71
|
+
description: "Goes sideways with minor fluctuations",
|
|
72
|
+
initialPrice: 0.01,
|
|
73
|
+
initialLiquidity: 5e4,
|
|
74
|
+
initialMarketCap: 3e5
|
|
75
|
+
});
|
|
76
|
+
this.addScenario({
|
|
77
|
+
type: "stagnant",
|
|
78
|
+
name: "DeadProject Token",
|
|
79
|
+
symbol: "DEAD",
|
|
80
|
+
description: "No volume, slowly dying",
|
|
81
|
+
initialPrice: 5e-3,
|
|
82
|
+
initialLiquidity: 1e4,
|
|
83
|
+
initialMarketCap: 5e4
|
|
84
|
+
});
|
|
85
|
+
this.addScenario({
|
|
86
|
+
type: "bluechip",
|
|
87
|
+
name: "Established Token",
|
|
88
|
+
symbol: "BLUE",
|
|
89
|
+
description: "Already successful, stable growth",
|
|
90
|
+
initialPrice: 10,
|
|
91
|
+
initialLiquidity: 5e6,
|
|
92
|
+
initialMarketCap: 1e8
|
|
93
|
+
});
|
|
94
|
+
this.addScenario({
|
|
95
|
+
type: "pump_dump",
|
|
96
|
+
name: "PumpDump Token",
|
|
97
|
+
symbol: "PUMP",
|
|
98
|
+
description: "Pumps 20x then dumps 95%",
|
|
99
|
+
initialPrice: 1e-5,
|
|
100
|
+
initialLiquidity: 15e3,
|
|
101
|
+
initialMarketCap: 2e4,
|
|
102
|
+
pumpTiming: 3,
|
|
103
|
+
dumpTiming: 5
|
|
104
|
+
});
|
|
105
|
+
this.addScenario({
|
|
106
|
+
type: "slow_bleed",
|
|
107
|
+
name: "BleedOut Token",
|
|
108
|
+
symbol: "BLEED",
|
|
109
|
+
description: "Slowly loses value over time",
|
|
110
|
+
initialPrice: 0.01,
|
|
111
|
+
initialLiquidity: 4e4,
|
|
112
|
+
initialMarketCap: 2e5
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
addScenario(scenario) {
|
|
116
|
+
this.scenarios.set(scenario.symbol, scenario);
|
|
117
|
+
}
|
|
118
|
+
createTokenFromScenario(scenario) {
|
|
119
|
+
const address = `${scenario.symbol}${uuidv4().substring(0, 8)}`;
|
|
120
|
+
let priceTrajectory;
|
|
121
|
+
switch (scenario.type) {
|
|
122
|
+
case "rug":
|
|
123
|
+
priceTrajectory = this.createRugTrajectory(scenario);
|
|
124
|
+
break;
|
|
125
|
+
case "scam":
|
|
126
|
+
priceTrajectory = this.createScamTrajectory(scenario);
|
|
127
|
+
break;
|
|
128
|
+
case "runner":
|
|
129
|
+
priceTrajectory = this.createRunnerTrajectory(scenario);
|
|
130
|
+
break;
|
|
131
|
+
case "successful":
|
|
132
|
+
priceTrajectory = this.createSuccessfulTrajectory(scenario);
|
|
133
|
+
break;
|
|
134
|
+
case "mediocre":
|
|
135
|
+
priceTrajectory = this.createMediocreTrajectory(scenario);
|
|
136
|
+
break;
|
|
137
|
+
case "stagnant":
|
|
138
|
+
priceTrajectory = this.createStagnantTrajectory(scenario);
|
|
139
|
+
break;
|
|
140
|
+
case "bluechip":
|
|
141
|
+
priceTrajectory = this.createBluechipTrajectory(scenario);
|
|
142
|
+
break;
|
|
143
|
+
case "pump_dump":
|
|
144
|
+
priceTrajectory = this.createPumpDumpTrajectory(scenario);
|
|
145
|
+
break;
|
|
146
|
+
case "slow_bleed":
|
|
147
|
+
priceTrajectory = this.createSlowBleedTrajectory(scenario);
|
|
148
|
+
break;
|
|
149
|
+
default:
|
|
150
|
+
priceTrajectory = MockPriceService.neutralTokenTrajectory(
|
|
151
|
+
scenario.initialPrice
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
address,
|
|
156
|
+
symbol: scenario.symbol,
|
|
157
|
+
name: scenario.name,
|
|
158
|
+
chain: SupportedChain.SOLANA,
|
|
159
|
+
performanceType: this.mapScenarioToPerformanceType(scenario.type),
|
|
160
|
+
priceTrajectory,
|
|
161
|
+
initialPrice: scenario.initialPrice,
|
|
162
|
+
liquidity: scenario.initialLiquidity,
|
|
163
|
+
marketCap: scenario.initialMarketCap
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
mapScenarioToPerformanceType(type) {
|
|
167
|
+
switch (type) {
|
|
168
|
+
case "rug":
|
|
169
|
+
case "scam":
|
|
170
|
+
case "pump_dump":
|
|
171
|
+
case "slow_bleed":
|
|
172
|
+
return "bad";
|
|
173
|
+
case "runner":
|
|
174
|
+
case "successful":
|
|
175
|
+
case "bluechip":
|
|
176
|
+
return "good";
|
|
177
|
+
default:
|
|
178
|
+
return "neutral";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
createRugTrajectory(scenario) {
|
|
182
|
+
const { rugTiming } = scenario;
|
|
183
|
+
if (rugTiming === void 0) {
|
|
184
|
+
throw new Error("Rug scenario requires rugTiming");
|
|
185
|
+
}
|
|
186
|
+
return (step) => {
|
|
187
|
+
if (step < rugTiming) {
|
|
188
|
+
return scenario.initialPrice * 1.5 ** step;
|
|
189
|
+
} else {
|
|
190
|
+
return scenario.initialPrice * 1e-3;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
createScamTrajectory(scenario) {
|
|
195
|
+
return (step) => {
|
|
196
|
+
const volatility = 0.5;
|
|
197
|
+
const trend = -0.1;
|
|
198
|
+
const random = (Math.random() - 0.5) * volatility;
|
|
199
|
+
return scenario.initialPrice * (1 + trend + random) ** step;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
createRunnerTrajectory(scenario) {
|
|
203
|
+
return (step) => {
|
|
204
|
+
const baseGrowth = scenario.symbol === "MOON" ? 0.15 : 0.08;
|
|
205
|
+
const consolidationPeriod = 5;
|
|
206
|
+
const isConsolidating = step % consolidationPeriod < 2;
|
|
207
|
+
const growth = isConsolidating ? 0 : baseGrowth;
|
|
208
|
+
const minorVolatility = (Math.random() - 0.5) * 0.1;
|
|
209
|
+
return scenario.initialPrice * (1 + growth + minorVolatility) ** step;
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
createSuccessfulTrajectory(scenario) {
|
|
213
|
+
return (step) => {
|
|
214
|
+
const growth = 0.03;
|
|
215
|
+
const volatility = 0.05;
|
|
216
|
+
const random = (Math.random() - 0.5) * volatility;
|
|
217
|
+
return scenario.initialPrice * (1 + growth + random) ** step;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
createMediocreTrajectory(scenario) {
|
|
221
|
+
return (_step) => {
|
|
222
|
+
const volatility = 0.1;
|
|
223
|
+
const random = (Math.random() - 0.5) * volatility;
|
|
224
|
+
return scenario.initialPrice * (1 + random);
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
createStagnantTrajectory(scenario) {
|
|
228
|
+
return (step) => {
|
|
229
|
+
const decay = -0.02;
|
|
230
|
+
const decreasedVolatility = 0.02 * Math.exp(-step * 0.1);
|
|
231
|
+
const random = (Math.random() - 0.5) * decreasedVolatility;
|
|
232
|
+
return scenario.initialPrice * (1 + decay + random) ** step;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
createBluechipTrajectory(scenario) {
|
|
236
|
+
return (step) => {
|
|
237
|
+
const growth = 0.01;
|
|
238
|
+
const lowVolatility = 0.03;
|
|
239
|
+
const random = (Math.random() - 0.5) * lowVolatility;
|
|
240
|
+
return scenario.initialPrice * (1 + growth + random) ** step;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
createPumpDumpTrajectory(scenario) {
|
|
244
|
+
const { pumpTiming, dumpTiming } = scenario;
|
|
245
|
+
if (pumpTiming === void 0 || dumpTiming === void 0) {
|
|
246
|
+
throw new Error("Pump/dump scenario requires pumpTiming and dumpTiming");
|
|
247
|
+
}
|
|
248
|
+
return (step) => {
|
|
249
|
+
if (step < pumpTiming) {
|
|
250
|
+
return scenario.initialPrice * (1 + (Math.random() - 0.5) * 0.1);
|
|
251
|
+
} else if (step >= pumpTiming && step < dumpTiming) {
|
|
252
|
+
const pumpStep = step - pumpTiming + 1;
|
|
253
|
+
return scenario.initialPrice * 5 ** pumpStep;
|
|
254
|
+
} else {
|
|
255
|
+
const peakPrice = scenario.initialPrice * 5 ** (dumpTiming - pumpTiming);
|
|
256
|
+
return peakPrice * 0.05;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
createSlowBleedTrajectory(scenario) {
|
|
261
|
+
return (step) => {
|
|
262
|
+
const baseDecline = -0.03;
|
|
263
|
+
const rallyChance = 0.2;
|
|
264
|
+
const isRally = Math.random() < rallyChance;
|
|
265
|
+
const movement = isRally ? 0.05 : baseDecline;
|
|
266
|
+
const volatility = 0.05;
|
|
267
|
+
const random = (Math.random() - 0.5) * volatility;
|
|
268
|
+
return scenario.initialPrice * (1 + movement + random) ** step;
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
getAllScenarios() {
|
|
272
|
+
return Array.from(this.scenarios.values());
|
|
273
|
+
}
|
|
274
|
+
getScenarioBySymbol(symbol) {
|
|
275
|
+
return this.scenarios.get(symbol);
|
|
276
|
+
}
|
|
277
|
+
generateDiverseTokenSet() {
|
|
278
|
+
const tokens = [];
|
|
279
|
+
for (const scenario of this.scenarios.values()) {
|
|
280
|
+
const instances = scenario.type === "bluechip" ? 1 : Math.floor(Math.random() * 3) + 1;
|
|
281
|
+
for (let i = 0; i < instances; i++) {
|
|
282
|
+
const token = this.createTokenFromScenario(scenario);
|
|
283
|
+
if (i > 0) {
|
|
284
|
+
token.initialPrice *= 0.5 + Math.random();
|
|
285
|
+
token.liquidity = token.liquidity ? token.liquidity * (0.5 + Math.random()) : void 0;
|
|
286
|
+
token.marketCap = token.marketCap ? token.marketCap * (0.5 + Math.random()) : void 0;
|
|
287
|
+
}
|
|
288
|
+
tokens.push(token);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return tokens;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
export {
|
|
295
|
+
TokenSimulationService
|
|
296
|
+
};
|
|
297
|
+
//# sourceMappingURL=tokenSimulationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/services/tokenSimulationService.ts"],"sourcesContent":["import { v4 as uuidv4 } from \"uuid\";\nimport { MockPriceService, type SimulatedToken } from \"../mockPriceService.js\";\nimport { SupportedChain } from \"../types.js\";\n\nexport interface TokenScenario {\n\ttype:\n\t\t| \"rug\"\n\t\t| \"scam\"\n\t\t| \"runner\"\n\t\t| \"successful\"\n\t\t| \"mediocre\"\n\t\t| \"stagnant\"\n\t\t| \"bluechip\"\n\t\t| \"pump_dump\"\n\t\t| \"slow_bleed\";\n\tname: string;\n\tsymbol: string;\n\tdescription: string;\n\tinitialPrice: number;\n\tinitialLiquidity: number;\n\tinitialMarketCap: number;\n\trugTiming?: number; // Step when rug happens\n\tpumpTiming?: number; // Step when pump happens\n\tdumpTiming?: number; // Step when dump happens\n}\n\nexport class TokenSimulationService {\n\tprivate scenarios: Map<string, TokenScenario> = new Map();\n\n\tconstructor() {\n\t\tthis.initializeScenarios();\n\t}\n\n\tprivate initializeScenarios() {\n\t\t// Rug pulls - different timings\n\t\tthis.addScenario({\n\t\t\ttype: \"rug\",\n\t\t\tname: \"FastRug Token\",\n\t\t\tsymbol: \"FRUG\",\n\t\t\tdescription: \"Rugs within 2 days of launch\",\n\t\t\tinitialPrice: 0.00001,\n\t\t\tinitialLiquidity: 5000,\n\t\t\tinitialMarketCap: 10000,\n\t\t\trugTiming: 2,\n\t\t});\n\n\t\tthis.addScenario({\n\t\t\ttype: \"rug\",\n\t\t\tname: \"SlowRug Token\",\n\t\t\tsymbol: \"SRUG\",\n\t\t\tdescription: \"Builds trust then rugs after 10 days\",\n\t\t\tinitialPrice: 0.00005,\n\t\t\tinitialLiquidity: 20000,\n\t\t\tinitialMarketCap: 50000,\n\t\t\trugTiming: 10,\n\t\t});\n\n\t\t// Scams - low liquidity, suspicious patterns\n\t\tthis.addScenario({\n\t\t\ttype: \"scam\",\n\t\t\tname: \"LowLiq Scam\",\n\t\t\tsymbol: \"SCAM\",\n\t\t\tdescription: \"Very low liquidity, manipulated price\",\n\t\t\tinitialPrice: 0.001,\n\t\t\tinitialLiquidity: 500, // Very low\n\t\t\tinitialMarketCap: 5000,\n\t\t});\n\n\t\t// Runners - sustained growth\n\t\tthis.addScenario({\n\t\t\ttype: \"runner\",\n\t\t\tname: \"MoonShot Token\",\n\t\t\tsymbol: \"MOON\",\n\t\t\tdescription: \"Legitimate project with 50x growth\",\n\t\t\tinitialPrice: 0.00001,\n\t\t\tinitialLiquidity: 50000,\n\t\t\tinitialMarketCap: 100000,\n\t\t});\n\n\t\tthis.addScenario({\n\t\t\ttype: \"runner\",\n\t\t\tname: \"SteadyGains Token\",\n\t\t\tsymbol: \"GAIN\",\n\t\t\tdescription: \"Consistent 10x growth over time\",\n\t\t\tinitialPrice: 0.0001,\n\t\t\tinitialLiquidity: 30000,\n\t\t\tinitialMarketCap: 200000,\n\t\t});\n\n\t\t// Successful but not runners\n\t\tthis.addScenario({\n\t\t\ttype: \"successful\",\n\t\t\tname: \"SolidProject Token\",\n\t\t\tsymbol: \"SOLID\",\n\t\t\tdescription: \"Good project with 3x growth\",\n\t\t\tinitialPrice: 0.001,\n\t\t\tinitialLiquidity: 100000,\n\t\t\tinitialMarketCap: 500000,\n\t\t});\n\n\t\t// Mediocre - sideways movement\n\t\tthis.addScenario({\n\t\t\ttype: \"mediocre\",\n\t\t\tname: \"CrabWalk Token\",\n\t\t\tsymbol: \"CRAB\",\n\t\t\tdescription: \"Goes sideways with minor fluctuations\",\n\t\t\tinitialPrice: 0.01,\n\t\t\tinitialLiquidity: 50000,\n\t\t\tinitialMarketCap: 300000,\n\t\t});\n\n\t\t// Stagnant - no volume, dying\n\t\tthis.addScenario({\n\t\t\ttype: \"stagnant\",\n\t\t\tname: \"DeadProject Token\",\n\t\t\tsymbol: \"DEAD\",\n\t\t\tdescription: \"No volume, slowly dying\",\n\t\t\tinitialPrice: 0.005,\n\t\t\tinitialLiquidity: 10000,\n\t\t\tinitialMarketCap: 50000,\n\t\t});\n\n\t\t// Blue chip - already established\n\t\tthis.addScenario({\n\t\t\ttype: \"bluechip\",\n\t\t\tname: \"Established Token\",\n\t\t\tsymbol: \"BLUE\",\n\t\t\tdescription: \"Already successful, stable growth\",\n\t\t\tinitialPrice: 10.0,\n\t\t\tinitialLiquidity: 5000000,\n\t\t\tinitialMarketCap: 100000000,\n\t\t});\n\n\t\t// Pump and dump\n\t\tthis.addScenario({\n\t\t\ttype: \"pump_dump\",\n\t\t\tname: \"PumpDump Token\",\n\t\t\tsymbol: \"PUMP\",\n\t\t\tdescription: \"Pumps 20x then dumps 95%\",\n\t\t\tinitialPrice: 0.00001,\n\t\t\tinitialLiquidity: 15000,\n\t\t\tinitialMarketCap: 20000,\n\t\t\tpumpTiming: 3,\n\t\t\tdumpTiming: 5,\n\t\t});\n\n\t\t// Slow bleed\n\t\tthis.addScenario({\n\t\t\ttype: \"slow_bleed\",\n\t\t\tname: \"BleedOut Token\",\n\t\t\tsymbol: \"BLEED\",\n\t\t\tdescription: \"Slowly loses value over time\",\n\t\t\tinitialPrice: 0.01,\n\t\t\tinitialLiquidity: 40000,\n\t\t\tinitialMarketCap: 200000,\n\t\t});\n\t}\n\n\tprivate addScenario(scenario: TokenScenario) {\n\t\tthis.scenarios.set(scenario.symbol, scenario);\n\t}\n\n\tcreateTokenFromScenario(scenario: TokenScenario): SimulatedToken {\n\t\tconst address = `${scenario.symbol}${uuidv4().substring(0, 8)}`;\n\n\t\tlet priceTrajectory: (step: number) => number;\n\n\t\tswitch (scenario.type) {\n\t\t\tcase \"rug\":\n\t\t\t\tpriceTrajectory = this.createRugTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"scam\":\n\t\t\t\tpriceTrajectory = this.createScamTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"runner\":\n\t\t\t\tpriceTrajectory = this.createRunnerTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"successful\":\n\t\t\t\tpriceTrajectory = this.createSuccessfulTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"mediocre\":\n\t\t\t\tpriceTrajectory = this.createMediocreTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"stagnant\":\n\t\t\t\tpriceTrajectory = this.createStagnantTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"bluechip\":\n\t\t\t\tpriceTrajectory = this.createBluechipTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"pump_dump\":\n\t\t\t\tpriceTrajectory = this.createPumpDumpTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tcase \"slow_bleed\":\n\t\t\t\tpriceTrajectory = this.createSlowBleedTrajectory(scenario);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tpriceTrajectory = MockPriceService.neutralTokenTrajectory(\n\t\t\t\t\tscenario.initialPrice,\n\t\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\taddress,\n\t\t\tsymbol: scenario.symbol,\n\t\t\tname: scenario.name,\n\t\t\tchain: SupportedChain.SOLANA,\n\t\t\tperformanceType: this.mapScenarioToPerformanceType(scenario.type),\n\t\t\tpriceTrajectory,\n\t\t\tinitialPrice: scenario.initialPrice,\n\t\t\tliquidity: scenario.initialLiquidity,\n\t\t\tmarketCap: scenario.initialMarketCap,\n\t\t};\n\t}\n\n\tprivate mapScenarioToPerformanceType(\n\t\ttype: TokenScenario[\"type\"],\n\t): SimulatedToken[\"performanceType\"] {\n\t\tswitch (type) {\n\t\t\tcase \"rug\":\n\t\t\tcase \"scam\":\n\t\t\tcase \"pump_dump\":\n\t\t\tcase \"slow_bleed\":\n\t\t\t\treturn \"bad\";\n\t\t\tcase \"runner\":\n\t\t\tcase \"successful\":\n\t\t\tcase \"bluechip\":\n\t\t\t\treturn \"good\";\n\t\t\tdefault:\n\t\t\t\treturn \"neutral\";\n\t\t}\n\t}\n\n\tprivate createRugTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\tconst { rugTiming } = scenario;\n\t\tif (rugTiming === undefined) {\n\t\t\tthrow new Error(\"Rug scenario requires rugTiming\");\n\t\t}\n\t\treturn (step: number) => {\n\t\t\tif (step < rugTiming) {\n\t\t\t\t// Price increases before rug to build trust\n\t\t\t\treturn scenario.initialPrice * 1.5 ** step;\n\t\t\t} else {\n\t\t\t\t// Rug pull - price drops to near zero\n\t\t\t\treturn scenario.initialPrice * 0.001;\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate createScamTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Highly volatile with overall downward trend\n\t\t\tconst volatility = 0.5;\n\t\t\tconst trend = -0.1;\n\t\t\tconst random = (Math.random() - 0.5) * volatility;\n\t\t\treturn scenario.initialPrice * (1 + trend + random) ** step;\n\t\t};\n\t}\n\n\tprivate createRunnerTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Strong upward trend with some consolidation\n\t\t\tconst baseGrowth = scenario.symbol === \"MOON\" ? 0.15 : 0.08;\n\t\t\tconst consolidationPeriod = 5;\n\t\t\tconst isConsolidating = step % consolidationPeriod < 2;\n\t\t\tconst growth = isConsolidating ? 0 : baseGrowth;\n\t\t\tconst minorVolatility = (Math.random() - 0.5) * 0.1;\n\t\t\treturn scenario.initialPrice * (1 + growth + minorVolatility) ** step;\n\t\t};\n\t}\n\n\tprivate createSuccessfulTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Moderate growth with stability\n\t\t\tconst growth = 0.03;\n\t\t\tconst volatility = 0.05;\n\t\t\tconst random = (Math.random() - 0.5) * volatility;\n\t\t\treturn scenario.initialPrice * (1 + growth + random) ** step;\n\t\t};\n\t}\n\n\tprivate createMediocreTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (_step: number) => {\n\t\t\t// Sideways movement\n\t\t\tconst volatility = 0.1;\n\t\t\tconst random = (Math.random() - 0.5) * volatility;\n\t\t\treturn scenario.initialPrice * (1 + random);\n\t\t};\n\t}\n\n\tprivate createStagnantTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Slow death with decreasing volume (reflected in price decline)\n\t\t\tconst decay = -0.02;\n\t\t\tconst decreasedVolatility = 0.02 * Math.exp(-step * 0.1); // Volatility decreases over time\n\t\t\tconst random = (Math.random() - 0.5) * decreasedVolatility;\n\t\t\treturn scenario.initialPrice * (1 + decay + random) ** step;\n\t\t};\n\t}\n\n\tprivate createBluechipTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Stable with minor growth\n\t\t\tconst growth = 0.01;\n\t\t\tconst lowVolatility = 0.03;\n\t\t\tconst random = (Math.random() - 0.5) * lowVolatility;\n\t\t\treturn scenario.initialPrice * (1 + growth + random) ** step;\n\t\t};\n\t}\n\n\tprivate createPumpDumpTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\tconst { pumpTiming, dumpTiming } = scenario;\n\t\tif (pumpTiming === undefined || dumpTiming === undefined) {\n\t\t\tthrow new Error(\"Pump/dump scenario requires pumpTiming and dumpTiming\");\n\t\t}\n\t\treturn (step: number) => {\n\t\t\tif (step < pumpTiming) {\n\t\t\t\t// Normal trading\n\t\t\t\treturn scenario.initialPrice * (1 + (Math.random() - 0.5) * 0.1);\n\t\t\t} else if (step >= pumpTiming && step < dumpTiming) {\n\t\t\t\t// Pump phase\n\t\t\t\tconst pumpStep = step - pumpTiming + 1;\n\t\t\t\treturn scenario.initialPrice * 5 ** pumpStep;\n\t\t\t} else {\n\t\t\t\t// Dump phase - lose 95% of peak value\n\t\t\t\tconst peakPrice =\n\t\t\t\t\tscenario.initialPrice * 5 ** (dumpTiming - pumpTiming);\n\t\t\t\treturn peakPrice * 0.05;\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate createSlowBleedTrajectory(\n\t\tscenario: TokenScenario,\n\t): (step: number) => number {\n\t\treturn (step: number) => {\n\t\t\t// Consistent decline with false hope rallies\n\t\t\tconst baseDecline = -0.03;\n\t\t\tconst rallyChance = 0.2;\n\t\t\tconst isRally = Math.random() < rallyChance;\n\t\t\tconst movement = isRally ? 0.05 : baseDecline;\n\t\t\tconst volatility = 0.05;\n\t\t\tconst random = (Math.random() - 0.5) * volatility;\n\t\t\treturn scenario.initialPrice * (1 + movement + random) ** step;\n\t\t};\n\t}\n\n\tgetAllScenarios(): TokenScenario[] {\n\t\treturn Array.from(this.scenarios.values());\n\t}\n\n\tgetScenarioBySymbol(symbol: string): TokenScenario | undefined {\n\t\treturn this.scenarios.get(symbol);\n\t}\n\n\tgenerateDiverseTokenSet(): SimulatedToken[] {\n\t\tconst tokens: SimulatedToken[] = [];\n\n\t\t// Generate multiple instances of each scenario type\n\t\tfor (const scenario of this.scenarios.values()) {\n\t\t\t// Create 1-3 instances of each scenario type\n\t\t\tconst instances =\n\t\t\t\tscenario.type === \"bluechip\" ? 1 : Math.floor(Math.random() * 3) + 1;\n\n\t\t\tfor (let i = 0; i < instances; i++) {\n\t\t\t\tconst token = this.createTokenFromScenario(scenario);\n\t\t\t\t// Add some variation to the initial parameters\n\t\t\t\tif (i > 0) {\n\t\t\t\t\ttoken.initialPrice *= 0.5 + Math.random();\n\t\t\t\t\ttoken.liquidity = token.liquidity\n\t\t\t\t\t\t? token.liquidity * (0.5 + Math.random())\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\ttoken.marketCap = token.marketCap\n\t\t\t\t\t\t? token.marketCap * (0.5 + Math.random())\n\t\t\t\t\t\t: undefined;\n\t\t\t\t}\n\t\t\t\ttokens.push(token);\n\t\t\t}\n\t\t}\n\n\t\treturn tokens;\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { type SimulationConfig, type SimulationResult } from "./simulationRunner";
|
|
2
|
+
export interface TrustScoreResult {
|
|
3
|
+
userId: string;
|
|
4
|
+
username: string;
|
|
5
|
+
calculatedScore: number;
|
|
6
|
+
expectedScore: number;
|
|
7
|
+
difference: number;
|
|
8
|
+
metrics: {
|
|
9
|
+
totalCalls: number;
|
|
10
|
+
profitableCalls: number;
|
|
11
|
+
averageProfit: number;
|
|
12
|
+
winRate: number;
|
|
13
|
+
sharpeRatio: number;
|
|
14
|
+
alpha: number;
|
|
15
|
+
volumePenalty: number;
|
|
16
|
+
consistency: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface OptimizationResult {
|
|
20
|
+
scores: TrustScoreResult[];
|
|
21
|
+
accuracy: {
|
|
22
|
+
mae: number;
|
|
23
|
+
rmse: number;
|
|
24
|
+
correlation: number;
|
|
25
|
+
rankingAccuracy: number;
|
|
26
|
+
};
|
|
27
|
+
suggestions: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface TrustScoreParameters {
|
|
30
|
+
profitWeight: number;
|
|
31
|
+
consistencyWeight: number;
|
|
32
|
+
volumeWeight: number;
|
|
33
|
+
alphaWeight: number;
|
|
34
|
+
sharpeWeight: number;
|
|
35
|
+
minCallsThreshold: number;
|
|
36
|
+
volumePenaltyThreshold: number;
|
|
37
|
+
timeDecayFactor: number;
|
|
38
|
+
rugPullPenalty: number;
|
|
39
|
+
}
|
|
40
|
+
export declare class TrustScoreOptimizer {
|
|
41
|
+
private simulationRunner;
|
|
42
|
+
private currentParams;
|
|
43
|
+
private balancedCalculator;
|
|
44
|
+
constructor();
|
|
45
|
+
/**
|
|
46
|
+
* Run a full optimization cycle
|
|
47
|
+
*/
|
|
48
|
+
runOptimizationCycle(simulationConfig?: SimulationConfig, useCache?: boolean): Promise<OptimizationResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Get simulation data, either from cache or by running new simulation
|
|
51
|
+
*/
|
|
52
|
+
private getSimulationData;
|
|
53
|
+
/**
|
|
54
|
+
* Create default set of actors for testing
|
|
55
|
+
*/
|
|
56
|
+
private createDefaultActors;
|
|
57
|
+
/**
|
|
58
|
+
* Calculate detailed metrics for an actor
|
|
59
|
+
*/
|
|
60
|
+
private calculateMetrics;
|
|
61
|
+
/**
|
|
62
|
+
* Calculate Sharpe ratio
|
|
63
|
+
*/
|
|
64
|
+
private calculateSharpeRatio;
|
|
65
|
+
/**
|
|
66
|
+
* Calculate market return (average of all token performances)
|
|
67
|
+
*/
|
|
68
|
+
private calculateMarketReturn;
|
|
69
|
+
/**
|
|
70
|
+
* Calculate consistency score
|
|
71
|
+
*/
|
|
72
|
+
private calculateConsistency;
|
|
73
|
+
/**
|
|
74
|
+
* Final optimized trust score calculation
|
|
75
|
+
*/
|
|
76
|
+
calculateFinalTrustScore(metrics: TrustScoreResult["metrics"], archetype?: string, rugPromotionPenalty?: number, goodCallBonus?: number): number;
|
|
77
|
+
/**
|
|
78
|
+
* Enhanced trust score calculation with token quality consideration
|
|
79
|
+
*/
|
|
80
|
+
calculateTrustScoresEnhanced(simulationData: SimulationResult): Promise<TrustScoreResult[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Evaluate accuracy of calculated scores vs expected
|
|
83
|
+
*/
|
|
84
|
+
private evaluateAccuracy;
|
|
85
|
+
/**
|
|
86
|
+
* Calculate Pearson correlation coefficient
|
|
87
|
+
*/
|
|
88
|
+
private calculateCorrelation;
|
|
89
|
+
/**
|
|
90
|
+
* Calculate ranking accuracy (% of correctly ordered pairs)
|
|
91
|
+
*/
|
|
92
|
+
private calculateRankingAccuracy;
|
|
93
|
+
/**
|
|
94
|
+
* Generate optimization suggestions based on results
|
|
95
|
+
*/
|
|
96
|
+
private generateSuggestions;
|
|
97
|
+
/**
|
|
98
|
+
* Log detailed results
|
|
99
|
+
*/
|
|
100
|
+
private logResults;
|
|
101
|
+
/**
|
|
102
|
+
* Grid search for optimal parameters
|
|
103
|
+
*/
|
|
104
|
+
optimizeParameters(parameterRanges: Partial<Record<keyof TrustScoreParameters, number[]>>, simulationConfig?: SimulationConfig): Promise<TrustScoreParameters>;
|
|
105
|
+
/**
|
|
106
|
+
* Generate all combinations of parameters for grid search
|
|
107
|
+
*/
|
|
108
|
+
private generateParameterCombinations;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=trustScoreOptimizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustScoreOptimizer.d.ts","sourceRoot":"","sources":["../../src/services/trustScoreOptimizer.ts"],"names":[],"mappings":"AAIA,OAAO,EAGN,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACpB,CAAC;CACF;AAGD,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,QAAQ,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB;AAGD,MAAM,WAAW,oBAAoB;IAEpC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IAGrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,CAAC;IAG/B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,kBAAkB,CAA+B;;IAoBzD;;OAEG;IACG,oBAAoB,CACzB,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,QAAQ,GAAE,OAAc,GACtB,OAAO,CAAC,kBAAkB,CAAC;IA8B9B;;OAEG;YACW,iBAAiB;IAgC/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuH3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgDxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiB7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,wBAAwB,CACvB,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,EACpC,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,GAAE,MAAU,EAC/B,aAAa,GAAE,MAAU,GACvB,MAAM;IAgGT;;OAEG;IACG,4BAA4B,CACjC,cAAc,EAAE,gBAAgB,GAC9B,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA8E9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAyBhC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6G3B;;OAEG;YACW,UAAU;IAmDxB;;OAEG;IACG,kBAAkB,CACvB,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,oBAAoB,EAAE,MAAM,EAAE,CAAC,CAAC,EACtE,gBAAgB,CAAC,EAAE,gBAAgB,GACjC,OAAO,CAAC,oBAAoB,CAAC;IAsChC;;OAEG;IACH,OAAO,CAAC,6BAA6B;CA6BrC"}
|