WebashalarForML commited on
Commit
e1d72a3
Β·
verified Β·
1 Parent(s): 89acb88

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +240 -179
app.py CHANGED
@@ -1833,255 +1833,316 @@ def extract_images_from_pdf(pdf_path: Path):
1833
  except Exception as e:
1834
  raise RuntimeError(f"❌ Error in extract_images_from_pdf: {str(e)}")
1835
 
1836
- def similarity_matching(input_json_path: str, project_folder:str) -> str:
1837
-
1838
- logger.info("πŸ” Running similarity matching...")
1839
  os.makedirs(project_folder, exist_ok=True)
1840
- # ============================== #
1841
- # DEFINE PATHS #
1842
- # ============================== #
1843
- #image_dirs = [backdrop_images_path, sprite_images_path]
1844
- print(" --------------------------------------- input_json_path ---------------------------------------", input_json_path)
 
 
1845
  project_json_path = os.path.join(project_folder, "project.json")
1846
-
1847
- # ============================== #
1848
- # READ SPRITE METADATA #
1849
- # ============================== #
1850
  with open(input_json_path, 'r') as f:
1851
  sprites_data = json.load(f)
1852
 
1853
  sprite_ids, texts, sprite_base64 = [], [], []
1854
  for sid, sprite in sprites_data.items():
1855
  sprite_ids.append(sid)
1856
- texts.append(
1857
- "This is " + sprite.get("description", sprite.get("name", "")))
1858
  sprite_base64.append(sprite["base64"])
1859
 
1860
- # ========================================= #
1861
- # Walk folders to collect all image paths #
1862
- # ========================================= #
1863
  folder_image_paths = [
1864
- #backdrops
1865
- BACKDROP_DIR / "badroom3.sb3" / "8cc0b88d53345b3e337e8f028a32a4e7.png",
1866
- BACKDROP_DIR / "baseball2.sb3" / "7be1f5b3e682813dac1f297e52ff7dca.png",
1867
- BACKDROP_DIR / "beach_malibu.sb3" / "050615fe992a00d6af0e664e497ebf53.png",
1868
- BACKDROP_DIR / "castle2.sb3" / "951765ee7f7370f120c9df20b577c22f.png",
1869
- BACKDROP_DIR / "hall.sb3" / "ea86ca30b346f27ca5faf1254f6a31e3.png",
1870
- BACKDROP_DIR / "jungle.sb3" / "f4f908da19e2753f3ed679d7b37650ca.png",
1871
- #sprite
1872
- SPRITE_DIR / "Batter.sprite3" / "baseball_sprite_motion_1.png",
1873
- SPRITE_DIR / "Bear.sprite3" / "bear_motion_2.png",
1874
- SPRITE_DIR / "Beetle.sprite3" / "46d0dfd4ae7e9bfe3a6a2e35a4905eae.png",
1875
- SPRITE_DIR / "cat" / "cat_motion_1.png",
1876
- SPRITE_DIR / "Centaur.sprite3" / "2373556e776cad3ba4d6ee04fc34550b.png",
1877
- SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
1878
- SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
1879
  ]
1880
- print(" --------------------------------------- folder_image_paths ---------------------------------------\n", folder_image_paths)
1881
- # ============================== #
1882
- # DECODE SPRITE IMAGES #
1883
- # ============================== #
1884
- # temp_dir = tempfile.mkdtemp()
1885
- # sprite_image_paths = []
1886
- # for idx, b64 in enumerate(sprite_base64):
1887
- # image_data = base64.b64decode(b64.split(",")[-1])
1888
- # img = Image.open(BytesIO(image_data)).convert("RGB")
1889
- # temp_path = os.path.join(temp_dir, f"sprite_{idx}.png")
1890
- # img.save(temp_path)
1891
- # sprite_image_paths.append(temp_path)
1892
- # print(f"\n\n\nSPRITE IMAGE PATHS: \n{sprite_image_paths}")
1893
-
1894
- # # ============================== #
1895
- # # EMBED SPRITE IMAGES #
1896
- # # ============================== #
1897
- # sprite_features = clip_embd.embed_image(sprite_base64)
1898
-
1899
- # # ============================== #
1900
- # # COMPUTE SIMILARITIES #
1901
- # # ============================== #
1902
- # with open(f"{BLOCKS_DIR}/embeddings.json", "r") as f:
1903
- # embedding_json = json.load(f)
1904
- # # print(f"\n\n EMBEDDING JSON: {embedding_json}")
1905
-
1906
- # img_matrix = np.array([img["embeddings"] for img in embedding_json])
1907
- # sprite_matrix = np.array(sprite_features)
1908
-
1909
- # similarity = np.matmul(sprite_matrix, img_matrix.T)
1910
 
