prthm11 commited on
Commit
c0cfc76
Β·
verified Β·
1 Parent(s): cca3e97

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +263 -266
app.py CHANGED
@@ -50,28 +50,6 @@ dinov2_model.eval()
50
  phash = PHash()
51
  gis = ImageSignature()
52
 
53
- def log_execution_time(func):
54
- @functools.wraps(func)
55
- def wrapper(*args, **kwargs):
56
- start_time = time.time()
57
- result = func(*args, **kwargs)
58
- end_time = time.time()
59
- logger.info(f"⏱ {func.__name__} executed in {end_time - start_time:.2f} seconds")
60
- return result
61
- return wrapper
62
-
63
- # Configure logging
64
- logging.basicConfig(
65
- level=logging.DEBUG, # Use INFO or ERROR in production
66
- format="%(asctime)s [%(levelname)s] %(message)s",
67
- handlers=[
68
- logging.FileHandler("/app/logs/app.log"),
69
- logging.StreamHandler()
70
- ]
71
- )
72
-
73
- logger = logging.getLogger(__name__)
74
-
75
  load_dotenv()
76
  # os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY")
77
  groq_api_key = os.getenv("GROQ_API_KEY")
@@ -84,26 +62,33 @@ llm = ChatGroq(
84
 
85
  app = Flask(__name__)
86
 
 
 
 
 
87
  count = 0
88
 
89
- # BASE_DIR = Path("/app")
90
- # BLOCKS_DIR = BASE_DIR / "blocks"
91
- # STATIC_DIR = BASE_DIR / "static"
92
- # GEN_PROJECT_DIR = BASE_DIR / "generated_projects"
93
  BASE_DIR = Path(os.getenv("APP_BASE_DIR", Path(__file__).resolve().parent)) # fallback to code location
94
- LOGS_DIR = BASE_DIR / "logs"
 
95
  for d in (BASE_DIR / "blocks", BASE_DIR / "static", BASE_DIR / "generated_projects", LOGS_DIR, BASE_DIR / "outputs"):
96
  d.mkdir(parents=True, exist_ok=True)
97
- BACKDROP_DIR = BLOCKS_DIR / "Backdrops"
98
- SPRITE_DIR = BLOCKS_DIR / "sprites"
99
- CODE_BLOCKS_DIR = BLOCKS_DIR / "code_blocks"
100
- # === new: outputs rooted under BASE_DIR ===
101
- OUTPUT_DIR = BASE_DIR / "outputs"
102
-
103
 
104
- backdrop_images_path = str(BACKDROP_DIR)
105
- sprite_images_path = str(SPRITE_DIR)
106
- code_blocks_image_path = str(CODE_BLOCKS_DIR)
 
 
 
 
 
 
107
 
108
  # Global variables to hold the model and index, loaded only once.
109
  MODEL = None
@@ -121,7 +106,30 @@ for d in (
121
  OUTPUT_DIR,
122
  ):
123
  d.mkdir(parents=True, exist_ok=True)
124
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  class GameState(TypedDict):
126
  project_json: dict
127
  description: str
@@ -1427,15 +1435,11 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1427
  import json
1428
  os.makedirs(project_folder, exist_ok=True)
1429
 
1430
- # backdrop_base_path = os.path.normpath(str(BACKDROP_DIR)).resolve()
1431
- # sprite_base_path = os.path.normpath(str(SPRITE_DIR)).resolve()
1432
- # code_blocks_path = os.path.normpath(str(CODE_BLOCKS_DIR)).resolve()
1433
- # project_json_path = os.path.join(project_folder, "project.json").resolve()
1434
- backdrop_base_path = BACKDROP_DIR.resolve()
1435
- sprite_base_path = SPRITE_DIR.resolve()
1436
- code_blocks_path = CODE_BLOCKS_DIR.resolve()
1437
- project_json_path = (Path(project_folder) / "project.json").resolve()
1438
 
 
1439
 
1440
  # -------------------------
1441
  # Build sprite images list (BytesIO) from sprites_data
@@ -1944,272 +1948,265 @@ def similarity_matching(sprites_data: dict, project_folder: str, top_k: int = 1,
1944
 
1945
  # print("---")
1946
  # add at top of file
1947
- # import shutil
1948
- # import json
1949
- # import os
1950
- # from pathlib import Path
1951
-
1952
- # # normalize base paths once before the loop
1953
- # sprite_base_p = Path(sprite_base_path).resolve(strict=False)
1954
- # backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
1955
- # project_folder_p = Path(project_folder)
1956
- # project_folder_p.mkdir(parents=True, exist_ok=True)
1957
-
1958
- # copied_sprite_folders = set()
1959
- # copied_backdrop_folders = set()
1960
-
1961
- # def display_like_windows_no_lead(p: Path) -> str:
1962
- # """
1963
- # For human-readable logs only β€” convert Path to a string like:
1964
- # "app\\blocks\\Backdrops\\Castle 2.sb3" (no leading slash).
1965
- # """
1966
- # s = p.as_posix() # forward-slash string, safe for Path objects
1967
- # if s.startswith("/"):
1968
- # s = s[1:]
1969
- # return s.replace("/", "\\")
1970
-
1971
- # def is_subpath(child: Path, parent: Path) -> bool:
1972
- # """Robust membership test: is child under parent?"""
1973
- # try:
1974
- # # use non-strict resolve only if needed, but avoid exceptions
1975
- # child.relative_to(parent)
1976
- # return True
1977
- # except Exception:
1978
- # return False
1979
-
1980
- # # Flatten unique matched indices (if not already)
1981
- # matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
1982
- # print("matched_indices------------------>", matched_indices)
1983
-
1984
- # for matched_idx in matched_indices:
1985
- # # defensive check
1986
- # if not (0 <= matched_idx < len(paths_list)):
1987
- # print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
1988
- # continue
1989
-
1990
- # matched_image_path = paths_list[matched_idx]
1991
- # matched_path_p = Path(matched_image_path).resolve(strict=False) # keep as Path
1992
- # matched_folder_p = matched_path_p.parent # Path object
1993
- # matched_filename = matched_path_p.name
1994
-
1995
- # # Prepare display-only string (do NOT reassign matched_folder_p)
1996
- # matched_folder_display = display_like_windows_no_lead(matched_folder_p)
1997
 
1998
- # print(f"Processing matched image: {matched_image_path}")
1999
- # print(f" - Folder: {matched_folder_display}")
2000
- # print(f" - Sprite path: {display_like_windows_no_lead(sprite_base_p)}")
2001
- # print(f" - Backdrop path: {display_like_windows_no_lead(backdrop_base_p)}")
2002
- # print(f" - Filename: {matched_filename}")
2003
 
2004
- # # Use a canonical string to store in the copied set (POSIX absolute-ish)
2005
- # folder_key = matched_folder_p.as_posix()
2006
 
2007
- # # ---------- SPRITE ----------
2008
- # if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
2009
- # print(f"Processing SPRITE folder: {matched_folder_display}")
2010
- # copied_sprite_folders.add(folder_key)
 
 
 
 
 
2011
 
2012
- # sprite_json_path = matched_folder_p / "sprite.json"
2013
- # print("sprite_json_path----------------------->", sprite_json_path)
2014
- # print("copied sprite folder----------------------->", copied_sprite_folders)
2015
- # if sprite_json_path.exists() and sprite_json_path.is_file():
2016
- # try:
2017
- # with sprite_json_path.open("r", encoding="utf-8") as f:
2018
- # sprite_info = json.load(f)
2019
- # project_data.append(sprite_info)
2020
- # print(f" βœ“ Successfully read sprite.json from {matched_folder_display}")
2021
- # except Exception as e:
2022
- # print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
2023
- # else:
2024
- # print(f" ⚠ No sprite.json in {matched_folder_display}")
2025
 
2026
- # # copy non-matching files from the sprite folder (except matched image and sprite.json)
2027
- # try:
2028
- # sprite_files = list(matched_folder_p.iterdir())
2029
- # except Exception as e:
2030
- # sprite_files = []
2031
- # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2032
 
2033
- # print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
2034
- # for p in sprite_files:
2035
- # fname = p.name
2036
- # if fname in (matched_filename, "sprite.json"):
2037
- # print(f" Skipping {fname} (matched image or sprite.json)")
2038
- # continue
2039
- # if p.is_file():
2040
- # dst = project_folder_p / fname
2041
- # try:
2042
- # shutil.copy2(str(p), str(dst))
2043
- # print(f" βœ“ Copied sprite asset: {p} -> {dst}")
2044
- # except Exception as e:
2045
- # print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
2046
- # else:
2047
- # print(f" Skipping {fname} (not a file)")
2048
 
2049
- # # ---------- BACKDROP ----------
2050
- # if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
2051
- # print(f"Processing BACKDROP folder: {matched_folder_display}")
2052
- # copied_backdrop_folders.add(folder_key)
2053
- # print("backdrop_base_path----------------------->", display_like_windows_no_lead(backdrop_base_p))
2054
- # print("copied backdrop folder----------------------->", copied_backdrop_folders)
2055
 
2056
- # # copy matched backdrop image
2057
- # backdrop_src = matched_folder_p / matched_filename
2058
- # backdrop_dst = project_folder_p / matched_filename
2059
- # if backdrop_src.exists() and backdrop_src.is_file():
2060
- # try:
2061
- # shutil.copy2(str(backdrop_src), str(backdrop_dst))
2062
- # print(f" βœ“ Copied matched backdrop image: {backdrop_src} -> {backdrop_dst}")
2063
- # except Exception as e:
2064
- # print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
2065
- # else:
2066
- # print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
2067
 
2068
- # # copy other files from folder (skip project.json and matched image)
2069
- # try:
2070
- # backdrop_files = list(matched_folder_p.iterdir())
2071
- # except Exception as e:
2072
- # backdrop_files = []
2073
- # print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2074
 
2075
- # print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
2076
- # for p in backdrop_files:
2077
- # fname = p.name
2078
- # if fname in (matched_filename, "project.json"):
2079
- # print(f" Skipping {fname} (matched image or project.json)")
2080
- # continue
2081
- # if p.is_file():
2082
- # dst = project_folder_p / fname
2083
- # try:
2084
- # shutil.copy2(str(p), str(dst))
2085
- # print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
2086
- # except Exception as e:
2087
- # print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
2088
- # else:
2089
- # print(f" Skipping {fname} (not a file)")
2090
 
2091
- # # read project.json to extract Stage/targets
2092
- # pj = matched_folder_p / "project.json"
2093
- # if pj.exists() and pj.is_file():
2094
- # try:
2095
- # with pj.open("r", encoding="utf-8") as f:
2096
- # bd_json = json.load(f)
2097
- # stage_count = 0
2098
- # for tgt in bd_json.get("targets", []):
2099
- # if tgt.get("isStage"):
2100
- # backdrop_data.append(tgt)
2101
- # stage_count += 1
2102
- # print(f" βœ“ Successfully read project.json from {matched_folder_display}, found {stage_count} stage(s)")
2103
- # except Exception as e:
2104
- # print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
2105
- # else:
2106
- # print(f" ⚠ No project.json in {matched_folder_display}")
2107
 
2108
- # print("---")
2109
- for matched_idx in matched_indices:
2110
- matched_image_path = paths_list[matched_idx]
2111
- # matched_folder = os.path.dirname(matched_image_path)
2112
- matched_folder = str(Path(matched_image_path).parent.resolve())
2113
- matched_filename = os.path.basename(matched_image_path)
2114
-
2115
- print(f"Processing matched image: {matched_image_path}")
2116
- print(f" - Folder: {matched_folder}")
2117
- print(f" - Sprite path: {sprite_base_path}")
2118
- print(f" - Backdrop path: {backdrop_base_path}")
2119
- print(f" - Filename: {matched_filename}")
2120
-
2121
- # If it's a sprite (under SPRITE_DIR) -> copy sprite assets and read sprite.json
2122
- # if matched_folder.startswith(sprite_base_path) and matched_folder not in copied_sprite_folders:
2123
- if is_subpath(matched_folder, sprite_base_path) and matched_folder not in copied_sprite_folders:
2124
- print(f"Processing SPRITE folder: {matched_folder}")
2125
- copied_sprite_folders.add(matched_folder)
2126
- # sprite_json_path = os.path.join(matched_folder, "sprite.json")
2127
- sprite_json_path = str(Path(matched_folder) / "sprite.json")
2128
- print("sprite_json_path----------------------->",sprite_json_path)
2129
- print("copied sprite folder----------------------->",copied_sprite_folders)
2130
- if os.path.exists(sprite_json_path):
2131
  try:
2132
- with open(sprite_json_path, "r", encoding="utf-8") as f:
2133
  sprite_info = json.load(f)
2134
  project_data.append(sprite_info)
2135
- print(f" βœ“ Successfully read sprite.json from {matched_folder}")
2136
  except Exception as e:
2137
- print(f" βœ— Failed to read sprite.json in {matched_folder}: {e}")
2138
  else:
2139
- print(f" ⚠ No sprite.json in {matched_folder}")
2140
-
2141
- # copy non-matching files from the sprite folder (except the matched image and sprite.json)
2142
- sprite_files = os.listdir(matched_folder)
2143
- print(f" Files in sprite folder: {sprite_files}")
2144
- for fname in sprite_files:
 
 
 
 
 
 
2145
  if fname in (matched_filename, "sprite.json"):
2146
  print(f" Skipping {fname} (matched image or sprite.json)")
2147
  continue
2148
- src = os.path.join(matched_folder, fname)
2149
- dst = os.path.join(project_folder, fname)
2150
- if os.path.isfile(src):
2151
  try:
2152
- shutil.copy2(src, dst)
2153
- print(f" βœ“ Copied sprite asset: {src} -> {dst}")
2154
  except Exception as e:
2155
- print(f" βœ— Failed to copy sprite asset {src}: {e}")
2156
  else:
2157
  print(f" Skipping {fname} (not a file)")
2158
-
2159
- # If it's a backdrop (under BACKDROP_DIR) -> copy backdrop assets and read project.json for stage
2160
- # if matched_folder.startswith(backdrop_base_path) and matched_folder not in copied_backdrop_folders:
2161
- if is_subpath(matched_folder, backdrop_base_path) and matched_folder not in copied_backdrop_folders:
2162
- print(f"Processing BACKDROP folder: {matched_folder}")
2163
- copied_backdrop_folders.add(matched_folder)
2164
- print("backdrop_base_path----------------------->",backdrop_base_path)
2165
- print("copied backdrop folder----------------------->",copied_backdrop_folders)
2166
  # copy matched backdrop image
2167
- backdrop_dst = os.path.join(project_folder, matched_filename)
 
 
 
 
 
 
 
 
 
 
 
2168
  try:
2169
- shutil.copy2(matched_image_path, backdrop_dst)
2170
- print(f" βœ“ Copied matched backdrop image: {matched_image_path} -> {backdrop_dst}")
2171
  except Exception as e:
2172
- print(f" βœ— Failed to copy matched backdrop image {matched_image_path}: {e}")
2173
-
2174
- # copy other files from folder (skip project.json and matched image)
2175
- backdrop_files = os.listdir(matched_folder)
2176
- print(f" Files in backdrop folder: {backdrop_files}")
2177
- for fname in backdrop_files:
2178
  if fname in (matched_filename, "project.json"):
2179
  print(f" Skipping {fname} (matched image or project.json)")
2180
  continue
2181
- # src = os.path.join(matched_folder, fname)
2182
- # dst = os.path.join(project_folder, fname)
2183
- src = Path(matched_folder) / fname
2184
- dst = Path(project_folder) / fname
2185
- if os.path.isfile(src):
2186
  try:
2187
- shutil.copy2(src, dst)
2188
- print(f" βœ“ Copied backdrop asset: {src} -> {dst}")
2189
  except Exception as e:
2190
- print(f" βœ— Failed to copy backdrop asset {src}: {e}")
2191
  else:
2192
  print(f" Skipping {fname} (not a file)")
2193
-
2194
  # read project.json to extract Stage/targets
2195
- # pj = os.path.join(matched_folder, "project.json")
2196
- pj = str(Path(matched_folder) / "project.json")
2197
- if os.path.exists(pj):
2198
  try:
2199
- with open(pj, "r", encoding="utf-8") as f:
2200
  bd_json = json.load(f)
2201
  stage_count = 0
2202
  for tgt in bd_json.get("targets", []):
2203
  if tgt.get("isStage"):
2204
  backdrop_data.append(tgt)
2205
  stage_count += 1
2206
- print(f" βœ“ Successfully read project.json from {matched_folder}, found {stage_count} stage(s)")
2207
  except Exception as e:
2208
- print(f" βœ— Failed to read project.json in {matched_folder}: {e}")
2209
  else:
2210
- print(f" ⚠ No project.json in {matched_folder}")
2211
-
2212
  print("---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2213
 
2214
  # --- Merge into final Scratch project.json (identical logic to before)
2215
  final_project = {
 
50
  phash = PHash()
51
  gis = ImageSignature()
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  load_dotenv()
54
  # os.environ["GROQ_API_KEY"] = os.getenv("GROQ_API_KEY")
55
  groq_api_key = os.getenv("GROQ_API_KEY")
 
62
 
63
  app = Flask(__name__)
64
 
65
+ backdrop_images_path = r"app\blocks\Backdrops"
66
+ sprite_images_path = r"app\blocks\sprites"
67
+ code_blocks_image_path = r"app\blocks\code_blocks"
68
+
69
  count = 0
70
 
71
+ from pathlib import Path
 
 
 
72
  BASE_DIR = Path(os.getenv("APP_BASE_DIR", Path(__file__).resolve().parent)) # fallback to code location
73
+ LOGS_DIR = Path(os.getenv("LOGS_DIR", "/tmp/logs")).resolve()
74
+ LOGS_DIR.mkdir(parents=True, exist_ok=True)
75
  for d in (BASE_DIR / "blocks", BASE_DIR / "static", BASE_DIR / "generated_projects", LOGS_DIR, BASE_DIR / "outputs"):
76
  d.mkdir(parents=True, exist_ok=True)
77
+ # adjust BLOCKS_DIR etc:
78
+ BLOCKS_DIR = BASE_DIR / "blocks"
79
+ BACKDROP_DIR = BLOCKS_DIR / "Backdrops"
80
+ SPRITE_DIR = BLOCKS_DIR / "sprites"
81
+ CODE_BLOCKS_DIR = BLOCKS_DIR / "code_blocks"
 
82
 
83
+ # BASE_DIR = Path("/app")
84
+ # BLOCKS_DIR = BASE_DIR / "blocks"
85
+ # STATIC_DIR = BASE_DIR / "static"
86
+ # GEN_PROJECT_DIR = BASE_DIR / "generated_projects"
87
+ # BACKDROP_DIR = BLOCKS_DIR / "Backdrops"
88
+ # SPRITE_DIR = BLOCKS_DIR / "sprites"
89
+ # CODE_BLOCKS_DIR = BLOCKS_DIR / "code_blocks"
90
+ # # === new: outputs rooted under BASE_DIR ===
91
+ # OUTPUT_DIR = BASE_DIR / "outputs"
92
 
93
  # Global variables to hold the model and index, loaded only once.
94
  MODEL = None
 
106
  OUTPUT_DIR,
107
  ):
108
  d.mkdir(parents=True, exist_ok=True)
109
+
110
+ def log_execution_time(func):
111
+ @functools.wraps(func)
112
+ def wrapper(*args, **kwargs):
113
+ start_time = time.time()
114
+ result = func(*args, **kwargs)
115
+ end_time = time.time()
116
+ logger.info(f"⏱ {func.__name__} executed in {end_time - start_time:.2f} seconds")
117
+ return result
118
+ return wrapper
119
+
120
+ # Configure logging
121
+ logging.basicConfig(
122
+ level=logging.INFO,
123
+ format="%(asctime)s [%(levelname)s] %(message)s",
124
+ handlers=[
125
+ logging.FileHandler(str(LOGS_DIR / "app.log")),
126
+ logging.StreamHandler()
127
+ ]
128
+ )
129
+
130
+ logger = logging.getLogger(__name__)
131
+
132
+
133
  class GameState(TypedDict):
134
  project_json: dict
135
  description: str
 
1435
  import json
1436
  os.makedirs(project_folder, exist_ok=True)
1437
 
1438
+ backdrop_base_path = os.path.normpath(str(BACKDROP_DIR))
1439
+ sprite_base_path = os.path.normpath(str(SPRITE_DIR))
1440
+ code_blocks_path = os.path.normpath(str(CODE_BLOCKS_DIR))
 
 
 
 
 
1441
 
1442
+ project_json_path = os.path.join(project_folder, "project.json")
1443
 
1444
  # -------------------------
1445
  # Build sprite images list (BytesIO) from sprites_data
 
1948
 
1949
  # print("---")
1950
  # add at top of file
1951
+ import shutil
1952
+ import json
1953
+ import os
1954
+ from pathlib import Path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1955
 
1956
+ # normalize base paths once before the loop
1957
+ sprite_base_p = Path(sprite_base_path).resolve(strict=False)
1958
+ backdrop_base_p = Path(backdrop_base_path).resolve(strict=False)
1959
+ project_folder_p = Path(project_folder)
1960
+ project_folder_p.mkdir(parents=True, exist_ok=True)
1961
 
1962
+ copied_sprite_folders = set()
1963
+ copied_backdrop_folders = set()
1964
 
1965
+ def display_like_windows_no_lead(p: Path) -> str:
1966
+ """
1967
+ For human-readable logs only β€” convert Path to a string like:
1968
+ "app\\blocks\\Backdrops\\Castle 2.sb3" (no leading slash).
1969
+ """
1970
+ s = p.as_posix() # forward-slash string, safe for Path objects
1971
+ if s.startswith("/"):
1972
+ s = s[1:]
1973
+ return s.replace("/", "\\")
1974
 
1975
+ def is_subpath(child: Path, parent: Path) -> bool:
1976
+ """Robust membership test: is child under parent?"""
1977
+ try:
1978
+ # use non-strict resolve only if needed, but avoid exceptions
1979
+ child.relative_to(parent)
1980
+ return True
1981
+ except Exception:
1982
+ return False
 
 
 
 
 
1983
 
1984
+ # Flatten unique matched indices (if not already)
1985
+ matched_indices = sorted({idx for lst in per_sprite_matched_indices for idx in lst})
1986
+ print("matched_indices------------------>", matched_indices)
 
 
 
1987
 
1988
+ for matched_idx in matched_indices:
1989
+ # defensive check
1990
+ if not (0 <= matched_idx < len(paths_list)):
1991
+ print(f" ⚠ matched_idx {matched_idx} out of range, skipping")
1992
+ continue
 
 
 
 
 
 
 
 
 
 
1993
 
1994
+ matched_image_path = paths_list[matched_idx]
1995
+ matched_path_p = Path(matched_image_path).resolve(strict=False) # keep as Path
1996
+ matched_folder_p = matched_path_p.parent # Path object
1997
+ matched_filename = matched_path_p.name
 
 
1998
 
1999
+ # Prepare display-only string (do NOT reassign matched_folder_p)
2000
+ matched_folder_display = display_like_windows_no_lead(matched_folder_p)
 
 
 
 
 
 
 
 
 
2001
 
2002
+ print(f"Processing matched image: {matched_image_path}")
2003
+ print(f" - Folder: {matched_folder_display}")
2004
+ print(f" - Sprite path: {display_like_windows_no_lead(sprite_base_p)}")
2005
+ print(f" - Backdrop path: {display_like_windows_no_lead(backdrop_base_p)}")
2006
+ print(f" - Filename: {matched_filename}")
 
2007
 
2008
+ # Use a canonical string to store in the copied set (POSIX absolute-ish)
2009
+ folder_key = matched_folder_p.as_posix()
 
 
 
 
 
 
 
 
 
 
 
 
 
2010
 
2011
+ # ---------- SPRITE ----------
2012
+ if is_subpath(matched_folder_p, sprite_base_p) and folder_key not in copied_sprite_folders:
2013
+ print(f"Processing SPRITE folder: {matched_folder_display}")
2014
+ copied_sprite_folders.add(folder_key)
 
 
 
 
 
 
 
 
 
 
 
 
2015
 
2016
+ sprite_json_path = matched_folder_p / "sprite.json"
2017
+ print("sprite_json_path----------------------->", sprite_json_path)
2018
+ print("copied sprite folder----------------------->", copied_sprite_folders)
2019
+ if sprite_json_path.exists() and sprite_json_path.is_file():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2020
  try:
2021
+ with sprite_json_path.open("r", encoding="utf-8") as f:
2022
  sprite_info = json.load(f)
2023
  project_data.append(sprite_info)
2024
+ print(f" βœ“ Successfully read sprite.json from {matched_folder_display}")
2025
  except Exception as e:
2026
+ print(f" βœ— Failed to read sprite.json in {matched_folder_display}: {repr(e)}")
2027
  else:
2028
+ print(f" ⚠ No sprite.json in {matched_folder_display}")
2029
+
2030
+ # copy non-matching files from the sprite folder (except matched image and sprite.json)
2031
+ try:
2032
+ sprite_files = list(matched_folder_p.iterdir())
2033
+ except Exception as e:
2034
+ sprite_files = []
2035
+ print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2036
+
2037
+ print(f" Files in sprite folder: {[p.name for p in sprite_files]}")
2038
+ for p in sprite_files:
2039
+ fname = p.name
2040
  if fname in (matched_filename, "sprite.json"):
2041
  print(f" Skipping {fname} (matched image or sprite.json)")
2042
  continue
2043
+ if p.is_file():
2044
+ dst = project_folder_p / fname
 
2045
  try:
2046
+ shutil.copy2(str(p), str(dst))
2047
+ print(f" βœ“ Copied sprite asset: {p} -> {dst}")
2048
  except Exception as e:
2049
+ print(f" βœ— Failed to copy sprite asset {p}: {repr(e)}")
2050
  else:
2051
  print(f" Skipping {fname} (not a file)")
2052
+
2053
+ # ---------- BACKDROP ----------
2054
+ if is_subpath(matched_folder_p, backdrop_base_p) and folder_key not in copied_backdrop_folders:
2055
+ print(f"Processing BACKDROP folder: {matched_folder_display}")
2056
+ copied_backdrop_folders.add(folder_key)
2057
+ print("backdrop_base_path----------------------->", display_like_windows_no_lead(backdrop_base_p))
2058
+ print("copied backdrop folder----------------------->", copied_backdrop_folders)
2059
+
2060
  # copy matched backdrop image
2061
+ backdrop_src = matched_folder_p / matched_filename
2062
+ backdrop_dst = project_folder_p / matched_filename
2063
+ if backdrop_src.exists() and backdrop_src.is_file():
2064
+ try:
2065
+ shutil.copy2(str(backdrop_src), str(backdrop_dst))
2066
+ print(f" βœ“ Copied matched backdrop image: {backdrop_src} -> {backdrop_dst}")
2067
+ except Exception as e:
2068
+ print(f" βœ— Failed to copy matched backdrop image {backdrop_src}: {repr(e)}")
2069
+ else:
2070
+ print(f" ⚠ Matched backdrop source not found: {backdrop_src}")
2071
+
2072
+ # copy other files from folder (skip project.json and matched image)
2073
  try:
2074
+ backdrop_files = list(matched_folder_p.iterdir())
 
2075
  except Exception as e:
2076
+ backdrop_files = []
2077
+ print(f" βœ— Failed to list files in {matched_folder_display}: {repr(e)}")
2078
+
2079
+ print(f" Files in backdrop folder: {[p.name for p in backdrop_files]}")
2080
+ for p in backdrop_files:
2081
+ fname = p.name
2082
  if fname in (matched_filename, "project.json"):
2083
  print(f" Skipping {fname} (matched image or project.json)")
2084
  continue
2085
+ if p.is_file():
2086
+ dst = project_folder_p / fname
 
 
 
2087
  try:
2088
+ shutil.copy2(str(p), str(dst))
2089
+ print(f" βœ“ Copied backdrop asset: {p} -> {dst}")
2090
  except Exception as e:
2091
+ print(f" βœ— Failed to copy backdrop asset {p}: {repr(e)}")
2092
  else:
2093
  print(f" Skipping {fname} (not a file)")
2094
+
2095
  # read project.json to extract Stage/targets
2096
+ pj = matched_folder_p / "project.json"
2097
+ if pj.exists() and pj.is_file():
 
2098
  try:
2099
+ with pj.open("r", encoding="utf-8") as f:
2100
  bd_json = json.load(f)
2101
  stage_count = 0
2102
  for tgt in bd_json.get("targets", []):
2103
  if tgt.get("isStage"):
2104
  backdrop_data.append(tgt)
2105
  stage_count += 1
2106
+ print(f" βœ“ Successfully read project.json from {matched_folder_display}, found {stage_count} stage(s)")
2107
  except Exception as e:
2108
+ print(f" βœ— Failed to read project.json in {matched_folder_display}: {repr(e)}")
2109
  else:
2110
+ print(f" ⚠ No project.json in {matched_folder_display}")
2111
+
2112
  print("---")
2113
+ # for matched_idx in matched_indices:
2114
+ # matched_image_path = paths_list[matched_idx]
2115
+ # matched_folder = os.path.dirname(matched_image_path)
2116
+ # matched_filename = os.path.basename(matched_image_path)
2117
+
2118
+ # print(f"Processing matched image: {matched_image_path}")
2119
+ # print(f" - Folder: {matched_folder}")
2120
+ # print(f" - Sprite path: {sprite_base_path}")
2121
+ # print(f" - Backdrop path: {backdrop_base_path}")
2122
+ # print(f" - Filename: {matched_filename}")
2123
+
2124
+ # # If it's a sprite (under SPRITE_DIR) -> copy sprite assets and read sprite.json
2125
+ # if matched_folder.startswith(sprite_base_path) and matched_folder not in copied_sprite_folders:
2126
+ # print(f"Processing SPRITE folder: {matched_folder}")
2127
+ # copied_sprite_folders.add(matched_folder)
2128
+ # sprite_json_path = os.path.join(matched_folder, "sprite.json")
2129
+ # print("sprite_json_path----------------------->",sprite_json_path)
2130
+ # print("copied sprite folder----------------------->",copied_sprite_folders)
2131
+ # if os.path.exists(sprite_json_path):
2132
+ # try:
2133
+ # with open(sprite_json_path, "r", encoding="utf-8") as f:
2134
+ # sprite_info = json.load(f)
2135
+ # project_data.append(sprite_info)
2136
+ # print(f" βœ“ Successfully read sprite.json from {matched_folder}")
2137
+ # except Exception as e:
2138
+ # print(f" βœ— Failed to read sprite.json in {matched_folder}: {e}")
2139
+ # else:
2140
+ # print(f" ⚠ No sprite.json in {matched_folder}")
2141
+
2142
+ # # copy non-matching files from the sprite folder (except the matched image and sprite.json)
2143
+ # sprite_files = os.listdir(matched_folder)
2144
+ # print(f" Files in sprite folder: {sprite_files}")
2145
+ # for fname in sprite_files:
2146
+ # if fname in (matched_filename, "sprite.json"):
2147
+ # print(f" Skipping {fname} (matched image or sprite.json)")
2148
+ # continue
2149
+ # src = os.path.join(matched_folder, fname)
2150
+ # dst = os.path.join(project_folder, fname)
2151
+ # if os.path.isfile(src):
2152
+ # try:
2153
+ # shutil.copy2(src, dst)
2154
+ # print(f" βœ“ Copied sprite asset: {src} -> {dst}")
2155
+ # except Exception as e:
2156
+ # print(f" βœ— Failed to copy sprite asset {src}: {e}")
2157
+ # else:
2158
+ # print(f" Skipping {fname} (not a file)")
2159
+
2160
+ # # If it's a backdrop (under BACKDROP_DIR) -> copy backdrop assets and read project.json for stage
2161
+ # if matched_folder.startswith(backdrop_base_path) and matched_folder not in copied_backdrop_folders:
2162
+ # print(f"Processing BACKDROP folder: {matched_folder}")
2163
+ # copied_backdrop_folders.add(matched_folder)
2164
+ # print("backdrop_base_path----------------------->",backdrop_base_path)
2165
+ # print("copied backdrop folder----------------------->",copied_backdrop_folders)
2166
+ # # copy matched backdrop image
2167
+ # backdrop_dst = os.path.join(project_folder, matched_filename)
2168
+ # try:
2169
+ # shutil.copy2(matched_image_path, backdrop_dst)
2170
+ # print(f" βœ“ Copied matched backdrop image: {matched_image_path} -> {backdrop_dst}")
2171
+ # except Exception as e:
2172
+ # print(f" βœ— Failed to copy matched backdrop image {matched_image_path}: {e}")
2173
+
2174
+ # # copy other files from folder (skip project.json and matched image)
2175
+ # backdrop_files = os.listdir(matched_folder)
2176
+ # print(f" Files in backdrop folder: {backdrop_files}")
2177
+ # for fname in backdrop_files:
2178
+ # if fname in (matched_filename, "project.json"):
2179
+ # print(f" Skipping {fname} (matched image or project.json)")
2180
+ # continue
2181
+ # src = os.path.join(matched_folder, fname)
2182
+ # dst = os.path.join(project_folder, fname)
2183
+ # if os.path.isfile(src):
2184
+ # try:
2185
+ # shutil.copy2(src, dst)
2186
+ # print(f" βœ“ Copied backdrop asset: {src} -> {dst}")
2187
+ # except Exception as e:
2188
+ # print(f" βœ— Failed to copy backdrop asset {src}: {e}")
2189
+ # else:
2190
+ # print(f" Skipping {fname} (not a file)")
2191
+
2192
+ # # read project.json to extract Stage/targets
2193
+ # pj = os.path.join(matched_folder, "project.json")
2194
+ # if os.path.exists(pj):
2195
+ # try:
2196
+ # with open(pj, "r", encoding="utf-8") as f:
2197
+ # bd_json = json.load(f)
2198
+ # stage_count = 0
2199
+ # for tgt in bd_json.get("targets", []):
2200
+ # if tgt.get("isStage"):
2201
+ # backdrop_data.append(tgt)
2202
+ # stage_count += 1
2203
+ # print(f" βœ“ Successfully read project.json from {matched_folder}, found {stage_count} stage(s)")
2204
+ # except Exception as e:
2205
+ # print(f" βœ— Failed to read project.json in {matched_folder}: {e}")
2206
+ # else:
2207
+ # print(f" ⚠ No project.json in {matched_folder}")
2208
+
2209
+ # print("---")
2210
 
2211
  # --- Merge into final Scratch project.json (identical logic to before)
2212
  final_project = {