diff --git a/draw_results.py b/draw_results.py new file mode 100644 index 000000000..fd48098b0 --- /dev/null +++ b/draw_results.py @@ -0,0 +1,143 @@ +import re +import argparse +import os +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import math + +def extract_logs(filename, start_time=None, end_time=None): + with open(filename, 'r') as f: + lines = f.readlines() + + if start_time is None or end_time is None: + # 如果没有提供时间参数,则返回所有日志 + return lines + + # 截取开始时间和停止时间之间的日志块 + logs_block = [] + capture = False + for line in lines: + if start_time in line: + capture = True + if capture: + logs_block.append(line) + if end_time in line: + capture = False + break + + return logs_block + +def extract_time_from_last_round_zero(log_filename): + with open(log_filename, 'r') as f: + lines = f.readlines() + + # 倒序遍历文件的每一行 + for line in reversed(lines): + if "check msg round :0" in line: + # 正则表达式匹配年月日 小时:分钟的格式 + match = re.search(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2})', line) + if match: + return match.group(1) + return None + +def analyze_log_block(logs_block): + rounds: list[int] = [] + items_collected :list[int] = [] + total_items = 0 + positions:list[(int,int,int)] = [] + + check_for_info = False # 用于检查是否应在下几行中查找 Inventory 的标志 + line_after_message = 0 # 从 "Critic Agent human message" 开始计数的行数 + + + for line in logs_block: + if "check msg round :" in line: + n = int(re.search(r'check msg round :(\d+)', line).group(1)) + if n not in rounds: + rounds.append(n) + items_collected.append(total_items) # add previous total before updating + if "Critic Agent human message" in line: + check_for_info = True + line_after_message = 0 + continue + + if check_for_info: + line_after_message += 1 + + if line_after_message <= 20: + if "Position: x=" in line: + match = re.search(r'Position: x=([\d.-]+), y=([\d.-]+), z=([\d.-]+)', line) + if match: + x, y, z = float(match.group(1)), float(match.group(2)), float(match.group(3)) + positions.append((x, y, z)) + + if "Inventory (" in line: + if ": Empty" in line: + check_for_info = False + continue + items = re.search(r'Inventory \(\d+/36\): ({.*?})', line).group(1) + items_dict = eval(items) + total_items = sum(items_dict.values()) + check_for_info = False + + return rounds, items_collected,positions + +def save_item_results_png(rounds, items_collected, start_time, path_prefix): + # item png + plt.plot(rounds, items_collected, '-o', label="Items Collected") + plt.xlabel("Round") + plt.ylabel("Total Items Collected") + plt.title("Items Collected Over Rounds") + plt.savefig(f'{path_prefix}/{start_time}_items_collected_over_rounds.png', dpi=300) + +def save_path_results_png(positions, start_time, path_prefix): + + x_coords = [pos[0] for pos in positions] + y_coords = [pos[1] for pos in positions] + z_coords = [pos[2] for pos in positions] + + # 计算总里程数 + total_distance = 0 + for i in range(1, len(positions)): + dx = positions[i][0] - positions[i - 1][0] + dy = positions[i][1] - positions[i - 1][1] + dz = positions[i][2] - positions[i - 1][2] + distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) + total_distance += distance + + # 3D path png + fig = plt.figure(figsize=(10, 10)) + ax = fig.add_subplot(111, projection='3d') + ax.plot(x_coords, y_coords, z_coords, '-o', color='blue', markersize=4) + ax.set_title("Bot Movement Path in 3D") + ax.set_xlabel("X Coordinate") + ax.set_ylabel("Y Coordinate") + ax.set_zlabel("Z Coordinate") + ax.text(min(x_coords), max(y_coords), max(z_coords), f"Total Distance: {total_distance:.2f} units", fontsize=15, color='red') + plt.savefig(f'{path_prefix}/{start_time}_bot_movement_3D_path.png', dpi=300) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Analyze game log file between a start and end time.") + parser.add_argument('--start_time', type=str, default=None, nargs='?', + help="Start time for analysis in the log file.") + parser.add_argument('--end_time', type=str, default=None, nargs='?', help="End time for analysis in the log file.") + args = parser.parse_args() + + + current_script_path = os.path.dirname(os.path.abspath(__file__)) + filename = f"{current_script_path}/logs/log.txt" + + start_time = None + if args.start_time: + # 手动输入起止时间,注意要带上"xxx" 如"2023-10-08 03:14" + logs_block = extract_logs(filename, args.start_time, args.end_time) + else: + # 自动寻找最新的实验开始时间 + start_time = extract_time_from_last_round_zero(filename) + logs_block = extract_logs(filename, start_time) + + rounds, items_collected, positions = analyze_log_block(logs_block) + #save png + save_item_results_png(rounds, items_collected, args.start_time if args.start_time else start_time, current_script_path+"/results_pic") + save_path_results_png(positions, args.start_time if args.start_time else start_time, current_script_path+"/results_pic") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index de861ded9..0e68cc0ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,4 +42,4 @@ pytest-mock==3.11.1 open-interpreter==0.1.4; python_version>"3.9" ta==0.10.2 semantic-kernel==0.3.10.dev0 - +matplotlib==3.7.2 diff --git a/results_pic/2023-10-10 17:04_bot_movement_3D_path.png b/results_pic/2023-10-10 17:04_bot_movement_3D_path.png new file mode 100644 index 000000000..35bfb1eaa Binary files /dev/null and b/results_pic/2023-10-10 17:04_bot_movement_3D_path.png differ diff --git a/results_pic/2023-10-10 17:04_items_collected_over_rounds.png b/results_pic/2023-10-10 17:04_items_collected_over_rounds.png new file mode 100644 index 000000000..f2f590618 Binary files /dev/null and b/results_pic/2023-10-10 17:04_items_collected_over_rounds.png differ