1911
- # most_similar_indices = np.argmax(similarity, axis=1)
1912
- # ========================================= #
1913
- # Load reference embeddings from JSON file #
1914
- # ========================================= #
1915
  with open(f"{BLOCKS_DIR}/embeddings.json", "r") as f:
1916
  embedding_json = json.load(f)
1917
  img_matrix = np.array([img["embeddings"] for img in embedding_json])
1918
 
1919
- # ============================== #
1920
- # EMBED SPRITE IMAGES #
1921
- # ============================== #
1922
  sprite_features = []
1923
  for b64 in sprite_base64:
1924
- # strip data URI if present
1925
  if "," in b64:
1926
  b64 = b64.split(",", 1)[1]
1927
  img_bytes = base64.b64decode(b64)
1928
  pil_img = Image.open(BytesIO(img_bytes)).convert("RGB")
1929
-
1930
  buf = BytesIO()
1931
  pil_img.save(buf, format="PNG")
1932
  buf.seek(0)
1933
-
1934
- # 4) pass the buffer inside a list
1935
- feats_list = clip_embd.embed_image([buf])
1936
- feats = feats_list[0]
1937
  sprite_features.append(feats)
1938
-
1939
- # stack into (n_sprites, dim)
1940
  sprite_matrix = np.vstack(sprite_features)
1941
 
1942
- # ============================== #
1943
- # COMPUTE SIMILARITIES #
1944
- # ============================== #
1945
  similarity = np.matmul(sprite_matrix, img_matrix.T)
1946
  most_similar_indices = np.argmax(similarity, axis=1)
1947
- print(f"")
1948
- # ============= Match and copy ===============
1949
- project_data = []
 
 
1950
  copied_folders = set()
1951
 
1952
- # =============================================================== #
1953
- # Loop through most similar images from Sprites folder #
1954
- # β†’ Copy sprite assets (excluding matched image + sprite.json) #
1955
- # β†’ Load sprite.json and append its data to project_data #
1956
- # =============================================================== #
1957
  for sprite_idx, matched_idx in enumerate(most_similar_indices):
1958
  matched_image_path = folder_image_paths[matched_idx]
1959
- matched_image_path = os.path.normpath(matched_image_path)
1960
- print(" --------------------------------------1- matched_image_path ---------------------------------------",matched_image_path)
1961
- matched_folder = os.path.dirname(matched_image_path)
1962
- #folder_name = os.path.basename(matched_folder)
1963
- print(" --------------------------------------1- matched_folder ---------------------------------------",matched_folder)
 
1964
  if matched_folder in copied_folders:
1965
  continue
1966
  copied_folders.add(matched_folder)
1967
- logger.info(f"Matched image path: {matched_image_path}")
1968
 
1969
  sprite_json_path = os.path.join(matched_folder, 'sprite.json')
1970
- print(" --------------------------------------- sprite_json_path ---------------------------------------",sprite_json_path)
1971
  if not os.path.exists(sprite_json_path):
1972
- logger.warning(f"sprite.json not found in: {matched_folder}")
1973
  continue
1974
 
1975
  with open(sprite_json_path, 'r') as f:
1976
- sprite_data = json.load(f)
1977
- # print(f"SPRITE DATA: \n{sprite_data}")
1978
- # # Copy only non-matched files
1979
- # for fname in os.listdir(matched_folder):
1980
- # fpath = os.path.join(matched_folder, fname)
1981
- # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'sprite.json'}:
1982
- # shutil.copy2(fpath, os.path.join(project_folder, fname))
1983
- # # logger.info(f"Copied Sprite asset: {fname}")
1984
- project_data.append(sprite_data)
1985
- print(" --------------------------------------1- project_data ---------------------------------------",project_data)
1986
  for fname in os.listdir(matched_folder):
