Merge branch 'main' into 'main'
Ace module, code 408, injecting fixes + separate option for speakers processing See merge request DazedAnon/DazedMTLTool!26
This commit is contained in:
commit
5a00b33f50
3 changed files with 1289 additions and 348 deletions
|
|
@ -256,6 +256,13 @@ class RPGMakerTab(QWidget):
|
||||||
self.join408_cb.setToolTip("Join 408 codes into a single string")
|
self.join408_cb.setToolTip("Join 408 codes into a single string")
|
||||||
left_column.addWidget(self.join408_cb)
|
left_column.addWidget(self.join408_cb)
|
||||||
|
|
||||||
|
self.speakers408_cb = QCheckBox("Process Speakers in 408")
|
||||||
|
self.speakers408_cb.setToolTip("Apply speaker detection and processing to code 408 (same as code 401)")
|
||||||
|
left_column.addWidget(self.speakers408_cb)
|
||||||
|
# Only show SPEAKERS408 for ACE engine (rpgmakerace.py)
|
||||||
|
if self.engine != "ACE":
|
||||||
|
self.speakers408_cb.hide()
|
||||||
|
|
||||||
left_column.addSpacing(15)
|
left_column.addSpacing(15)
|
||||||
|
|
||||||
# Main Codes
|
# Main Codes
|
||||||
|
|
@ -379,6 +386,8 @@ class RPGMakerTab(QWidget):
|
||||||
self.fixtextwrap_cb.stateChanged.disconnect()
|
self.fixtextwrap_cb.stateChanged.disconnect()
|
||||||
self.ignoretltext_cb.stateChanged.disconnect()
|
self.ignoretltext_cb.stateChanged.disconnect()
|
||||||
self.join408_cb.stateChanged.disconnect()
|
self.join408_cb.stateChanged.disconnect()
|
||||||
|
if self.engine == "ACE":
|
||||||
|
self.speakers408_cb.stateChanged.disconnect()
|
||||||
|
|
||||||
# Main Codes
|
# Main Codes
|
||||||
self.code401_cb.stateChanged.disconnect()
|
self.code401_cb.stateChanged.disconnect()
|
||||||
|
|
@ -415,6 +424,8 @@ class RPGMakerTab(QWidget):
|
||||||
self.fixtextwrap_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
self.fixtextwrap_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
||||||
self.ignoretltext_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
self.ignoretltext_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
||||||
self.join408_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
self.join408_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
||||||
|
if self.engine == "ACE":
|
||||||
|
self.speakers408_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
||||||
|
|
||||||
# Main Codes
|
# Main Codes
|
||||||
self.code401_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
self.code401_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
|
||||||
|
|
@ -473,6 +484,10 @@ class RPGMakerTab(QWidget):
|
||||||
"CODE111": self.code111_cb.isChecked(),
|
"CODE111": self.code111_cb.isChecked(),
|
||||||
"CODE108": self.code108_cb.isChecked(),
|
"CODE108": self.code108_cb.isChecked(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Only include SPEAKERS408 for ACE engine
|
||||||
|
if self.engine == "ACE":
|
||||||
|
config["SPEAKERS408"] = self.speakers408_cb.isChecked()
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
@ -485,6 +500,10 @@ class RPGMakerTab(QWidget):
|
||||||
self.fixtextwrap_cb.setChecked(config.get("FIXTEXTWRAP", True))
|
self.fixtextwrap_cb.setChecked(config.get("FIXTEXTWRAP", True))
|
||||||
self.ignoretltext_cb.setChecked(config.get("IGNORETLTEXT", False))
|
self.ignoretltext_cb.setChecked(config.get("IGNORETLTEXT", False))
|
||||||
self.join408_cb.setChecked(config.get("JOIN408", False))
|
self.join408_cb.setChecked(config.get("JOIN408", False))
|
||||||
|
|
||||||
|
# Only set SPEAKERS408 for ACE engine
|
||||||
|
if self.engine == "ACE":
|
||||||
|
self.speakers408_cb.setChecked(config.get("SPEAKERS408", False))
|
||||||
|
|
||||||
# Main Codes
|
# Main Codes
|
||||||
self.code401_cb.setChecked(config.get("CODE401", True))
|
self.code401_cb.setChecked(config.get("CODE401", True))
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -34,6 +34,7 @@ PBAR = None
|
||||||
FILENAME = None
|
FILENAME = None
|
||||||
TIMETOTAL = 0 # Total Time Taken for all translations
|
TIMETOTAL = 0 # Total Time Taken for all translations
|
||||||
VOCAB_LOCK = threading.Lock()
|
VOCAB_LOCK = threading.Lock()
|
||||||
|
PREFLIGHT_COUNT_MODE = False # When True, translateAI wrapper only counts units and never calls API
|
||||||
|
|
||||||
# Speakers
|
# Speakers
|
||||||
NAMESLIST = []
|
NAMESLIST = []
|
||||||
|
|
@ -433,10 +434,107 @@ def update_vocab_section(category: str, pairs: list[tuple[str, str]]):
|
||||||
|
|
||||||
def parseMap(data, filename):
|
def parseMap(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
totalLines = 0
|
|
||||||
events = data["events"]
|
events = data["events"]
|
||||||
global LOCK
|
global LOCK
|
||||||
|
|
||||||
|
# --- Preflight: estimate exact progress total using the same translation batching ---
|
||||||
|
class _CountingBar:
|
||||||
|
def __init__(self):
|
||||||
|
self.n = 0
|
||||||
|
def update(self, n=1):
|
||||||
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
# Silent during preflight
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_map_units(d, fname) -> int:
|
||||||
|
# Use a deep copy to avoid mutating real data during estimation
|
||||||
|
dcopy = copy.deepcopy(d)
|
||||||
|
bar = _CountingBar()
|
||||||
|
# Temporarily enable preflight-count mode and route progress updates to our counter
|
||||||
|
global PREFLIGHT_COUNT_MODE
|
||||||
|
saved_preflight = PREFLIGHT_COUNT_MODE
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
global PBAR
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
# Count display name TL (1 unit if present)
|
||||||
|
if "Map" in fname and isinstance(dcopy.get("displayName", None), str):
|
||||||
|
try:
|
||||||
|
translateAI(
|
||||||
|
dcopy["displayName"],
|
||||||
|
"Reply with only the " + LANGUAGE + " translation of the RPG location name",
|
||||||
|
False,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Notes and pages
|
||||||
|
evts = dcopy.get("events", []) or []
|
||||||
|
for evt in evts:
|
||||||
|
if not evt:
|
||||||
|
continue
|
||||||
|
note_val = evt.get("note") or ""
|
||||||
|
if not isinstance(note_val, str):
|
||||||
|
note_val = str(note_val) if note_val is not None else ""
|
||||||
|
|
||||||
|
# <LB> name translation
|
||||||
|
if "<LB>" in note_val:
|
||||||
|
name_val = evt.get("name") or ""
|
||||||
|
if isinstance(name_val, str) and name_val:
|
||||||
|
try:
|
||||||
|
translateAI(
|
||||||
|
name_val,
|
||||||
|
"Reply with only the " + LANGUAGE + " translation of the RPG location name",
|
||||||
|
False,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# <msgText:"...">
|
||||||
|
if "<msgText:" in note_val:
|
||||||
|
try:
|
||||||
|
translateNote(evt, r"<msgText:\"(.*?)\">", False)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# <namePop:...>, <LB:...>, <dn:...> handled before page processing in real run
|
||||||
|
if "<namePop:" in note_val:
|
||||||
|
try:
|
||||||
|
translateNoteOmitSpace(evt, r"<namePop:\\s?([\\w一-龠ぁ-ゔァ-ヴーa-zA-Z0-9\\uFF61-\\uFF9F]+)")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if "<LB:" in note_val:
|
||||||
|
try:
|
||||||
|
translateNoteOmitSpace(evt, r"<LB:(.*?)\\s?>.*")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
if "<dn:" in note_val:
|
||||||
|
try:
|
||||||
|
translateNoteOmitSpace(evt, r"<dn:\\s*(.*)>.*")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Other note tags handled during main loop
|
||||||
|
# We'll just invoke the normal search pass which will batch and call translateAI
|
||||||
|
for page in (evt.get("pages", []) or []):
|
||||||
|
try:
|
||||||
|
searchCodes(page, bar, [], fname)
|
||||||
|
except Exception:
|
||||||
|
# Ignore counting errors to avoid blocking
|
||||||
|
pass
|
||||||
|
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_preflight
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
# Translate displayName for Map files
|
# Translate displayName for Map files
|
||||||
if "Map" in filename:
|
if "Map" in filename:
|
||||||
response = translateAI(
|
response = translateAI(
|
||||||
|
|
@ -448,30 +546,18 @@ def parseMap(data, filename):
|
||||||
totalTokens[1] += response[1][1]
|
totalTokens[1] += response[1][1]
|
||||||
data["displayName"] = response[0].replace('"', "")
|
data["displayName"] = response[0].replace('"', "")
|
||||||
|
|
||||||
# Get total for progress bar (sum of all command list lengths across pages)
|
# Compute accurate total using preflight (includes speakers, choices, groups, and notes)
|
||||||
for event in events:
|
totalLines = _estimate_map_units(data, filename)
|
||||||
if event:
|
if not isinstance(totalLines, int) or totalLines <= 0:
|
||||||
note_val = event.get("note") or ""
|
# Fallback to naive count so a bar still renders
|
||||||
if not isinstance(note_val, str):
|
totalLines = 0
|
||||||
note_val = str(note_val) if note_val is not None else ""
|
for event in events:
|
||||||
if "<LB>" in note_val:
|
if event:
|
||||||
# Translate event name when flagged with <LB>
|
for page in event.get("pages", []) or []:
|
||||||
name_val = event.get("name") or ""
|
try:
|
||||||
if isinstance(name_val, str) and name_val:
|
totalLines += len(page.get("list", []))
|
||||||
response = translateAI(
|
except Exception:
|
||||||
name_val,
|
pass
|
||||||
"Reply with only the " + LANGUAGE + " translation of the RPG location name",
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
totalTokens[0] += response[1][0]
|
|
||||||
totalTokens[1] += response[1][1]
|
|
||||||
event["name"] = response[0].replace('"', "")
|
|
||||||
if "<msgText:" in note_val:
|
|
||||||
tokensResponse = translateNote(event, r"<msgText:\"(.*?)\">", False)
|
|
||||||
totalTokens[0] += tokensResponse[0]
|
|
||||||
totalTokens[1] += tokensResponse[1]
|
|
||||||
for page in event["pages"]:
|
|
||||||
totalLines += len(page["list"])
|
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
# Process each page synchronously with progress updates
|
# Process each page synchronously with progress updates
|
||||||
|
|
@ -595,13 +681,52 @@ def translateNoteOmitSpace(event, regex):
|
||||||
|
|
||||||
def parseCommonEvents(data, filename):
|
def parseCommonEvents(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
totalLines = 0
|
|
||||||
global LOCK
|
global LOCK
|
||||||
|
|
||||||
# Get total for progress bar
|
# --- Preflight: estimate exact progress total using same batching ---
|
||||||
for page in data:
|
class _CountingBar:
|
||||||
if page is not None:
|
def __init__(self):
|
||||||
totalLines += len(page["list"])
|
self.n = 0
|
||||||
|
def update(self, n=1):
|
||||||
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_units(pages, fname) -> int:
|
||||||
|
dcopy = copy.deepcopy(pages)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
for page in dcopy:
|
||||||
|
if page is not None:
|
||||||
|
try:
|
||||||
|
searchCodes(page, bar, [], fname)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
totalLines = _estimate_units(data, filename)
|
||||||
|
if not isinstance(totalLines, int) or totalLines <= 0:
|
||||||
|
# Fallback to naive command count
|
||||||
|
totalLines = 0
|
||||||
|
for page in data:
|
||||||
|
if page is not None:
|
||||||
|
try:
|
||||||
|
totalLines += len(page.get("list", []))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -623,15 +748,55 @@ def parseCommonEvents(data, filename):
|
||||||
|
|
||||||
def parseTroops(data, filename):
|
def parseTroops(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
totalLines = 0
|
|
||||||
global LOCK
|
global LOCK
|
||||||
|
|
||||||
# Get total for progress bar
|
# --- Preflight total using same code paths ---
|
||||||
for troop in data:
|
class _CountingBar:
|
||||||
if troop is not None:
|
def __init__(self):
|
||||||
for page in troop["pages"]:
|
self.n = 0
|
||||||
# Progress measured by number of commands in each page's list
|
def update(self, n=1):
|
||||||
totalLines += len(page["list"])
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_units(troops, fname) -> int:
|
||||||
|
tcopy = copy.deepcopy(troops)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
for troop in tcopy:
|
||||||
|
if troop is None:
|
||||||
|
continue
|
||||||
|
for page in (troop.get("pages", []) or []):
|
||||||
|
if page is not None:
|
||||||
|
try:
|
||||||
|
searchCodes(page, bar, [], fname)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
totalLines = _estimate_units(data, filename)
|
||||||
|
if not isinstance(totalLines, int) or totalLines <= 0:
|
||||||
|
totalLines = 0
|
||||||
|
for troop in data:
|
||||||
|
if troop is not None:
|
||||||
|
for page in troop.get("pages", []) or []:
|
||||||
|
try:
|
||||||
|
totalLines += len(page.get("list", []))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -656,49 +821,138 @@ def parseTroops(data, filename):
|
||||||
def parseNames(data, filename, context):
|
def parseNames(data, filename, context):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
|
|
||||||
# Precompute total work units for progress bar
|
# --- Preflight: custom estimator that mirrors searchNames increments (incl. notes/messages) ---
|
||||||
def count_work_units(data, context):
|
class _CountingBar:
|
||||||
total = 0
|
def __init__(self):
|
||||||
|
self.n = 0
|
||||||
|
def update(self, n=1):
|
||||||
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_names_units(entries, ctx, fname) -> int:
|
||||||
|
ecopy = copy.deepcopy(entries)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
# Count names/descriptions/profile/nickname
|
||||||
|
name_cnt = 0
|
||||||
|
desc_cnt = 0
|
||||||
|
profile_cnt = 0
|
||||||
|
nickname_cnt = 0
|
||||||
|
msg_cnt = 0
|
||||||
|
notes_cnt = 0
|
||||||
|
|
||||||
|
note_regexes = [
|
||||||
|
(r"<note:(.*?)>", False),
|
||||||
|
(r"<PE拡張:(.*?)>", False),
|
||||||
|
(r"<hint:(.*?)>", False),
|
||||||
|
(r"<SGDescription:(.*?)>", False),
|
||||||
|
(r"<SG説明:\n?(.*?)>", False),
|
||||||
|
(r"<SG説明2:\n?(.*?)>", False),
|
||||||
|
(r"<SG説明3:\n?(.*?)>", False),
|
||||||
|
(r"<SG説明4:\n?(.*?)>", False),
|
||||||
|
(r"<SG説明:.+?Client\s?:.+?\n\n(.*?)>", True),
|
||||||
|
(r"<SGカテゴリ:(.*?)>", False),
|
||||||
|
(r"<Switch Shop Description>\n(.*)\n", False),
|
||||||
|
(r"<MapText:(.*?)>", False),
|
||||||
|
(r"WATs:(.+?)>", False),
|
||||||
|
(r"ADTs?:(.+?)>", False),
|
||||||
|
(r"<detail:(.*?)>", False),
|
||||||
|
(r"<Name:(.*?)>", False),
|
||||||
|
(r"<sub_1:([^>]+)", True),
|
||||||
|
(r"<sub_2:([^>]+)", True),
|
||||||
|
(r"<sub_3:([^>]+)", True),
|
||||||
|
(r"<infowindow:(.*?)>", True),
|
||||||
|
(r"<ExtendDesc:(.*?)>", True),
|
||||||
|
(r"<desc\d:(.*?)>", False),
|
||||||
|
(r"<拡張説明:(.+?)>", False),
|
||||||
|
(r"<STS DESC>\n(.+?)\n<", False),
|
||||||
|
(r"text:(.+)>", False),
|
||||||
|
]
|
||||||
|
|
||||||
|
for entry in ecopy:
|
||||||
|
if not entry:
|
||||||
|
continue
|
||||||
|
nm = entry.get("name") or ""
|
||||||
|
ds = entry.get("description") or ""
|
||||||
|
nn = entry.get("nickname") or ""
|
||||||
|
pf = entry.get("profile") or ""
|
||||||
|
if ctx == "Actors":
|
||||||
|
if nm: name_cnt += 1
|
||||||
|
if nn: nickname_cnt += 1
|
||||||
|
if pf: profile_cnt += 1
|
||||||
|
elif ctx in ["Armors", "Weapons", "Items"]:
|
||||||
|
if nm: name_cnt += 1
|
||||||
|
if ds: desc_cnt += 1
|
||||||
|
elif ctx == "Skills":
|
||||||
|
if nm: name_cnt += 1
|
||||||
|
if ds: desc_cnt += 1
|
||||||
|
for k in range(1,5):
|
||||||
|
if entry.get(f"message{k}"): msg_cnt += 1
|
||||||
|
elif ctx in ["Enemies", "Classes", "MapInfos"]:
|
||||||
|
if nm: name_cnt += 1
|
||||||
|
|
||||||
|
# Notes counting
|
||||||
|
note = entry.get("note") or ""
|
||||||
|
if isinstance(note, str) and note:
|
||||||
|
for regex, _ww in note_regexes:
|
||||||
|
try:
|
||||||
|
matches = re.findall(regex, note, re.DOTALL)
|
||||||
|
except Exception:
|
||||||
|
matches = []
|
||||||
|
if regex.startswith(r"<SG説明:"):
|
||||||
|
for m in matches:
|
||||||
|
s = m if isinstance(m, str) else (m[0] if m else "")
|
||||||
|
if "Client:" in s or "Client :" in s:
|
||||||
|
continue
|
||||||
|
notes_cnt += 1
|
||||||
|
else:
|
||||||
|
notes_cnt += len(matches)
|
||||||
|
|
||||||
|
# Simulate increments via wrapper (updates bar.n)
|
||||||
|
if name_cnt:
|
||||||
|
translateAI([""] * name_cnt, "", True)
|
||||||
|
if desc_cnt:
|
||||||
|
translateAI([""] * desc_cnt, "", True)
|
||||||
|
if profile_cnt:
|
||||||
|
translateAI([""] * profile_cnt, "", True)
|
||||||
|
if nickname_cnt:
|
||||||
|
translateAI([""] * nickname_cnt, "", True)
|
||||||
|
if msg_cnt:
|
||||||
|
translateAI([""] * msg_cnt, "", True)
|
||||||
|
if notes_cnt:
|
||||||
|
translateAI([""] * notes_cnt, "", True)
|
||||||
|
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
total_units = _estimate_names_units(data, context, filename)
|
||||||
|
if not isinstance(total_units, int) or total_units <= 0:
|
||||||
|
# Reasonable fallback: count visible fields/messages (no notes)
|
||||||
|
total_units = 0
|
||||||
for entry in data:
|
for entry in data:
|
||||||
if not entry:
|
if not entry:
|
||||||
continue
|
continue
|
||||||
|
if entry.get("name"): total_units += 1
|
||||||
# Names and associated fields
|
if context in ["Armors", "Weapons", "Items", "Skills"] and entry.get("description"): total_units += 1
|
||||||
name = entry.get("name", "")
|
|
||||||
desc = entry.get("description", "")
|
|
||||||
nickname = entry.get("nickname", "")
|
|
||||||
profile = entry.get("profile", "")
|
|
||||||
|
|
||||||
if context == "Actors":
|
if context == "Actors":
|
||||||
if name:
|
if entry.get("nickname"): total_units += 1
|
||||||
total += 1
|
if entry.get("profile"): total_units += 1
|
||||||
if nickname:
|
if context == "Skills":
|
||||||
total += 1
|
for k in range(1,5):
|
||||||
if profile:
|
if entry.get(f"message{k}"): total_units += 1
|
||||||
total += 1
|
|
||||||
elif context in ["Armors", "Weapons", "Items"]:
|
|
||||||
if name:
|
|
||||||
total += 1
|
|
||||||
if desc:
|
|
||||||
total += 1
|
|
||||||
elif context == "Skills":
|
|
||||||
if name:
|
|
||||||
total += 1
|
|
||||||
if desc:
|
|
||||||
total += 1
|
|
||||||
# Messages translated individually in searchNames
|
|
||||||
for n in range(1, 5):
|
|
||||||
msg = entry.get(f"message{n}")
|
|
||||||
if msg:
|
|
||||||
total += 1
|
|
||||||
elif context in ["Enemies", "Classes", "MapInfos"]:
|
|
||||||
if name:
|
|
||||||
total += 1
|
|
||||||
|
|
||||||
return total
|
|
||||||
|
|
||||||
total_units = count_work_units(data, context)
|
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -720,22 +974,50 @@ def parseNames(data, filename, context):
|
||||||
def parseSS(data, filename):
|
def parseSS(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
|
|
||||||
# Precompute total units (ignore notes): name, description, message1..4 presence
|
# --- Preflight using searchSS over deep copy ---
|
||||||
def count_work_units(states):
|
class _CountingBar:
|
||||||
total = 0
|
def __init__(self):
|
||||||
for st in states:
|
self.n = 0
|
||||||
|
def update(self, n=1):
|
||||||
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_units(states, fname) -> int:
|
||||||
|
scopy = copy.deepcopy(states)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
for ss in scopy:
|
||||||
|
if ss is not None:
|
||||||
|
try:
|
||||||
|
searchSS(ss, bar)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
total_units = _estimate_units(data, filename)
|
||||||
|
if not isinstance(total_units, int) or total_units <= 0:
|
||||||
|
total_units = 0
|
||||||
|
for st in data:
|
||||||
if not st:
|
if not st:
|
||||||
continue
|
continue
|
||||||
if st.get("name"):
|
if st.get("name"): total_units += 1
|
||||||
total += 1
|
if st.get("description"): total_units += 1
|
||||||
if st.get("description"):
|
for n in range(1,5):
|
||||||
total += 1
|
if st.get(f"message{n}"): total_units += 1
|
||||||
for n in range(1, 5):
|
|
||||||
if st.get(f"message{n}"):
|
|
||||||
total += 1
|
|
||||||
return total
|
|
||||||
|
|
||||||
total_units = count_work_units(data)
|
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -758,29 +1040,53 @@ def parseSS(data, filename):
|
||||||
def parseSystem(data, filename):
|
def parseSystem(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
|
|
||||||
# Precompute total units across system sections (exclude notes; count strings)
|
# --- Preflight: call searchSystem on deep copy to count increments ---
|
||||||
def count_work_units(sys):
|
class _CountingBar:
|
||||||
total = 0
|
def __init__(self):
|
||||||
# Title
|
self.n = 0
|
||||||
if sys.get("gameTitle"):
|
def update(self, n=1):
|
||||||
total += 1
|
try:
|
||||||
# Terms (excluding 'messages' object)
|
self.n += int(n) if n is not None else 1
|
||||||
terms = sys.get("terms", {})
|
except Exception:
|
||||||
for term_key, term_list in terms.items():
|
self.n += 1
|
||||||
if term_key == "messages":
|
def write(self, *args, **kwargs):
|
||||||
continue
|
pass
|
||||||
if isinstance(term_list, list):
|
def refresh(self):
|
||||||
total += sum(1 for x in term_list if x is not None)
|
pass
|
||||||
# Armor, Skill, Equip types
|
|
||||||
total += len(sys.get("armorTypes", []) or [])
|
|
||||||
total += len(sys.get("skillTypes", []) or [])
|
|
||||||
total += len(sys.get("equipTypes", []) or [])
|
|
||||||
# Messages
|
|
||||||
messages = terms.get("messages", {}) or {}
|
|
||||||
total += len(messages)
|
|
||||||
return total
|
|
||||||
|
|
||||||
total_units = count_work_units(data)
|
def _estimate_units(sysobj, fname) -> int:
|
||||||
|
scopy = copy.deepcopy(sysobj)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
searchSystem(scopy, bar)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
total_units = _estimate_units(data, filename)
|
||||||
|
if not isinstance(total_units, int) or total_units <= 0:
|
||||||
|
# Fallback: rough count of strings
|
||||||
|
total_units = 0
|
||||||
|
if data.get("gameTitle"): total_units += 1
|
||||||
|
terms = data.get("terms", {}) or {}
|
||||||
|
for k,v in terms.items():
|
||||||
|
if k == "messages":
|
||||||
|
continue
|
||||||
|
if isinstance(v, list):
|
||||||
|
total_units += sum(1 for x in v if x is not None)
|
||||||
|
total_units += len(data.get("armorTypes", []) or [])
|
||||||
|
total_units += len(data.get("skillTypes", []) or [])
|
||||||
|
total_units += len(data.get("equipTypes", []) or [])
|
||||||
|
total_units += len((terms.get("messages", {}) or {}))
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -800,12 +1106,50 @@ def parseSystem(data, filename):
|
||||||
|
|
||||||
def parseScenario(data, filename):
|
def parseScenario(data, filename):
|
||||||
totalTokens = [0, 0]
|
totalTokens = [0, 0]
|
||||||
totalLines = 0
|
|
||||||
global LOCK
|
global LOCK
|
||||||
|
|
||||||
# Get total for progress bar
|
# --- Preflight: run searchCodes on each page list ---
|
||||||
for page in data.items():
|
class _CountingBar:
|
||||||
totalLines += len(page[1])
|
def __init__(self):
|
||||||
|
self.n = 0
|
||||||
|
def update(self, n=1):
|
||||||
|
try:
|
||||||
|
self.n += int(n) if n is not None else 1
|
||||||
|
except Exception:
|
||||||
|
self.n += 1
|
||||||
|
def write(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _estimate_units(scenario, fname) -> int:
|
||||||
|
scopy = copy.deepcopy(scenario)
|
||||||
|
bar = _CountingBar()
|
||||||
|
global PREFLIGHT_COUNT_MODE, PBAR
|
||||||
|
saved_flag = PREFLIGHT_COUNT_MODE
|
||||||
|
saved_pbar = PBAR
|
||||||
|
PREFLIGHT_COUNT_MODE = True
|
||||||
|
PBAR = bar
|
||||||
|
try:
|
||||||
|
for key, lst in scopy.items():
|
||||||
|
if lst is not None:
|
||||||
|
try:
|
||||||
|
searchCodes(lst, bar, [], fname)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return getattr(bar, "n", 0) or 0
|
||||||
|
finally:
|
||||||
|
PREFLIGHT_COUNT_MODE = saved_flag
|
||||||
|
PBAR = saved_pbar
|
||||||
|
|
||||||
|
totalLines = _estimate_units(data, filename)
|
||||||
|
if not isinstance(totalLines, int) or totalLines <= 0:
|
||||||
|
totalLines = 0
|
||||||
|
for _, lst in data.items():
|
||||||
|
try:
|
||||||
|
totalLines += len(lst or [])
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
global PBAR
|
global PBAR
|
||||||
|
|
||||||
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
with tqdm(total=totalLines, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE, desc=filename) as pbar:
|
||||||
|
|
@ -3192,6 +3536,21 @@ def translateAI(text, history, fullPromptFlag):
|
||||||
# Return original text unmodified with zero tokens
|
# Return original text unmodified with zero tokens
|
||||||
return [text, [0, 0]]
|
return [text, [0, 0]]
|
||||||
|
|
||||||
|
# Preflight count mode: don't hit API; just simulate progress units
|
||||||
|
if 'PREFLIGHT_COUNT_MODE' in globals() and PREFLIGHT_COUNT_MODE:
|
||||||
|
try:
|
||||||
|
n = len(text) if isinstance(text, list) else 1
|
||||||
|
except Exception:
|
||||||
|
n = 1
|
||||||
|
if PBAR is not None:
|
||||||
|
try:
|
||||||
|
with LOCK:
|
||||||
|
PBAR.update(n)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# Return original payload and zero tokens so totals aren't affected
|
||||||
|
return [text, [0, 0]]
|
||||||
|
|
||||||
return sharedtranslateAI(
|
return sharedtranslateAI(
|
||||||
text=text,
|
text=text,
|
||||||
history=history,
|
history=history,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue