extends Node class_name GameStatistics ## 游戏统计和分析功能 ## 收集和分析游戏整体运行数据和玩家统计信息 # 统计数据类型 enum StatType { PLAYER_COUNT, # 玩家数量 SESSION_DURATION, # 会话时长 FEATURE_USAGE, # 功能使用率 PERFORMANCE, # 性能指标 ERROR_RATE, # 错误率 ENGAGEMENT, # 参与度 RETENTION, # 留存率 SOCIAL_ACTIVITY # 社交活动 } # 统计数据结构 class GameStat: var stat_type: StatType var value: float var timestamp: float var metadata: Dictionary = {} func _init(type: StatType, val: float, meta: Dictionary = {}): stat_type = type value = val timestamp = Time.get_unix_time_from_system() metadata = meta.duplicate() # 数据存储 var statistics_history: Array[GameStat] = [] var daily_statistics: Dictionary = {} # date_string -> Dictionary var feature_usage_stats: Dictionary = {} var performance_metrics: Dictionary = {} var player_statistics: Dictionary = {} # 配置 var max_history_entries: int = 10000 var statistics_enabled: bool = true var collection_interval: float = 300.0 # 5分钟收集一次 # 引用其他系统 var user_behavior_analytics: UserBehaviorAnalytics var social_manager: SocialManager # 数据持久化 var stats_file_path: String = "user://game_statistics.json" # 信号 signal statistic_recorded(stat_type: StatType, value: float) signal daily_report_generated(date: String, report: Dictionary) signal performance_alert(metric: String, value: float, threshold: float) func _ready(): """初始化游戏统计系统""" _load_statistics_data() # 设置定时统计收集 var collection_timer = Timer.new() collection_timer.wait_time = collection_interval collection_timer.timeout.connect(_collect_periodic_statistics) collection_timer.autostart = true add_child(collection_timer) # 设置每日报告生成 var daily_timer = Timer.new() daily_timer.wait_time = 86400.0 # 24小时 daily_timer.timeout.connect(_generate_daily_report) daily_timer.autostart = true add_child(daily_timer) print("GameStatistics initialized") ## 设置系统引用 func set_system_references(uba: UserBehaviorAnalytics, sm: SocialManager) -> void: """ 设置其他系统的引用 @param uba: 用户行为分析系统 @param sm: 社交管理器 """ user_behavior_analytics = uba social_manager = sm # 连接信号 if user_behavior_analytics: user_behavior_analytics.behavior_recorded.connect(_on_behavior_recorded) if social_manager: social_manager.friend_activity.connect(_on_social_activity) ## 记录统计数据 func record_statistic(stat_type: StatType, value: float, metadata: Dictionary = {}) -> void: """ 记录统计数据 @param stat_type: 统计类型 @param value: 统计值 @param metadata: 元数据 """ if not statistics_enabled: return var stat = GameStat.new(stat_type, value, metadata) statistics_history.append(stat) # 限制历史记录数量 if statistics_history.size() > max_history_entries: statistics_history.pop_front() # 更新当日统计 _update_daily_statistics(stat) # 检查性能警报 _check_performance_alerts(stat_type, value) # 发射信号 statistic_recorded.emit(stat_type, value) print("Statistic recorded: ", StatType.keys()[stat_type], " = ", value) ## 记录玩家数量 func record_player_count(online_count: int, total_count: int) -> void: """ 记录玩家数量统计 @param online_count: 在线玩家数 @param total_count: 总玩家数 """ record_statistic(StatType.PLAYER_COUNT, online_count, { "total_players": total_count, "online_ratio": float(online_count) / max(total_count, 1) }) ## 记录功能使用情况 func record_feature_usage(feature_name: String, usage_count: int, user_count: int) -> void: """ 记录功能使用统计 @param feature_name: 功能名称 @param usage_count: 使用次数 @param user_count: 使用用户数 """ # 更新功能使用统计 if not feature_usage_stats.has(feature_name): feature_usage_stats[feature_name] = { "total_usage": 0, "unique_users": {}, "daily_usage": {} } var feature_stat = feature_usage_stats[feature_name] feature_stat.total_usage += usage_count # 记录到统计历史 record_statistic(StatType.FEATURE_USAGE, usage_count, { "feature": feature_name, "user_count": user_count, "usage_rate": float(usage_count) / max(user_count, 1) }) ## 记录性能指标 func record_performance_metric(metric_name: String, value: float, threshold: float = 0.0) -> void: """ 记录性能指标 @param metric_name: 指标名称 @param value: 指标值 @param threshold: 警报阈值 """ # 更新性能指标历史 if not performance_metrics.has(metric_name): performance_metrics[metric_name] = [] var metric_history = performance_metrics[metric_name] metric_history.append({ "value": value, "timestamp": Time.get_unix_time_from_system() }) # 限制历史记录长度 if metric_history.size() > 100: metric_history.pop_front() # 记录统计 record_statistic(StatType.PERFORMANCE, value, { "metric": metric_name, "threshold": threshold }) ## 记录参与度指标 func record_engagement_metric(session_duration: float, actions_count: int, features_used: int) -> void: """ 记录用户参与度指标 @param session_duration: 会话时长 @param actions_count: 操作次数 @param features_used: 使用功能数 """ var engagement_score = _calculate_engagement_score(session_duration, actions_count, features_used) record_statistic(StatType.ENGAGEMENT, engagement_score, { "session_duration": session_duration, "actions_count": actions_count, "features_used": features_used }) ## 计算参与度分数 func _calculate_engagement_score(duration: float, actions: int, features: int) -> float: """ 计算参与度分数 @param duration: 会话时长(秒) @param actions: 操作次数 @param features: 使用功能数 @return: 参与度分数(0-100) """ # 时长分数(最多30分钟满分) var duration_score = min(duration / 1800.0, 1.0) * 40.0 # 操作频率分数 var action_rate = actions / max(duration / 60.0, 1.0) # 每分钟操作数 var action_score = min(action_rate / 10.0, 1.0) * 30.0 # 功能多样性分数 var feature_score = min(features / 5.0, 1.0) * 30.0 return duration_score + action_score + feature_score ## 定期收集统计数据 func _collect_periodic_statistics() -> void: """定期收集系统统计数据""" if not statistics_enabled: return # 收集性能数据 var fps = Engine.get_frames_per_second() var memory = OS.get_static_memory_usage_by_type() record_performance_metric("fps", fps, 30.0) record_performance_metric("memory_mb", memory / 1024.0 / 1024.0, 512.0) # 收集用户行为数据 if user_behavior_analytics: var behavior_stats = user_behavior_analytics.get_realtime_statistics() record_statistic(StatType.SESSION_DURATION, behavior_stats.get("current_session_duration", 0.0)) # 收集社交活动数据 if social_manager: var social_stats = social_manager.get_statistics() _record_social_statistics(social_stats) ## 记录社交统计 func _record_social_statistics(social_stats: Dictionary) -> void: """记录社交活动统计""" if social_stats.has("friend_system"): var friend_stats = social_stats.friend_system record_statistic(StatType.SOCIAL_ACTIVITY, friend_stats.get("total_friends", 0), { "type": "friends", "pending_requests": friend_stats.get("pending_requests", 0) }) if social_stats.has("community_events"): var event_stats = social_stats.community_events record_statistic(StatType.SOCIAL_ACTIVITY, event_stats.get("active_events", 0), { "type": "events", "total_events": event_stats.get("total_events", 0) }) ## 更新每日统计 func _update_daily_statistics(stat: GameStat) -> void: """更新每日统计数据""" var date_string = Time.get_date_string_from_unix_time(stat.timestamp) if not daily_statistics.has(date_string): daily_statistics[date_string] = { "date": date_string, "stats_by_type": {}, "total_records": 0, "performance_summary": {}, "feature_usage_summary": {} } var daily_data = daily_statistics[date_string] daily_data.total_records += 1 # 按类型统计 var type_name = StatType.keys()[stat.stat_type] if not daily_data.stats_by_type.has(type_name): daily_data.stats_by_type[type_name] = { "count": 0, "total_value": 0.0, "min_value": stat.value, "max_value": stat.value } var type_stats = daily_data.stats_by_type[type_name] type_stats.count += 1 type_stats.total_value += stat.value type_stats.min_value = min(type_stats.min_value, stat.value) type_stats.max_value = max(type_stats.max_value, stat.value) ## 生成每日报告 func _generate_daily_report() -> void: """生成每日统计报告""" var yesterday = Time.get_date_string_from_unix_time(Time.get_unix_time_from_system() - 86400) if not daily_statistics.has(yesterday): return var daily_data = daily_statistics[yesterday] var report = _create_daily_report(daily_data) daily_report_generated.emit(yesterday, report) print("Daily report generated for: ", yesterday) ## 创建每日报告 func _create_daily_report(daily_data: Dictionary) -> Dictionary: """创建每日报告数据""" var report = daily_data.duplicate() # 计算平均值 for type_name in daily_data.stats_by_type: var type_stats = daily_data.stats_by_type[type_name] type_stats["average_value"] = type_stats.total_value / max(type_stats.count, 1) # 添加趋势分析 report["trends"] = _analyze_daily_trends(daily_data.date) # 添加关键指标摘要 report["key_metrics"] = _extract_key_metrics(daily_data) return report ## 分析每日趋势 func _analyze_daily_trends(date: String) -> Dictionary: """分析每日数据趋势""" var trends = {} # 获取前一天数据进行对比 var prev_date_time = Time.get_unix_time_from_datetime_string(date + "T00:00:00") - 86400 var prev_date = Time.get_date_string_from_unix_time(prev_date_time) if daily_statistics.has(prev_date): var current_data = daily_statistics[date] var prev_data = daily_statistics[prev_date] # 比较总记录数 var current_total = current_data.get("total_records", 0) var prev_total = prev_data.get("total_records", 0) if prev_total > 0: trends["activity_change"] = (float(current_total - prev_total) / prev_total) * 100.0 # 比较各类型统计 trends["type_changes"] = {} for type_name in current_data.get("stats_by_type", {}): var current_count = current_data.stats_by_type[type_name].get("count", 0) var prev_count = prev_data.get("stats_by_type", {}).get(type_name, {}).get("count", 0) if prev_count > 0: trends.type_changes[type_name] = (float(current_count - prev_count) / prev_count) * 100.0 return trends ## 提取关键指标 func _extract_key_metrics(daily_data: Dictionary) -> Dictionary: """提取每日关键指标""" var metrics = {} var stats_by_type = daily_data.get("stats_by_type", {}) # 性能指标 if stats_by_type.has("PERFORMANCE"): metrics["performance"] = { "average": stats_by_type.PERFORMANCE.get("average_value", 0.0), "min": stats_by_type.PERFORMANCE.get("min_value", 0.0), "max": stats_by_type.PERFORMANCE.get("max_value", 0.0) } # 参与度指标 if stats_by_type.has("ENGAGEMENT"): metrics["engagement"] = { "average_score": stats_by_type.ENGAGEMENT.get("average_value", 0.0), "peak_score": stats_by_type.ENGAGEMENT.get("max_value", 0.0) } # 社交活动指标 if stats_by_type.has("SOCIAL_ACTIVITY"): metrics["social"] = { "activity_count": stats_by_type.SOCIAL_ACTIVITY.get("count", 0), "average_activity": stats_by_type.SOCIAL_ACTIVITY.get("average_value", 0.0) } return metrics ## 检查性能警报 func _check_performance_alerts(stat_type: StatType, value: float) -> void: """检查性能警报条件""" if stat_type == StatType.PERFORMANCE: # FPS过低警报 if value < 20.0: performance_alert.emit("low_fps", value, 20.0) # 内存使用过高警报(假设单位是MB) if value > 1000.0: performance_alert.emit("high_memory", value, 1000.0) ## 获取统计摘要 func get_statistics_summary(days: int = 7) -> Dictionary: """ 获取统计摘要 @param days: 统计天数 @return: 统计摘要 """ var summary = {} var current_time = Time.get_unix_time_from_system() var start_time = current_time - (days * 86400) # 获取时间范围内的统计 var recent_stats = statistics_history.filter(func(stat): return stat.timestamp >= start_time) summary["period_days"] = days summary["total_records"] = recent_stats.size() summary["start_date"] = Time.get_date_string_from_unix_time(start_time) summary["end_date"] = Time.get_date_string_from_unix_time(current_time) # 按类型汇总 var type_summary = {} for stat in recent_stats: var type_name = StatType.keys()[stat.stat_type] if not type_summary.has(type_name): type_summary[type_name] = { "count": 0, "values": [] } type_summary[type_name].count += 1 type_summary[type_name].values.append(stat.value) # 计算统计指标 for type_name in type_summary: var values = type_summary[type_name].values if values.size() > 0: type_summary[type_name]["average"] = _calculate_average(values) type_summary[type_name]["min"] = values.min() type_summary[type_name]["max"] = values.max() summary["by_type"] = type_summary return summary ## 计算平均值 func _calculate_average(values: Array) -> float: """计算数组平均值""" if values.is_empty(): return 0.0 var sum = 0.0 for value in values: sum += float(value) return sum / values.size() ## 信号处理函数 func _on_behavior_recorded(event_type: UserBehaviorAnalytics.EventType, data: Dictionary): """处理用户行为记录事件""" # 将用户行为转换为游戏统计 match event_type: UserBehaviorAnalytics.EventType.LOGIN: record_statistic(StatType.PLAYER_COUNT, 1.0, {"action": "login"}) UserBehaviorAnalytics.EventType.UI_ACTION: var element = data.get("element", "unknown") record_feature_usage(element, 1, 1) func _on_social_activity(activity_type: String, data: Dictionary): """处理社交活动事件""" record_statistic(StatType.SOCIAL_ACTIVITY, 1.0, { "activity_type": activity_type, "data": data }) ## 保存统计数据 func _save_statistics_data() -> void: """保存统计数据到本地文件""" var data = { "statistics_history": [], "daily_statistics": daily_statistics, "feature_usage_stats": feature_usage_stats, "performance_metrics": performance_metrics, "saved_at": Time.get_unix_time_from_system() } # 序列化统计历史(只保存最近的数据) var stats_to_save = statistics_history.slice(max(0, statistics_history.size() - 1000), statistics_history.size()) for stat in stats_to_save: data.statistics_history.append({ "stat_type": stat.stat_type, "value": stat.value, "timestamp": stat.timestamp, "metadata": stat.metadata }) var file = FileAccess.open(stats_file_path, FileAccess.WRITE) if file: var json_string = JSON.stringify(data) file.store_string(json_string) file.close() print("Game statistics saved: ", stats_to_save.size(), " records") else: print("Failed to save game statistics") ## 加载统计数据 func _load_statistics_data() -> void: """从本地文件加载统计数据""" if not FileAccess.file_exists(stats_file_path): print("No game statistics file found, starting fresh") return var file = FileAccess.open(stats_file_path, FileAccess.READ) if file: var json_string = file.get_as_text() file.close() var json = JSON.new() var parse_result = json.parse(json_string) if parse_result == OK: var data = json.data # 加载统计历史 if data.has("statistics_history"): for stat_data in data.statistics_history: var stat = GameStat.new( stat_data.get("stat_type", StatType.PERFORMANCE), stat_data.get("value", 0.0), stat_data.get("metadata", {}) ) stat.timestamp = stat_data.get("timestamp", 0.0) statistics_history.append(stat) # 加载其他数据 daily_statistics = data.get("daily_statistics", {}) feature_usage_stats = data.get("feature_usage_stats", {}) performance_metrics = data.get("performance_metrics", {}) print("Game statistics loaded: ", statistics_history.size(), " records") else: print("Failed to parse game statistics JSON") else: print("Failed to open game statistics file") func _exit_tree(): """节点退出时保存数据""" _save_statistics_data()