1987
- fpath = os.path.join(matched_folder, fname)
1988
- dest_path = os.path.join(project_folder, fname)
1989
- if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'sprite.json'}:
1990
- shutil.copy2(fpath, dest_path)
1991
- logger.info(f"🟒 Copied Sprite Asset: {fpath} β†’ {dest_path}")
1992
-
1993
- # ================================================================== #
1994
- # Loop through most similar images from Backdrops folder #
1995
- # β†’ Copy Backdrop assets (excluding matched image + project.json) #
1996
- # β†’ Load project.json and append its data to project_data #
1997
- # ================================================================== #
1998
- backdrop_data = [] # for backdrop-related entries
1999
 
2000
  for backdrop_idx, matched_idx in enumerate(most_similar_indices):
2001
- matched_image_path = os.path.normpath(folder_image_paths[matched_idx])
2002
- print(" --------------------------------------2- matched_image_path ---------------------------------------",matched_image_path)
2003
- # Check if the match is from the Backdrops folder
2004
- if matched_image_path.startswith(os.path.normpath(backdrop_images_path)):
2005
- matched_folder = os.path.dirname(matched_image_path)
2006
- print(" --------------------------------------2- matched_folder ---------------------------------------",matched_folder)
2007
- folder_name = os.path.basename(matched_folder)
2008
-
2009
- logger.info(f"Backdrop matched image: {matched_image_path}")
2010
-
2011
- # Copy only non-matched files
2012
- # for fname in os.listdir(matched_folder):
2013
- # fpath = os.path.join(matched_folder, fname)
2014
- # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'project.json'}:
2015
- # shutil.copy2(fpath, os.path.join(project_folder, fname))
2016
- # # logger.info(f"Copied Backdrop asset: {fname}")
2017
- for fname in os.listdir(matched_folder):
2018
- fpath = os.path.join(matched_folder, fname)
2019
- dest_path = os.path.join(project_folder, fname)
2020
- if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'project.json'}:
2021
- shutil.copy2(fpath, dest_path)
2022
- logger.info(f"🟑 Copied Backdrop Asset: {fpath} β†’ {dest_path}")
2023
-
2024
-
2025
- # Append backdrop's project.json
2026
- backdrop_json_path = os.path.join(matched_folder, 'project.json')
2027
- print(" --------------------------------------2- backdrop_json_path ---------------------------------------",backdrop_json_path)
2028
- if os.path.exists(backdrop_json_path):
2029
- with open(backdrop_json_path, 'r') as f:
2030
- backdrop_json_data = json.load(f)
2031
- # print(f"SPRITE DATA: \n{backdrop_json_data}")
2032
- if "targets" in backdrop_json_data:
2033
- for target in backdrop_json_data["targets"]:
2034
- if target.get("isStage") == True:
2035
- backdrop_data.append(target)
2036
- else:
2037
- logger.warning(f"project.json not found in: {matched_folder}")
2038
 
2039
- # Merge JSON structure
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2040
  final_project = {
2041
- "targets": [],
2042
- "monitors": [],
2043
- "extensions": [],
2044
  "meta": {
2045
  "semver": "3.0.0",
2046
  "vm": "11.3.0",
2047
- "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
2048
  }
2049
  }
 
 
 
 
2050
 
2051
- for sprite in project_data:
2052
- if not sprite.get("isStage", False):
2053
- final_project["targets"].append(sprite)
2054
-
2055
  if backdrop_data:
2056
  all_costumes, sounds = [], []
2057
- for idx, bd in enumerate(backdrop_data):
2058
  all_costumes.extend(bd.get("costumes", []))
2059
- if idx == 0 and "sounds" in bd:
2060
- sounds = bd["sounds"]
2061
  final_project["targets"].append({
2062
  "isStage": True,
2063
  "name": "Stage",
2064
- "variables": {},
2065
- "lists": {},
2066
- "broadcasts": {},
2067
- "blocks": {},
2068
- "comments": {},
2069
  "currentCostume": 1 if len(all_costumes) > 1 else 0,
2070
  "costumes": all_costumes,
2071
  "sounds": sounds,
2072
- "volume": 100,
2073
- "layerOrder": 0,
2074
- "tempo": 60,
2075
- "videoTransparency": 50,
2076
- "videoState": "on",
2077
- "textToSpeechLanguage": None
2078
  })
