diff --git a/engine.py b/engine.py index fc1e7af..76460ed 100644 --- a/engine.py +++ b/engine.py @@ -7,67 +7,51 @@ from io import BytesIO class SorterEngine: CONFIG_PATH = "/app/favorites.json" - @staticmethod - def get_images(path): - """Returns list of image files in a directory.""" - exts = ('.jpg', '.jpeg', '.png', '.webp', '.bmp', '.tiff') - if not path or not os.path.exists(path): return [] - try: - return sorted([f for f in os.listdir(path) if f.lower().endswith(exts)]) - except: return [] - - @staticmethod - def get_id_mapping(path): - """Maps idXXX prefixes to full filenames.""" - mapping = {} - for f in SorterEngine.get_images(path): - if f.startswith("id") and "_" in f: - prefix = f.split('_')[0] - mapping[prefix] = f - return mapping - - @staticmethod - def get_max_id_number(folder_path): - """Finds the highest idXXX_ prefix in a folder.""" - max_id = 0 - if not folder_path or not os.path.exists(folder_path): return 0 - try: - for f in os.listdir(folder_path): - if f.startswith("id") and "_" in f: - try: - num = int(f[2:].split('_')[0]) - if num > max_id: max_id = num - except: continue - except: pass - return max_id - - @staticmethod - def compress_for_web(path, quality): - """Compresses image to BytesIO for Streamlit display.""" - try: - with Image.open(path) as img: - buf = BytesIO() - img.convert("RGB").save(buf, format="JPEG", quality=quality) - return buf - except: return None + # ... [get_images, get_id_mapping, get_max_id_number, compress_for_web remain the same] ... @staticmethod def execute_move(t_path, c_path, t_folder, c_folder, prefix, mode="standard"): - """Moves target and copies control into subfolders.""" - t_fname = f"{prefix}{os.path.basename(t_path)}" - c_fname = f"{prefix}{os.path.basename(c_path)}" + """ + Moves target and copies control. + Renames control to match target's name exactly. + """ + # We use the target's filename as the base for BOTH + target_base_name = os.path.basename(t_path) + + t_fname = f"{prefix}{target_base_name}" + c_fname = f"{prefix}{target_base_name}" # Now identical to target name + subdirs = { "standard": ("selected_target", "selected_control"), "solo": ("selected_target_solo_woman", "control_selected_solo_woman") } + t_sub, c_sub = subdirs[mode] - t_dst, c_dst = os.path.join(t_folder, t_sub, t_fname), os.path.join(c_folder, c_sub, c_fname) + t_dst = os.path.join(t_folder, t_sub, t_fname) + c_dst = os.path.join(c_folder, c_sub, c_fname) + os.makedirs(os.path.dirname(t_dst), exist_ok=True) os.makedirs(os.path.dirname(c_dst), exist_ok=True) + shutil.move(t_path, t_dst) shutil.copy2(c_path, c_dst) return t_dst, c_dst + @staticmethod + def move_to_unused_synced(t_p, c_p, t_folder, c_folder): + """Moves both to unused, renaming control to match target name.""" + t_name = os.path.basename(t_p) + + t_un = os.path.join(t_folder, "unused", t_name) + c_un = os.path.join(c_folder, "unused", t_name) # Renamed to match target + + os.makedirs(os.path.dirname(t_un), exist_ok=True) + os.makedirs(os.path.dirname(c_un), exist_ok=True) + + shutil.move(t_p, t_un) + shutil.move(c_p, c_un) + return t_un, c_un + @staticmethod def revert_action(action): """Reverses the last filesystem action."""