this.getRetentionData(), 'engagementData' => this.getEngagementData(), 'segmentationData' => this.getSegmentationData(), 'funnelData' => this.getFunnelData(), 'ethicalMetrics' => this.getEthicalMetrics(), ]); } /** * Get retention metrics (D1/D7/D30) * * @return array{d1: float, d7: float, d30: float, trend: array} */ private function getRetentionData(): array { $retention = PlayerRetention::calculate( period: this.period, region: this.region, segment: this.segment ); return [ 'd1' => $retention->d1, 'd7' => $retention->d7, 'd30' => $retention->d30, 'trend' => $retention->trendArray(), ]; } /** * Get engagement metrics * * @return array{avg_session_minutes: float, sessions_per_day: float, feature_usage: array} */ private function getEngagementData(): array { return this.analyticsService->getEngagementMetrics( period: this.period, region: this.region ); } /** * Get player segmentation data * * Classification: - Whale: > $100/month - Dolphin: $20-100/month - Minnow: < $20/month - Free: $0 spending * * @return array{whales: int, dolphins: int, minnows: int, free: int} */ private function getSegmentationData(): array { return this.segmentationService->classifyPlayers( region: this.region, period: this.period ); } /** * Get engagement funnel data * * Funnel stages: 1. Install 2. First session 3. Day 1 retention 4. Day 7 retention 5. Day 30 retention 6. First purchase 7. Repeat purchase * * @return array{stages: array{name: string, count: int, rate: float}} */ private function getFunnelData(): array { return [ 'stages' => [ ['name' => 'Install', 'count' => Player::count(), 'rate' => 100.0], ['name' => 'First Session', 'count' => PlayerSession::count(), 'rate' => 95.0], ['name' => 'Day 1', 'count' => PlayerRetention::d1()->count(), 'rate' => 42.5], ['name' => 'Day 7', 'count' => PlayerRetention::d7()->count(), 'rate' => 25.0], ['name' => 'Day 30', 'count' => PlayerRetention::d30()->count(), 'rate' => 15.0], ['name' => 'First Purchase', 'count' => Player::paid()->count(), 'rate' => 8.0], ['name' => 'Repeat Purchase', 'count' => Player::repeatPurchasers()->count(), 'rate' => 4.0], ], ]; } /** * Get ethical engagement metrics * * Includes: - Spending limit compliance - Loot table transparency status - Rest-state mechanics usage * * @return array{spending_limit_users: int, loot_transparency_enabled: bool, rest_state_avg: float} */ private function getEthicalMetrics(): array { return [ 'spending_limit_users' => Player::withSpendingLimits()->count(), 'loot_transparency_enabled' => \App\Models\LootTable::allTransparent(), 'rest_state_avg' => Player::avgOfflineRegeneration(), ]; } /** * Update period filter * * @param string $newPeriod New period (7d, 30d, 90d) */ public function updatePeriod(string $newPeriod): void { this.period = $newPeriod; } /** * Update segment filter * * @param string $newSegment New segment (whale, dolphin, minnow, free) */ public function updateSegment(string $newSegment): void { this.segment = $newSegment; } /** * Export analytics data * * @return \Symfony\Component\HttpFoundation\BinaryFileResponse */ public function export(): \Symfony\Component\HttpFoundation\BinaryFileResponse { $data = [ 'retention' => this.getRetentionData(), 'engagement' => this.getEngagementData(), 'segmentation' => this.getSegmentationData(), 'funnel' => this.getFunnelData(), 'ethical' => this.getEthicalMetrics(), ]; return response()->json($data, 200, [ 'Content-Disposition' => 'attachment; filename=analytics-' . this.period . '.json', ]); } /** * Refresh analytics via polling * * @return array{retention: array, engagement: array} */ public function refresh(): array { return [ 'retention' => this.getRetentionData(), 'engagement' => this.getEngagementData(), ]; } }