2079
 
2080
  with open(project_json_path, 'w') as f:
2081
  json.dump(final_project, f, indent=2)
2082
 
2083
- # logger.info(f"πŸŽ‰ Final project saved: {project_json_path}")
2084
  return project_json_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2085
 
2086
  def delay_for_tpm_node(state: GameState):
2087
  logger.info("--- Running DelayForTPMNode ---")
 
1833
  except Exception as e:
1834
  raise RuntimeError(f"❌ Error in extract_images_from_pdf: {str(e)}")
1835
 
1836
+ def similarity_matching(input_json_path: str, project_folder: str) -> str:
1837
+ logger.info("πŸ” Running similarity matching…")
 
1838
  os.makedirs(project_folder, exist_ok=True)
1839
+
1840
+ # ----------------------------------------
1841
+ # CHANGED: define normalized base-paths so startswith() checks work
1842
+ backdrop_base_path = os.path.normpath(str(BACKDROP_DIR))
1843
+ sprite_base_path = os.path.normpath(str(SPRITE_DIR))
1844
+ # ----------------------------------------
1845
+
1846
  project_json_path = os.path.join(project_folder, "project.json")
1847
+
1848
+ # ==============================
1849
+ # READ SPRITE METADATA
1850
+ # ==============================
1851
  with open(input_json_path, 'r') as f:
1852
  sprites_data = json.load(f)
1853
 
1854
  sprite_ids, texts, sprite_base64 = [], [], []
1855
  for sid, sprite in sprites_data.items():
1856
  sprite_ids.append(sid)
1857
+ texts.append("This is " + sprite.get("description", sprite.get("name", "")))
 
1858
  sprite_base64.append(sprite["base64"])
1859
 
1860
+ # =========================================
1861
+ # Build the list of all candidate images
1862
+ # =========================================
1863
  folder_image_paths = [
1864
+ # backdrops
1865
+ BACKDROP_DIR / "badroom3.sb3" / "8cc0b88d53345b3e337e8f028a32a4e7.png",
1866
+ BACKDROP_DIR / "baseball2.sb3" / "7be1f5b3e682813dac1f297e52ff7dca.png",
1867
+ BACKDROP_DIR / "beach_malibu.sb3" / "050615fe992a00d6af0e664e497ebf53.png",
1868
+ BACKDROP_DIR / "castle2.sb3" / "951765ee7f7370f120c9df20b577c22f.png",
1869
+ BACKDROP_DIR / "hall.sb3" / "ea86ca30b346f27ca5faf1254f6a31e3.png",
1870
+ BACKDROP_DIR / "jungle.sb3" / "f4f908da19e2753f3ed679d7b37650ca.png",
1871
+ # sprites
1872
+ SPRITE_DIR / "Batter.sprite3" / "baseball_sprite_motion_1.png",
1873
+ SPRITE_DIR / "Bear.sprite3" / "bear_motion_2.png",
1874
+ SPRITE_DIR / "Beetle.sprite3" / "46d0dfd4ae7e9bfe3a6a2e35a4905eae.png",
1875
+ SPRITE_DIR / "cat" / "cat_motion_1.png",
1876
+ SPRITE_DIR / "Centaur.sprite3" / "2373556e776cad3ba4d6ee04fc34550b.png",
1877
+ SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
1878
+ SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
1879
  ]
1880
+ folder_image_paths = [os.path.normpath(str(p)) for p in folder_image_paths]
1881
+ # =========================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1882
 
1883
+ # -----------------------------------------
1884
+ # Load reference embeddings from JSON
1885
+ # -----------------------------------------
 
1886
  with open(f"{BLOCKS_DIR}/embeddings.json", "r") as f:
1887
  embedding_json = json.load(f)
1888
  img_matrix = np.array([img["embeddings"] for img in embedding_json])
1889
 
1890
+ # =========================================
1891
+ # Decode & embed each sprite image
1892
+ # =========================================
1893
  sprite_features = []
1894
  for b64 in sprite_base64:
 
