Fix progress bars for some file types

This commit is contained in:
dazedanon 2025-08-24 15:44:52 -05:00
parent f535e3a4e4
commit ecaa4ac815
3 changed files with 368 additions and 61 deletions

View file

@ -420,10 +420,44 @@ def parseTroops(data, filename):
def parseNames(data, filename, context):
totalTokens = [0, 0]
totalLines = 0
totalLines += len(data)
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
# Precompute total work units for progress bar (exclude notes)
def count_work_units(entries, ctx):
total = 0
for entry in entries:
if not entry:
continue
name = entry.get("name", "")
desc = entry.get("description", "")
nickname = entry.get("nickname", "")
if ctx == "Actors":
if name:
total += 1
if nickname:
total += 1
if desc:
total += 1
elif ctx in ["Armors", "Weapons", "Items"]:
if name:
total += 1
if desc:
total += 1
elif ctx == "Skills":
if name:
total += 1
if desc:
total += 1
for n in range(1, 5):
if entry.get(f"message{n}"):
total += 1
elif ctx in ["Enemies", "Classes", "MapInfos"]:
if name:
total += 1
return total
total_units = count_work_units(data, context)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
try:
result = searchNames(data, pbar, context)
@ -439,10 +473,25 @@ def parseNames(data, filename, context):
def parseSS(data, filename):
totalTokens = [0, 0]
totalLines = 0
totalLines += len(data)
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
# Precompute total units: name, description, message1..4 (exclude notes)
def count_work_units(states):
total = 0
for st in states:
if not st:
continue
if st.get("name"):
total += 1
if st.get("description"):
total += 1
for n in range(1, 5):
if st.get(f"message{n}"):
total += 1
return total
total_units = count_work_units(data)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
for ss in data:
if ss is not None:
@ -460,19 +509,29 @@ def parseSS(data, filename):
def parseSystem(data, filename):
totalTokens = [0, 0]
totalLines = 0
# Calculate Total Lines
for term in data["terms"]:
termList = data["terms"][term]
totalLines += len(termList)
totalLines += len(data["game_title"])
totalLines += len(data["variables"])
totalLines += len(data["weapon_types"])
totalLines += len(data["armor_types"])
totalLines += len(data["skill_types"])
# Precompute total units for Ace schema
def count_work_units(sys):
total = 0
# Terms: sum list lengths of each term list
for term in sys.get("terms", {}):
termList = sys["terms"][term]
if isinstance(termList, list):
total += len(termList)
# game_title might be a string; count as 1 if non-empty
gt = sys.get("game_title")
if isinstance(gt, str) and gt:
total += 1
# variables is a list
total += len(sys.get("variables", []) or [])
total += len(sys.get("weapon_types", []) or [])
total += len(sys.get("armor_types", []) or [])
total += len(sys.get("skill_types", []) or [])
return total
with tqdm(bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
total_units = count_work_units(data)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
try:
result = searchSystem(data, pbar)
@ -680,6 +739,9 @@ def searchNames(data, pbar, context):
data[i][f"message{number}"] = msgResponse[0].replace("Taro", "")
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
if pbar is not None:
pbar.update(1)
pbar.refresh()
number += 1
else:
@ -691,6 +753,9 @@ def searchNames(data, pbar, context):
data[i][f"message{number}"] = msgResponse[0]
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
if pbar is not None:
pbar.update(1)
pbar.refresh()
number += 1
else:
number += 1
@ -751,6 +816,9 @@ def searchNames(data, pbar, context):
translatedNameBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.update(len(nameList))
pbar.refresh()
# Nickname
if nicknameList:
@ -758,6 +826,9 @@ def searchNames(data, pbar, context):
translatedNicknameBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.update(len(nicknameList))
pbar.refresh()
# Profile
if profileList:
@ -765,6 +836,9 @@ def searchNames(data, pbar, context):
translatedProfileBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.update(len(profileList))
pbar.refresh()
# Set Data
if len(nameList) == len(translatedNameBatch):
@ -805,6 +879,9 @@ def searchNames(data, pbar, context):
translatedNameBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.update(len(nameList))
pbar.refresh()
# Description
if descriptionList:
@ -816,6 +893,9 @@ def searchNames(data, pbar, context):
translatedDescriptionBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.update(len(descriptionList))
pbar.refresh()
# Set Data
if len(nameList) == len(translatedNameBatch):
@ -850,6 +930,9 @@ def searchNames(data, pbar, context):
translatedNameBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.update(len(nameList))
pbar.refresh()
# Set Data
if len(nameList) == len(translatedNameBatch):

View file

@ -446,8 +446,52 @@ def parseTroops(data, filename):
def parseNames(data, filename, context):
totalTokens = [0, 0]
# Use dynamic total; we'll grow it inside searchNames as we discover work units
with tqdm(total=0, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
# Precompute total work units for progress bar
def count_work_units(data, context):
total = 0
for entry in data:
if not entry:
continue
# Names and associated fields
name = entry.get("name", "")
desc = entry.get("description", "")
nickname = entry.get("nickname", "")
profile = entry.get("profile", "")
if context == "Actors":
if name:
total += 1
if nickname:
total += 1
if profile:
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)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
try:
result = searchNames(data, pbar, context)
@ -464,8 +508,25 @@ def parseNames(data, filename, context):
def parseSS(data, filename):
totalTokens = [0, 0]
# Use dynamic total to account for variable work per state
with tqdm(total=0, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
# Precompute total units (ignore notes): name, description, message1..4 presence
def count_work_units(states):
total = 0
for st in states:
if not st:
continue
if st.get("name"):
total += 1
if st.get("description"):
total += 1
for n in range(1, 5):
if st.get(f"message{n}"):
total += 1
return total
total_units = count_work_units(data)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
for ss in data:
if ss is not None:
@ -484,8 +545,32 @@ def parseSS(data, filename):
def parseSystem(data, filename):
totalTokens = [0, 0]
# Use dynamic progress; set total as we process sections
with tqdm(total=0, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
# Precompute total units across system sections (exclude notes; count strings)
def count_work_units(sys):
total = 0
# Title
if sys.get("gameTitle"):
total += 1
# Terms (excluding 'messages' object)
terms = sys.get("terms", {})
for term_key, term_list in terms.items():
if term_key == "messages":
continue
if isinstance(term_list, list):
total += sum(1 for x in term_list if x is not None)
# 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)
with tqdm(total=total_units, bar_format=BAR_FORMAT, position=POSITION, leave=LEAVE) as pbar:
pbar.desc = filename
try:
result = searchSystem(data, pbar)
@ -619,11 +704,7 @@ def searchNames(data, pbar, context):
translatedNotesBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
# Progress: add and complete note translations
if pbar is not None:
pbar.total += len(notesBatch)
pbar.update(len(notesBatch))
pbar.refresh()
# Notes don't update progress
# --- Insert translated notes back ---
note_insert_idx = 0
@ -692,6 +773,9 @@ def searchNames(data, pbar, context):
data[i][f"message{number}"] = msgResponse[0].replace("Taro", "")
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
if pbar is not None:
pbar.update(1)
pbar.refresh()
number += 1
else:
msgResponse = translateAI(
@ -702,6 +786,9 @@ def searchNames(data, pbar, context):
data[i][f"message{number}"] = msgResponse[0]
totalTokens[0] += msgResponse[1][0]
totalTokens[1] += msgResponse[1][1]
if pbar is not None:
pbar.update(1)
pbar.refresh()
number += 1
else:
number += 1
@ -725,7 +812,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.total += len(nameList)
pbar.update(len(nameList))
pbar.refresh()
@ -736,7 +822,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.total += len(nicknameList)
pbar.update(len(nicknameList))
pbar.refresh()
@ -747,7 +832,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.total += len(profileList)
pbar.update(len(profileList))
pbar.refresh()
@ -793,7 +877,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.total += len(nameList)
pbar.update(len(nameList))
pbar.refresh()
@ -808,7 +891,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.total += len(descriptionList)
pbar.update(len(descriptionList))
pbar.refresh()
@ -848,7 +930,6 @@ def searchNames(data, pbar, context):
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None and nameList:
pbar.total += len(nameList)
pbar.update(len(nameList))
pbar.refresh()
@ -2353,10 +2434,7 @@ Translate 'Taroを倒した' as 'Taro was defeated!'",
translatedNotesBatch = response[0]
totalTokens[0] += response[1][0]
totalTokens[1] += response[1][1]
if pbar is not None:
pbar.total += len(notesBatch)
pbar.update(len(notesBatch))
pbar.refresh()
# Notes don't update progress
# --- Insert translated notes back ---
note_insert_idx = 0
@ -2396,7 +2474,6 @@ Translate 'Taroを倒した' as 'Taro was defeated!'",
work_units += 1 if message3Response != "" else 0
work_units += 1 if message4Response != "" else 0
if work_units:
pbar.total += work_units
pbar.update(work_units)
pbar.refresh()
@ -2434,7 +2511,6 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
data["gameTitle"] = response[0].strip(".")
if pbar is not None:
pbar.total += 1
pbar.update(1)
pbar.refresh()
@ -2449,9 +2525,7 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
termList[i] = response[0].replace('"', "").strip()
if pbar is not None and len(termList) > 0:
# Count non-empty entries as completed work units
units = sum(1 for x in termList if x is not None)
pbar.total += units
pbar.update(units)
pbar.refresh()
@ -2466,7 +2540,6 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
data["armorTypes"][i] = response[0].replace('"', "").strip()
if pbar is not None and len(data["armorTypes"]) > 0:
pbar.total += len(data["armorTypes"])
pbar.update(len(data["armorTypes"]))
pbar.refresh()
@ -2481,7 +2554,6 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
data["skillTypes"][i] = response[0].replace('"', "").strip()
if pbar is not None and len(data["skillTypes"]) > 0:
pbar.total += len(data["skillTypes"])
pbar.update(len(data["skillTypes"]))
pbar.refresh()
@ -2496,7 +2568,6 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
data["equipTypes"][i] = response[0].replace('"', "").strip()
if pbar is not None and len(data["equipTypes"]) > 0:
pbar.total += len(data["equipTypes"])
pbar.update(len(data["equipTypes"]))
pbar.refresh()
@ -2528,7 +2599,6 @@ def searchSystem(data, pbar):
totalTokens[1] += response[1][1]
messages[key] = translatedText
if pbar is not None and len(messages) > 0:
pbar.total += len(messages)
pbar.update(len(messages))
pbar.refresh()

184
vocab.txt
View file

@ -1,20 +1,10 @@
Here are some vocabulary and terms so that you know the proper spelling and translation.
# Game Characters
かけだし錬金術師 (Novice Alchemist)
アル=ソレイユ (Al Soleil) - Female
月夜の錬金術師 (Moonlit Alchemist)
ケミィ=ルーン (Chemmy Rune) - Female
英雄の娘 (Hero's Daughter)
ルビナ=ローズストーン (Rubina Rosestone) - Female
鋼鉄の意志 (Iron Will)
スティーリア=ブリュンヒルデ (Stilia Brynhildr) - Female
梅園陽芽香 (Himeka Umezono) - Female
東十字優蕾 (Yura Azamajuji) - Female
セイラ (Seira) - Female
澪(みお) (Mio) - Female
ルカ (Luka) - Female
ひなた (Hinata) - Female
# Lewd Terms
マンコ (pussy)
@ -176,4 +166,168 @@ w (lol)
』 (』)
# Game Specific
アルケム (Alchema)
見せかけ場所移動 (Fake Location Move)
撮影用_駅前 (For Filming_Station Front)
__自宅周辺___ (__Around Home__)
撮影用_トレーニングジム (For Filming_Training Gym)
__澪の自室__ (__Mio's Room__)
撮影用_イベントホール (For Filming_Event Hall)
_ (OP_1)
撮影用_アーケード (For Filming_Arcade)
撮影用__神社 (For Filming_Shrine)
__教室 (OP_Classroom)
撮影用__ワールドマップ___ (For Filming_World Map___)
___ワールドマップ___ (___World Map___)
イベ用_澪の家の庭 (Event_Mio's Garden)
★回想部屋 (★Recollection Room)
アーケードバックアップ (Arcade Backup)
撮影用_コンビニ (For Filming_Convenience Store)
撮影用_骨董品屋 (For Filming_Antique Shop)
__教室 (OP_Classroom 2)
_駅前 (OP_Station Front)
コンビニ (Convenience Store)
撮影用__森林公園 (For Filming_Forest Park)
回想セイラ_パイズリ (Recollection Seira_Titjob)
回想_ルカ手コキ (Recollection_Luka Handjob)
再開発ビル (Redevelopment Building)
撮影用__海岸洞窟 (For Filming_Coastal Cave)
OP_自宅周辺_ (OP_Around Home_)
_自宅周辺_ (OP_Around Home_2)
撮影用_遊園地 (For Filming_Amusement Park)
撮影用__総合病院 (For Filming_General Hospital)
撮影用__ラストダンジョン (For Filming_Last Dungeon)
学校 3階 (School 3F)
再開発ビルF (Redevelopment Building 2F)
ボス会話1 (Boss Conversation 1)
再開発ビルF (Redevelopment Building 3F)
撮影用_学校 (For Filming_School)
撮影用_海 (For Filming_Sea)
駅前_夜_撮影用 (Station Front_Night_For Filming)
ひなた救出_自宅周辺_ (Hinata Rescue_Near Home_)
森林公園クリア後_セイラと会話 (After Clearing Forest Park_Talk with Seira)
回想_物置小屋イベ用 (Recollection_Shed Event)
回想_汎用07 (Recollection_Generic 07)
手術室 (Operating Room)
総合病院1Fトイレ (General Hospital 1F Restroom)
イベントホール_初めて入る (Event Hall_First Entry)
__神社 (OP_Shrine)
再開発ビルF (Redevelopment Building 4F)
イベ用___婦警神社の近く (For Event_Near Policewoman Shrine)
_澪の自室__ (OP_Mio's Room_)
ナースステーション (Nurse Station)
総合病院3Fトイレ (General Hospital 3F Restroom)
管理室イベ用 (For Event_Control Room)
バックアップ通気口 (Backup Ventilation Duct)
イベントホール_クリア後 (Event Hall_After Clearing)
_オープニング (OP_Opening 2)
思い出の公園 (Memorial Park)
ルカの部屋 (Luka's Room)
最初_海岸洞窟 (First_Coastal Cave)
森林公園_エリア (Forest Park_Area 1)
森林公園エリア2小屋 (Forest Park Area 2_Hut)
図書室で情報聞いた後 (After Getting Info in Library)
イベントホール (Event Hall)
_サマースクール後 (_After Summer School)
ボス会話2 (Boss Conversation 2)
イベントホール_ボス倒した章 (Event Hall_Boss Defeated ~ Chapter 3)
サマースクール後_催眠見た後 (After Summer School_After Hypnosis Scene)
思い出の公園_過去 (Memorial Park_Past)
イベ_プール (Event 2_Pool)
_イベ_学校の女子トイレ (_Event_School Girls' Restroom)
ボス会話3 (Boss Conversation 3)
学校ボス倒した~7章 (School Boss Defeated ~ Chapter 7)
エレベーター内 (Inside Elevator)
ルカの回想_過去 (Luka's Flashback_Past)
ラスボス前会話 (Pre-Final Boss Conversation)
アイドルイベ_駅前_ (Idol Event_Station Front_)
アイドルイベ_イベントホール (Idol Event_Event Hall)
ボーイッシュ女子_ぶっかけ用 (Boyish Girl_For Cumshot)
ボーイッシュ女子_挿入用 (Boyish Girl_For Insertion)
思い出の公園_過去後 (Memorial Park_After the Past)
ゲームオーバー澪の部屋__ (Game Over Mio's Room__)
セイラ_襲う前会話 (Seira_Pre-Attack Conversation)
ラスボス倒した後会話 (Post-Final Boss Conversation)
エンディング真__神社 (True Ending__Shrine)
エンディングセイラ__神社 (Seira Ending__Shrine)
エンディング_ルカ (Ending_Luka)
エンディング_思い出の公園 (Ending_Memorial Park)
ロッカールーム (Locker Room)
イベ_プール (Event_Pool)
プール会話 (Pool Conversation)
回想ルカ_初催眠 (Luka Flashback_First Hypnosis)
回想_ルカ_素股 (Flashback_Luka_Thighjob)
回想_ルカ_全裸 (Recollection_Luka_Nude)
回想_プールで (Recollection_At the Pool)
回想_悪の騎乗 (Recollection_Evil Cowgirl)
回想_ラスボス (Recollection_Final Boss)
回想_ボーイッシュ女子 (Recollection_Boyish Girl)
コンビニのトイレ (Convenience Store Bathroom)
回想_コンビニ店員 (Recollection_Convenience Store Clerk)
回想__婦警 (Recollection_Policewoman)
回想_女子アナ (Recollection_Female Announcer)
回想_アイドル本番 (Recollection_Idol Sex Scene)
回想_ひなた (Recollection_Hinata)
回想_ひなた (Recollection_Hinata 2)
回想_セイラ_襲う前会話 (Recollection_Seira_Pre-Attack Conversation)
回想ダン_ダウナー (Recollection_Dan_Downer)
最初テレビ__澪の自室__ (First TV__Mio's Room__)
回想_JD (Recollection_College Girl)
回想ダン_スク水女子 (Recollection_Dan_School Swimsuit Girl)
回想_ナース (Recollection_Nurse)
学校 2階 (School 2F)
回想_ダン_お嬢様系女子 (Recollection_Dan_Ojou-sama Type Girl)
遊園地 (Amusement Park)
ジェットコースター乗り場 (Roller Coaster Platform)
回想_ダン_眼鏡女子 (Recollection_Dan_Glasses Girl)
ひなたイベ_自宅周辺 (Hinata Event_Near Home)
駅前 (In Front of the Station)
学校1階 (School 1F)
図書室 (Library)
屋上 (Rooftop)
回想_OL (Recollection_Office Lady)
女子トイレ (Girls' Bathroom)
プール (Pool)
教室 (Classroom)
回想_ルカ全裸_導入 (Recollection_Luka Nude_Intro)
テンプレ (Template)
海岸 (Beach)
オーケストラフロア (Orchestra Floor)
アーケード (Arcade)
岩場 (Rocky Area)
バックアップ部屋 (Backup Room)
__神社 (__Shrine)
__骨董品屋 (__Antique Shop)
森林公園_エリア (Forest Park_Area 2)
森林公園_エリア (Forest Park_Area 3)
通気口 (Ventilation Duct)
森林公園_物置小屋 (Forest Park_Storage Shed)
森林公園_物置小屋イベ用 (Forest Park_Storage Shed (Event))
森林公園エリア4 (Forest Park Area 4)
ライブ会場 (Live Venue)
空きフロア (Empty Floor)
管理室 (Control Room)
女子トイレ (Girls' Restroom)
男子トイレ (Boys' Restroom)
レストラン (Restaurant)
海岸洞窟入口 (Beach Cave Entrance)
海岸洞窟エリア1 (Beach Cave Area 1)
海岸洞窟小部屋 (Beach Cave Small Room)
海岸洞窟エリア2 (Beach Cave Area 2)
海岸洞窟小部屋2 (Beach Cave Small Room 2)
海岸洞窟エリア3 (Beach Cave Area 3)
海岸洞窟エリア4 (Beach Cave Area 4)
お化け屋敷 (Haunted House)
食堂 (Dining Hall)
書斎 (Study)
総合病院F (General Hospital 2F)
総合病院 (General Hospital)
総合病院F (General Hospital 3F)
✖エレベーター内_バックアップ (✖Inside Elevator_Backup)
エレベーター内 (Inside Elevator)
病室イベント用 (For Hospital Room Event)
トレーニングジム (Training Gym)
路地裏_ひなた (Back Alley_Hinata)
公衆トイレ_女子アナイベ (Public Restroom_Female Announcer Event)
戦闘テスト (Battle Test)
撮影用_自宅周辺__ (For Filming_Near Home)
撮影用_澪の部屋__ (For Filming_Mio's Room)