Compatibility unverified
This community Razor script has not been tested in game by the Hub. Read its setup and client requirements before use.
This is python not razor! It expects your journal file in a folder named 'journal' and it will return a razor script that can be run once you're back in game to target the box of all SOS's, then target each individual bag, then it moves…
CombatOrganizing
Cluster MIBs part 2 python.razor
1# This is an automated backup - check out https://outlands.uorazorscripts.com/script/42a8a9e7-04d1-4f84-91b7-20e0329afd80 for latest2# Automation by Jaseowns3## Script: Cluster MIBs part 2 (python)4## Created by: dabiri#05#############################################6 7#This is python not razor! It expects your journal file in a folder named 'journal' and it will return a razor script that can be run once you're back in game to target the box of all SOS's, then target each individual bag, then it moves each mib into its cluster appropriate bag. Enjoy and good luck! Depending on your programmin experience this is perhaps not for the faint of heart :)8 9import os10import re11import glob12import numpy as np13from sklearn.metrics import pairwise_distances14 15batch_size = 1016 17def parse_log_file(file_path):18 sos_data = []19 coordinates_pattern = r'\[Razor\]: a waterstained SOS message \(located at (\d+), (\d+)\)'20 serial_pattern = r'\[Razor\]: Added (\d+) to ignore list'21 22 with open(file_path, 'r') as file:23 lines = file.readlines()24 25 i = 026 while i < len(lines):27 coord_match = re.search(coordinates_pattern, lines[i])28 if coord_match:29 x, y = coord_match.groups()30 # Look for the serial number in the next few lines31 for j in range(i+1, min(i+5, len(lines))):32 serial_match = re.search(serial_pattern, lines[j])33 if serial_match:34 serial = serial_match.group(1)35 sos_data.append({36 'coordinates': (int(x), int(y)),37 'serial': serial38 })39 break40 i += 141 42 return sos_data43 44def is_in_big_blue(coord):45 x, y = coord46 return 1600 <= x <= 4000 and 750 <= y <= 300047 48def ball_clustering(sos_data, batch_size):49 coordinates = np.array([entry['coordinates'] for entry in sos_data])50 51 # Separate points into Big Blue and outside52 big_blue_indices = [i for i, coord in enumerate(coordinates) if is_in_big_blue(coord)]53 outside_indices = [i for i, coord in enumerate(coordinates) if not is_in_big_blue(coord)]54 55 # Function to cluster a set of indices56 def cluster_indices(indices):57 clusters = []58 unclustered = indices.copy()59 60 while unclustered:61 start_point = unclustered.pop(0)62 current_cluster = [start_point]63 64 if unclustered:65 distances = pairwise_distances([coordinates[start_point]], coordinates[unclustered])[0]66 closest_indices = np.argsort(distances)[:min(batch_size - 1, len(distances))]67 68 for idx in sorted(closest_indices, reverse=True):69 point_idx = unclustered.pop(idx)70 current_cluster.append(point_idx)71 72 clusters.append([sos_data[i] for i in current_cluster])73 74 return clusters75 76 # Cluster Big Blue and outside separately77 big_blue_clusters = cluster_indices(big_blue_indices)78 outside_clusters = cluster_indices(outside_indices)79 80 # Combine and return all clusters81 return big_blue_clusters + outside_clusters82 83def cluster_coordinates(sos_data, batch_size):84 return ball_clustering(sos_data, batch_size)85 86 87 88def generate_razor_script(batches):89 script = []90 91 # Add header92 script.append("// You will be targeting {} bags".format(len(batches)))93 script.append("")94 script.append("overhead 'Target main box'")95 script.append("@setvar main_box")96 script.append("")97 98 # Add bag targeting instructions99 for i in range(len(batches)):100 script.append(f"overhead 'Target bag {i+1}'")101 script.append(f"@setvar bag_{i+1}")102 script.append("")103 104 # Process each batch105 for i, batch in enumerate(batches):106 script.append(f"//Process bag_{i+1}")107 for entry in batch:108 script.append(f"lift {entry['serial']}")109 script.append(f"drop bag_{i+1} -1 -1 0")110 script.append("pause 650")111 script.append("")112 113 # Join all lines and return114 return "\n".join(script)115 116def generate_map_pin_files(batches):117 output_folder = './output'118 os.makedirs(output_folder, exist_ok=True)119 120 for i, batch in enumerate(batches):121 filename = os.path.join(output_folder, f'bag_{i+1}.txt')122 with open(filename, 'w') as f:123 for entry in batch:124 x, y = entry['coordinates']125 name = f"{x}/{y}"126 line = f"+\t{name}\t{x}\t{y}\t7\tfalse\n"127 f.write(line)128 129 print(f"Map pin file for bag {i+1} has been written to {filename}")130 131# Find the most recent log file in the 'journal' folder132journal_folder = './journal'133list_of_files = glob.glob(os.path.join(journal_folder, '*_journal.txt'))134if not list_of_files:135 print("No journal files found.")136 exit()137 138latest_file = max(list_of_files, key=os.path.getctime)139 140# Parse the log file141sos_data = parse_log_file(latest_file)142 143 144batches = cluster_coordinates(sos_data, batch_size)145 146# Print the results147for i, batch in enumerate(batches):148 print(f"Batch {i+1}:")149 for entry in batch:150 print(f" Coordinates: {entry['coordinates']}, Serial: {entry['serial']}")151 print()152 153 154# After clustering155razor_script = generate_razor_script(batches)156 157# Write to file158output_folder = './output'159os.makedirs(output_folder, exist_ok=True)160output_file = os.path.join(output_folder, 'process_bags.razor')161 162with open(output_file, 'w') as f:163 f.write(razor_script)164 165print(f"Razor script has been written to {output_file}")166 167# After clustering and generating the Razor script168generate_map_pin_files(batches)169 170print('\n\n~~~Map pin files have been generated~~~\n\n')171 172print ('\n~~~All done~~~\n')