| import argparse |
| import json |
| from datetime import datetime, timezone |
| from pathlib import Path |
|
|
|
|
| DEFAULT_EXTENSIONS = {".cs", ".js", ".md", ".txt"} |
| SKIP_DIRS = { |
| ".git", |
| "Library", |
| "Temp", |
| "Obj", |
| "Build", |
| "Builds", |
| "Logs", |
| "UserSettings", |
| } |
|
|
|
|
| def should_skip(path): |
| return path.suffix.lower() == ".meta" or any(part in SKIP_DIRS for part in path.parts) |
|
|
|
|
| def iter_files(root, extensions): |
| for path in sorted(root.rglob("*")): |
| if not path.is_file() or should_skip(path): |
| continue |
| if path.suffix.lower() in extensions: |
| yield path |
|
|
|
|
| def file_type_for(path): |
| name = path.name.lower() |
| suffix = path.suffix.lower() |
| if name.endswith(".build.cs") or name.endswith(".target.cs"): |
| return "unreal-build-csharp" |
| if suffix == ".cs": |
| return "csharp" |
| if suffix in {".cpp", ".cc", ".cxx"}: |
| return "cpp" |
| if suffix in {".h", ".hpp", ".hh"}: |
| return "cpp-header" |
| if suffix == ".js": |
| return "javascript" |
| return "notes" |
|
|
|
|
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--scripts-dir", required=True) |
| parser.add_argument("--out", default="data/clean/mmorpg_project_scripts.txt") |
| parser.add_argument("--metadata-out", default="data/metadata/mmorpg_project_scripts.jsonl") |
| parser.add_argument("--max-file-chars", type=int, default=12000) |
| parser.add_argument("--extension", action="append") |
| parser.add_argument("--domain-label", default="Unity MMORPG project") |
| parser.add_argument("--source-label", default="Scripts") |
| args = parser.parse_args() |
|
|
| root = Path(args.scripts_dir).resolve() |
| if not root.exists(): |
| raise SystemExit(f"Scripts directory not found: {root}") |
|
|
| extensions = {ext.lower() if ext.startswith(".") else f".{ext.lower()}" for ext in args.extension or []} |
| if not extensions: |
| extensions = DEFAULT_EXTENSIONS |
|
|
| documents = [] |
| included = 0 |
| skipped_empty = 0 |
| total_chars = 0 |
|
|
| for path in iter_files(root, extensions): |
| rel = path.relative_to(root).as_posix() |
| text = path.read_text(encoding="utf-8", errors="ignore").strip() |
| if len(text) < 20: |
| skipped_empty += 1 |
| continue |
| if len(text) > args.max_file_chars: |
| text = text[: args.max_file_chars].rsplit("\n", 1)[0].strip() |
|
|
| documents.append( |
| f"Domain: {args.domain_label}\n" |
| f"Source: {args.source_label}/{rel}\n" |
| f"Type: {file_type_for(path)}\n\n" |
| f"{text}\n" |
| ) |
| included += 1 |
| total_chars += len(text) |
|
|
| out_path = Path(args.out) |
| out_path.parent.mkdir(parents=True, exist_ok=True) |
| out_path.write_text("\n\n<|eos|>\n\n".join(documents) + "\n", encoding="utf-8") |
|
|
| metadata = { |
| "source": "local Unity MMORPG project scripts", |
| "scripts_dir": str(root), |
| "domain_label": args.domain_label, |
| "source_label": args.source_label, |
| "output": str(out_path), |
| "extensions": sorted(extensions), |
| "included_files": included, |
| "skipped_empty_files": skipped_empty, |
| "total_chars": total_chars, |
| "prepared_at": datetime.now(timezone.utc).isoformat(), |
| } |
| metadata_path = Path(args.metadata_out) |
| metadata_path.parent.mkdir(parents=True, exist_ok=True) |
| metadata_path.write_text(json.dumps(metadata, ensure_ascii=False) + "\n", encoding="utf-8") |
|
|
| print(f"included files: {included}") |
| print(f"skipped empty: {skipped_empty}") |
| print(f"wrote {out_path} ({out_path.stat().st_size / 1024 / 1024:.2f} MiB)") |
| print(f"wrote {metadata_path}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|