1895
  if "," in b64:
1896
  b64 = b64.split(",", 1)[1]
1897
  img_bytes = base64.b64decode(b64)
1898
  pil_img = Image.open(BytesIO(img_bytes)).convert("RGB")
 
1899
  buf = BytesIO()
1900
  pil_img.save(buf, format="PNG")
1901
  buf.seek(0)
1902
+ feats = clip_embd.embed_image([buf])[0]
 
 
 
1903
  sprite_features.append(feats)
 
 
1904
  sprite_matrix = np.vstack(sprite_features)
1905
 
1906
+ # =========================================
1907
+ # Compute similarities & pick best match
1908
+ # =========================================
1909
  similarity = np.matmul(sprite_matrix, img_matrix.T)
1910
  most_similar_indices = np.argmax(similarity, axis=1)
1911
+
1912
+ # =========================================
1913
+ # Copy matched sprite assets + collect data
1914
+ # =========================================
1915
+ project_data = []
1916
  copied_folders = set()
1917
 
 
 
 
 
 
1918
  for sprite_idx, matched_idx in enumerate(most_similar_indices):
1919
  matched_image_path = folder_image_paths[matched_idx]
1920
+ matched_folder = os.path.dirname(matched_image_path)
1921
+
1922
+ # CHANGED: use our new normalized sprite_base_path
1923
+ if not matched_folder.startswith(sprite_base_path):
1924
+ continue
1925
+
1926
  if matched_folder in copied_folders:
1927
  continue
1928
  copied_folders.add(matched_folder)
1929
+ logger.info(f"Matched sprite: {matched_image_path}")
1930
 
1931
  sprite_json_path = os.path.join(matched_folder, 'sprite.json')
 
1932
  if not os.path.exists(sprite_json_path):
1933
+ logger.warning(f"No sprite.json in {matched_folder}")
1934
  continue
1935
 
1936
  with open(sprite_json_path, 'r') as f:
1937
+ sprite_info = json.load(f)
1938
+ # copy all non‐matched files
 
 
 
 
 
 
 
 
1939
  for fname in os.listdir(matched_folder):
1940
+ if fname in (os.path.basename(matched_image_path), 'sprite.json'):
1941
+ continue
1942
+ shutil.copy2(os.path.join(matched_folder, fname),
1943
+ os.path.join(project_folder, fname))
1944
+ project_data.append(sprite_info)
1945
+
1946
+ # =========================================
1947
+ # Copy matched backdrop assets + collect
1948
+ # =========================================
1949
+ backdrop_data = []
 
 
1950
 
1951
  for backdrop_idx, matched_idx in enumerate(most_similar_indices):
