@extends('adminlte::page') @section('title', 'Event Timeline') @section('css') @stop @section('content_header') @stop @section('content')

 Event Timeline — Gantt Chart

{{-- Date range picker --}}
Reset {{ count($days) }} days • {{ count($events) }} events
{{-- Legend --}}
@foreach([ ['weekly', 'Weekly'], ['monthly', 'Monthly'], ['purchase', 'Purchase'], ['spender', 'Spender'], ['guild', 'Guild'], ['top', 'Top Event'], ['stamina', 'Stamina'], ['chain', 'Chain'], ['server', 'Server'], ['trader', 'Trader'], ['config', 'Config'], ['announce', 'Announce'], ['other', 'Other'], ] as $leg) {{ $leg[1] }} @endforeach
@if(count($events) === 0)
No events found in this date range.
@else {{-- Gantt Chart --}} @php $today = date('Y-m-d'); $todayTs = strtotime($today); $totalDays = count($days); // Group days by month for header $months = []; foreach ($days as $day) { $m = substr($day, 0, 7); if (!isset($months[$m])) $months[$m] = 0; $months[$m]++; } // Category helper $weeklyEvt = ['EVENT_OPEN_ALL_CAVERN','EVENT_OPEN_ALL_DOJO','EVENT_MULTIPLY_CAVERN','EVENT_MULTIPLY_DOJO','EVENT_MULTIPLY_COF_GEM','EVENT_MULTIPLY_COF_ITEM','EVENT_GOBLIN_SHOP','EVENT_MULTIPLY_TREASURE_LAND','EVENT_SHOP_DISCOUNT','EVENT_USE_HERO_IN_ARENA']; $monthlyEvt = ['EVENT_MULTIPLY_EXP','EVENT_MULTIPLY_NORMAL_ITEM','ITEM_DROP_EVENT','EVENT_PURCHASE_PROMOTE']; $chainEvt = ['PURCHASE_STAMINA','EVENT_BUY_STAMINA_UNLIMITED','EVENT_MULTIPLY_HEROIC_SOUL_STONE','EVENT_MULTIPLY_HEROIC_ITEM']; $serverEvt = ['EVENT_MULTIPLY_HEROIC_ITEM','EVENT_MULTIPLY_HEROIC_SOUL_STONE','EVENT_MULTIPLY_NORMAL_ITEM','EVENT_PURCHASE_PROMOTE','ITEM_DROP_EVENT','ITEM_DROP_HALLOWEEN_EVENT','ITEM_DROP_TRUNGTHU_EVENT']; $traderEvt = ['EVENT_EXCHANGE_ITEM','EVENT_TRADER_DIAMOND','EVENT_TRADER_GOLD']; $configEvt = ['AUTO_SELL_EVENT_ITEMS','DAILY_REWARD_BONUS','EVENT_PURCHASE_BEGINER','EVENT_PURCHASE_HEROES','EVENT_PURCHASE_ITEMS','EVENT_PURCHASE_PACKAGE','EVENT_PURCHASE_SKIN','EVENT_USE_ADMOB','EVENT_VIP_REWARD','USE_ADDITION_STATS','USE_CHANGE_LOG','USE_CUSTOM_BAN_CHAT','USE_CUSTOM_HERO_ITEM','USE_CUSTOM_KEY_SERVER','USE_CUSTOM_PACKAGE','USE_VALIDATE_CLIENT','EVENT_BEGINER_PURCHASE','EVENT_BEGINER_SPENDER','EVENT_BUY_STAMINA_NEW','EVENT_GROWTH_FUND','EVENT_GROWTH_GEM','EVENT_SUMMON_SOULSTONE']; function getEventCategory($code, $weeklyEvt, $monthlyEvt, $chainEvt, $serverEvt, $traderEvt, $configEvt) { if (in_array($code, $weeklyEvt)) return 'weekly'; if (in_array($code, $monthlyEvt)) return 'monthly'; if (in_array($code, $chainEvt)) return 'chain'; if (strpos($code, 'EVENT_DIAMOND_BUY_') === 0) return 'purchase'; if (strpos($code, 'EVENT_DIAMOND_SPENDER') === 0) return 'spender'; if (strpos($code, 'EVENT_G_DIAMOND_') === 0) return 'guild'; if (in_array($code, ['EVENT_TOP_ARENA','EVENT_TOP_HOL_GUILD'])) return 'top'; if ($code === 'EVENT_MULTIPLY_EXP') return 'stamina'; if (strpos($code, 'EVENT_ANNOUNCE_') === 0) return 'announce'; if (in_array($code, $traderEvt)) return 'trader'; if (in_array($code, $serverEvt)) return 'server'; if (in_array($code, $configEvt)) return 'config'; return 'other'; } @endphp
{{-- Row 1: Month headers --}} @foreach($months as $month => $count) @endforeach {{-- Row 2: Day headers --}} @foreach($days as $day) @php $dow = date('N', strtotime($day)); $isToday = ($day === $today); $isWeekend = in_array($dow, [6,7]); $hdrClass = 'day-hdr' . ($isToday ? ' today-hdr' : ($isWeekend ? ' weekend-hdr' : '')); @endphp @endforeach @foreach($events as $event) @php $beginDay = date('Y-m-d', $event['begin_ts']); $endDay = date('Y-m-d', $event['end_ts']); // Skip events that don't overlap with the timeline range if ($beginDay > $days[$totalDays-1] || $endDay < $days[0]) continue; $cat = getEventCategory($event['code'], $weeklyEvt, $monthlyEvt, $chainEvt, $serverEvt, $traderEvt, $configEvt); // Clamp to visible range $clampedBegin = max($beginDay, $days[0]); $clampedEnd = min($endDay, $days[$totalDays-1]); // Find column indices $startIdx = array_search($clampedBegin, $days); $endIdx = array_search($clampedEnd, $days); if ($startIdx === false || $endIdx === false) continue; $barSpan = $endIdx - $startIdx + 1; $beforeCols = $startIdx; $afterCols = $totalDays - $endIdx - 1; $isStartClamped = ($beginDay < $days[0]); $isEndClamped = ($endDay > $days[$totalDays-1]); $barClass = 'gantt-bar cat-' . $cat; if (!$isStartClamped && !$isEndClamped) $barClass .= ' bar-both'; elseif (!$isStartClamped) $barClass .= ' bar-start'; elseif (!$isEndClamped) $barClass .= ' bar-end'; else $barClass .= ' bar-mid'; $isActive = (time() >= $event['begin_ts'] && time() <= $event['end_ts']); @endphp {{-- Empty cells before bar --}} @if($beforeCols > 0) @foreach($days as $i => $day) @if($i < $beforeCols) @php $dow = date('N', strtotime($day)); $isToday = ($day === $today); @endphp @endif @endforeach @endif {{-- Bar cell --}} {{-- Empty cells after bar --}} @if($afterCols > 0) @foreach($days as $i => $day) @if($i > $endIdx) @php $dow = date('N', strtotime($day)); $isToday = ($day === $today); @endphp @endif @endforeach @endif @endforeach
Event {{ date('M Y', strtotime($month . '-01')) }}
{{ date('d', strtotime($day)) }}
@if($isActive) @else @endif {{ $event['code'] }} @if($barSpan >= 3) {{ $event['code'] }} @elseif($barSpan == 2) {{ substr($event['code'], 0, 16) }} @else   @endif
@endif
@stop @section('js') @stop