', $lastProcessedId) ->orderBy('id') ->limit($this->maxRecords / 2) // 分配一半给收获日志 ->get() ->map(function ($log) { $log->log_type = 'harvest'; return $log; }); // 收集升级日志 $upgradeLogs = FarmUpgradeLog::where('id', '>', $lastProcessedId) ->orderBy('id') ->limit($this->maxRecords / 2) // 分配一半给升级日志 ->get() ->map(function ($log) { $log->log_type = 'upgrade'; return $log; }); // 合并并按ID排序 return $harvestLogs->concat($upgradeLogs)->sortBy('id'); } /** * 按时间获取新的记录 * * @param int $lastProcessedTimestamp 上次处理的最大时间戳 * @return \Illuminate\Database\Eloquent\Collection */ protected function getNewRecordsByTime(int $lastProcessedTimestamp) { $lastTime = date('Y-m-d H:i:s', $lastProcessedTimestamp); // 收集收获日志 $harvestLogs = FarmHarvestLog::where('created_at', '>', $lastTime) ->orderBy('created_at') ->orderBy('id') ->limit($this->maxRecords / 2) // 分配一半给收获日志 ->get() ->map(function ($log) { $log->log_type = 'harvest'; return $log; }); // 收集升级日志 $upgradeLogs = FarmUpgradeLog::where('created_at', '>', $lastTime) ->orderBy('created_at') ->orderBy('id') ->limit($this->maxRecords / 2) // 分配一半给升级日志 ->get() ->map(function ($log) { $log->log_type = 'upgrade'; return $log; }); // 合并并按时间排序 return $harvestLogs->concat($upgradeLogs)->sortBy(['created_at', 'id']); } /** * 获取记录的时间戳 * * @param mixed $record 农场日志记录 * @return int 时间戳 */ protected function getRecordTimestamp($record): int { return strtotime($record->created_at); } /** * 根据记录ID获取原始记录的时间戳 * 由于农场收集器处理多个表,需要特殊处理 * * @param int $recordId 记录ID * @return int 时间戳 */ protected function getOriginalRecordTimestamp(int $recordId): int { try { // 先尝试从收获日志表查找 $harvestRecord = FarmHarvestLog::find($recordId); if ($harvestRecord) { return strtotime($harvestRecord->created_at); } // 再尝试从升级日志表查找 $upgradeRecord = FarmUpgradeLog::find($recordId); if ($upgradeRecord) { return strtotime($upgradeRecord->created_at); } return 0; } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error("获取农场日志原始时间戳失败", [ 'record_id' => $recordId, 'error' => $e->getMessage() ]); return 0; } } /** * 转换记录为用户日志数据 * * @param mixed $record 农场日志记录 * @return array|null 用户日志数据,null表示跳过 */ protected function convertToUserLog($record): ?array { try { if ($record->log_type === 'harvest') { return $this->convertHarvestLog($record); } elseif ($record->log_type === 'upgrade') { return $this->convertUpgradeLog($record); } return null; } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error("转换农场日志失败", [ 'record_id' => $record->id, 'log_type' => $record->log_type ?? 'unknown', 'error' => $e->getMessage() ]); return null; } } /** * 转换收获日志 * * @param FarmHarvestLog $record * @return array|null */ private function convertHarvestLog(FarmHarvestLog $record): ?array { // 获取作物名称 $cropName = $this->getCropName($record->seed_id); // 构建收获消息 $message = "收获{$record->land_id}号土地的{$cropName}"; // 添加收获数量信息 if ($record->harvest_quantity > 0) { $message .= ",获得{$record->harvest_quantity}个"; } // 添加经验信息 if ($record->exp_gained > 0) { $message .= ",获得经验{$record->exp_gained}"; } return $this->createUserLogData( $record->user_id, $message, $record->id, $record->created_at ); } /** * 转换升级日志 * * @param FarmUpgradeLog $record * @return array|null */ private function convertUpgradeLog(FarmUpgradeLog $record): ?array { $message = $this->buildUpgradeMessage($record); return $this->createUserLogData( $record->user_id, $message, $record->id, $record->created_at ); } /** * 构建升级消息 * * @param FarmUpgradeLog $record * @return string */ private function buildUpgradeMessage(FarmUpgradeLog $record): string { // 使用UPGRADE_TYPE枚举判断升级类型 switch ($record->upgrade_type) { case \App\Module\Farm\Enums\UPGRADE_TYPE::HOUSE->value: return "房屋升级到{$record->new_level}级"; case \App\Module\Farm\Enums\UPGRADE_TYPE::LAND->value: $oldLandType = $this->getLandTypeName($record->old_level); $newLandType = $this->getLandTypeName($record->new_level); return "土地{$record->target_id}从{$oldLandType}升级为{$newLandType}"; default: return "升级类型{$record->upgrade_type}从{$record->old_level}级升级到{$record->new_level}级"; } } /** * 获取作物名称 * * @param int $seedId 种子ID * @return string */ private function getCropName(int $seedId): string { try { // 尝试从配置中获取种子信息 $seedConfig = \App\Module\Farm\Models\FarmSeed::find($seedId); if ($seedConfig) { return $seedConfig->name; } return "作物{$seedId}"; } catch (\Exception $e) { return "作物{$seedId}"; } } /** * 静态缓存:土地类型名称映射 * * @var array|null */ private static ?array $landTypeNames = null; /** * 获取土地类型名称 * * @param int $typeId 土地类型ID * @return string */ private function getLandTypeName(int $typeId): string { // 初始化静态缓存 if (self::$landTypeNames === null) { $this->initLandTypeNamesCache(); } return self::$landTypeNames[$typeId] ?? "未知土地类型{$typeId}"; } /** * 初始化土地类型名称缓存 * * @return void */ private function initLandTypeNamesCache(): void { try { // 从数据库读取所有土地类型 $landTypes = \App\Module\Farm\Models\FarmLandType::select('id', 'name') ->get() ->pluck('name', 'id') ->toArray(); self::$landTypeNames = $landTypes; \Illuminate\Support\Facades\Log::info("土地类型缓存初始化完成", [ 'count' => count($landTypes), 'types' => $landTypes ]); } catch (\Exception $e) { // 如果数据库查询失败,使用默认值 self::$landTypeNames = [ 1 => '普通土地', 2 => '红土地', 3 => '黑土地', 4 => '金色特殊土地', 5 => '蓝色特殊土地', 6 => '紫色特殊土地', ]; \Illuminate\Support\Facades\Log::warning("土地类型缓存初始化失败,使用默认值", [ 'error' => $e->getMessage(), 'default_types' => self::$landTypeNames ]); } } /** * 清除土地类型名称缓存(用于测试或数据更新后) * * @return void */ public static function clearLandTypeNamesCache(): void { self::$landTypeNames = null; } /** * 格式化消耗物品信息 * * @param mixed $costItems 消耗物品数据 * @return string */ private function formatCostItems($costItems): string { try { if (is_string($costItems)) { $costItems = json_decode($costItems, true); } if (!is_array($costItems)) { return ''; } $costDesc = []; foreach ($costItems as $item) { if (isset($item['name']) && isset($item['quantity'])) { $costDesc[] = "{$item['name']} {$item['quantity']}"; } } return implode('、', $costDesc); } catch (\Exception $e) { return ''; } } /** * 是否应该记录此日志 * * @param mixed $record * @return bool */ private function shouldLogRecord($record): bool { // 对于收获日志,跳过收获数量为0的记录 if ($record->log_type === 'harvest' && $record->harvest_quantity <= 0) { return false; } return true; } /** * 重写获取最后处理ID的方法,因为要处理多个表 * 从user_logs表中查询农场相关的最后处理记录 * * @return int */ protected function getLastProcessedId(): int { try { // 查询农场相关的最后处理记录 $lastLog = \App\Module\Game\Models\UserLog::where('source_type', $this->sourceType) ->whereIn('source_table', ['farm_harvest_logs', 'farm_upgrade_logs']) ->orderBy('source_id', 'desc') ->first(); return $lastLog ? $lastLog->source_id : 0; } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error("获取农场日志最后处理ID失败", [ 'collector' => $this->collectorName, 'error' => $e->getMessage() ]); return 0; } } /** * 重写更新最后处理ID的方法 * 不再需要手动更新,因为进度通过user_logs表自动追踪 * * @param int $id * @return void */ protected function updateLastProcessedId(int $id): void { // 不再需要手动更新,进度通过user_logs表自动追踪 // 这个方法保留是为了兼容性 } }