1952
+ matched_image_path = folder_image_paths[matched_idx]
1953
+ matched_folder = os.path.dirname(matched_image_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1954
 
1955
+ # CHANGED: use our new normalized backdrop_base_path
1956
+ if not matched_folder.startswith(backdrop_base_path):
1957
+ continue
1958
+
1959
+ logger.info(f"Matched backdrop: {matched_image_path}")
1960
+ # copy non‐matched files
1961
+ for fname in os.listdir(matched_folder):
1962
+ if fname in (os.path.basename(matched_image_path), 'project.json'):
1963
+ continue
1964
+ shutil.copy2(os.path.join(matched_folder, fname),
1965
+ os.path.join(project_folder, fname))
1966
+
1967
+ # append the stage‐target from its project.json
1968
+ pj = os.path.join(matched_folder, 'project.json')
1969
+ if os.path.exists(pj):
1970
+ with open(pj, 'r') as f:
1971
+ bd_json = json.load(f)
1972
+ for tgt in bd_json.get("targets", []):
1973
+ if tgt.get("isStage"):
1974
+ backdrop_data.append(tgt)
1975
+ else:
1976
+ logger.warning(f"No project.json in {matched_folder}")
1977
+
1978
+ # =========================================
1979
+ # Merge into final Scratch project.json
1980
+ # =========================================
1981
  final_project = {
1982
+ "targets": [], "monitors": [], "extensions": [],
 
 
1983
  "meta": {
1984
  "semver": "3.0.0",
1985
  "vm": "11.3.0",
1986
+ "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
1987
  }
1988
  }
1989
+ # sprites first
1990
+ for spr in project_data:
1991
+ if not spr.get("isStage", False):
1992
+ final_project["targets"].append(spr)
1993
 
1994
+ # then backdrop as the Stage
 
 
 
1995
  if backdrop_data:
1996
  all_costumes, sounds = [], []
1997
+ for i, bd in enumerate(backdrop_data):
1998
  all_costumes.extend(bd.get("costumes", []))
1999
+ if i == 0:
2000
+ sounds = bd.get("sounds", [])
2001
  final_project["targets"].append({
2002
  "isStage": True,
2003
  "name": "Stage",
2004
+ "variables": {}, "lists": {}, "broadcasts": {},
2005
+ "blocks": {}, "comments": {},
 
 
 
2006
  "currentCostume": 1 if len(all_costumes) > 1 else 0,
2007
  "costumes": all_costumes,
2008
  "sounds": sounds,
2009
+ "volume": 100, "layerOrder": 0,
2010
+ "tempo": 60, "videoTransparency": 50,
2011
+ "videoState": "on", "textToSpeechLanguage": None
 
 
 
2012
  })
2013
 
2014
  with open(project_json_path, 'w') as f:
2015
  json.dump(final_project, f, indent=2)
2016
 
 
2017
  return project_json_path
2018
+ # for sprite_idx, matched_idx in enumerate(most_similar_indices):
2019
+ # matched_image_path = folder_image_paths[matched_idx]
2020
+ # matched_image_path = os.path.normpath(matched_image_path)
2021
+ # print(" --------------------------------------1- matched_image_path ---------------------------------------",matched_image_path)
2022
+ # matched_folder = os.path.dirname(matched_image_path)
2023
+ # #folder_name = os.path.basename(matched_folder)
2024
+ # print(" --------------------------------------1- matched_folder ---------------------------------------",matched_folder)
2025
+ # if matched_folder in copied_folders:
2026
+ # continue
2027
+ # copied_folders.add(matched_folder)
2028
+ # logger.info(f"Matched image path: {matched_image_path}")
2029
+
2030
+ # sprite_json_path = os.path.join(matched_folder, 'sprite.json')
2031
+ # print(" --------------------------------------- sprite_json_path ---------------------------------------",sprite_json_path)
2032
+ # if not os.path.exists(sprite_json_path):
2033
+ # logger.warning(f"sprite.json not found in: {matched_folder}")
2034
+ # continue
2035
+
2036
+ # with open(sprite_json_path, 'r') as f:
2037
+ # sprite_data = json.load(f)
2038
+ # # print(f"SPRITE DATA: \n{sprite_data}")
2039
+ # # # Copy only non-matched files
2040
+ # # for fname in os.listdir(matched_folder):
2041
+ # # fpath = os.path.join(matched_folder, fname)
2042
+ # # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'sprite.json'}:
2043
+ # # shutil.copy2(fpath, os.path.join(project_folder, fname))
2044
+ # # # logger.info(f"Copied Sprite asset: {fname}")
2045
+ # project_data.append(sprite_data)
2046
+ # print(" --------------------------------------1- project_data ---------------------------------------",project_data)
2047
+ # for fname in os.listdir(matched_folder):
2048
+ # fpath = os.path.join(matched_folder, fname)
2049
+ # dest_path = os.path.join(project_folder, fname)
2050
+ # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'sprite.json'}:
2051
+ # shutil.copy2(fpath, dest_path)
2052
+ # logger.info(f"🟒 Copied Sprite Asset: {fpath} β†’ {dest_path}")
2053
+
2054
+ # # ================================================================== #
2055
+ # # Loop through most similar images from Backdrops folder #
2056
+ # # β†’ Copy Backdrop assets (excluding matched image + project.json) #
2057
+ # # β†’ Load project.json and append its data to project_data #
2058
+ # # ================================================================== #
2059
+ # backdrop_data = [] # for backdrop-related entries
2060
+
2061
+ # for backdrop_idx, matched_idx in enumerate(most_similar_indices):
2062
+ # matched_image_path = os.path.normpath(folder_image_paths[matched_idx])
2063
+ # print(" --------------------------------------2- matched_image_path ---------------------------------------",matched_image_path)
2064
+ # # Check if the match is from the Backdrops folder
2065
+ # if matched_image_path.startswith(os.path.normpath(backdrop_images_path)):
2066
+ # matched_folder = os.path.dirname(matched_image_path)
2067
+ # print(" --------------------------------------2- matched_folder ---------------------------------------",matched_folder)
2068
+ # folder_name = os.path.basename(matched_folder)
2069
+
2070
+ # logger.info(f"Backdrop matched image: {matched_image_path}")
2071
+
2072
+ # # Copy only non-matched files
2073
+ # # for fname in os.listdir(matched_folder):
2074
+ # # fpath = os.path.join(matched_folder, fname)
2075
+ # # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'project.json'}:
2076
+ # # shutil.copy2(fpath, os.path.join(project_folder, fname))
2077
+ # # # logger.info(f"Copied Backdrop asset: {fname}")
2078
+ # for fname in os.listdir(matched_folder):
2079
+ # fpath = os.path.join(matched_folder, fname)
2080
+ # dest_path = os.path.join(project_folder, fname)
2081
+ # if os.path.isfile(fpath) and fname not in {os.path.basename(matched_image_path), 'project.json'}:
2082
+ # shutil.copy2(fpath, dest_path)
2083
+ # logger.info(f"🟑 Copied Backdrop Asset: {fpath} β†’ {dest_path}")
2084
+
2085
+
2086
+ # # Append backdrop's project.json
2087
+ # backdrop_json_path = os.path.join(matched_folder, 'project.json')
2088
+ # print(" --------------------------------------2- backdrop_json_path ---------------------------------------",backdrop_json_path)
2089
+ # if os.path.exists(backdrop_json_path):
2090
+ # with open(backdrop_json_path, 'r') as f:
2091
+ # backdrop_json_data = json.load(f)
2092
+ # # print(f"SPRITE DATA: \n{backdrop_json_data}")
2093
+ # if "targets" in backdrop_json_data:
2094
+ # for target in backdrop_json_data["targets"]:
2095
+ # if target.get("isStage") == True:
2096
+ # backdrop_data.append(target)
2097
+ # else:
2098
+ # logger.warning(f"project.json not found in: {matched_folder}")
2099
+
2100
+ # # Merge JSON structure
2101
+ # final_project = {
2102
+ # "targets": [],
2103
+ # "monitors": [],
2104
+ # "extensions": [],
2105
+ # "meta": {
2106
+ # "semver": "3.0.0",
2107
+ # "vm": "11.3.0",
2108
+ # "agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
2109
+ # }
2110
+ # }
2111
+
2112
+ # for sprite in project_data:
2113
+ # if not sprite.get("isStage", False):
2114
+ # final_project["targets"].append(sprite)
2115
+
2116
+ # if backdrop_data:
2117
+ # all_costumes, sounds = [], []
2118
+ # for idx, bd in enumerate(backdrop_data):
2119
+ # all_costumes.extend(bd.get("costumes", []))
2120
+ # if idx == 0 and "sounds" in bd:
2121
+ # sounds = bd["sounds"]
2122
+ # final_project["targets"].append({
2123
+ # "isStage": True,
2124
+ # "name": "Stage",
2125
+ # "variables": {},
2126
+ # "lists": {},
2127
+ # "broadcasts": {},
2128
+ # "blocks": {},
2129
+ # "comments": {},
2130
+ # "currentCostume": 1 if len(all_costumes) > 1 else 0,
2131
+ # "costumes": all_costumes,
2132
+ # "sounds": sounds,
2133
+ # "volume": 100,
2134
+ # "layerOrder": 0,
2135
+ # "tempo": 60,
2136
+ # "videoTransparency": 50,
2137
+ # "videoState": "on",
2138
+ # "textToSpeechLanguage": None
2139
+ # })
2140
+
2141
+ # with open(project_json_path, 'w') as f:
2142
+ # json.dump(final_project, f, indent=2)
2143
+
2144
+ # # logger.info(f"πŸŽ‰ Final project saved: {project_json_path}")
2145
+ # return project_json_path
2146
 
2147
  def delay_for_tpm_node(state: GameState):
2148
  logger.info("--- Running DelayForTPMNode ---")