TW Server 活动适配

This commit is contained in:
wess09 2026-05-10 17:24:22 +08:00
parent 6f3de587b0
commit 38e8a09454
5 changed files with 104 additions and 16 deletions

View File

@ -288,6 +288,6 @@ To add a new event, add a new row in here, and run `python -m module.config.conf
| 20260402 | event 20260326 cn | The Vagabonds Recruitment Plan | - | - | - | 漫遊者招募計劃 |
| 20260416 | event 20220915 cn | Violet Tempest Blooming Lycoris | - | - | - | 復刻紫絳槿嵐 |
| 20260417 | event 20260417 cn | Vacation Lane Beachside Brilliance | 假日航线闪耀海滨 | Vacation Lane Beachside Brilliance | バケーションレーン・きらめく砂浜 | - |
| 20260417 | event 20201126 cn | Vacation Lane Rerun | 复刻假日航线 | Vacation Lane Rerun | バケーションレーン(復刻) | - |
| 20260417 | event 20201126 cn | Vacation Lane Rerun | 复刻假日航线 | Vacation Lane Rerun | バケーションレーン(復刻) | 復刻假日航線 |
| 20260417 | event 20250424 cn | Toward Tulipas Seas Rerun | 复刻扬起郁金之旗 | Toward Tulipas Seas Rerun | チュリッパの海へ(復刻) | - |
| 20260417 | event 20260417 cn | Vacation Lane Beachside Brilliance | - | - | - | 假日航線閃耀海濱 |

View File

@ -2148,6 +2148,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -2642,6 +2643,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -3540,6 +3542,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -3974,6 +3977,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -4408,6 +4412,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -6760,6 +6765,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -7211,6 +7217,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -7662,6 +7669,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -8113,6 +8121,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"
@ -8554,6 +8563,7 @@
],
"option_tw": [
"event_20260417_cn",
"event_20201126_cn",
"event_20220915_cn",
"event_20260326_cn",
"event_20220728_cn"

View File

@ -895,7 +895,7 @@
"event_20201002_en": "Counterattack Within the Fjord",
"event_20201012_cn": "復刻劃破海空之翼",
"event_20201029_cn": "激唱的UNIVERSE",
"event_20201126_cn": "假日航線",
"event_20201126_cn": "復刻假日航線",
"event_20201229_cn": "復刻-負象限作戰",
"event_20210121_cn": "復刻神聖的悲喜劇",
"event_20210225_cn": "復刻破曉冰華",

View File

@ -1,4 +1,6 @@
import os
import queue
import threading
import numpy as np
import cv2
from PIL import Image
@ -30,6 +32,68 @@ config_name = os.environ.get("ALAS_CONFIG_NAME") or "alas"
config = AzurLaneConfig(config_name)
class _OcrJob:
def __init__(self, func, args, kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
self.done = threading.Event()
self.result = None
self.exc_info = None
def run(self):
try:
self.result = self.func(*self.args, **self.kwargs)
except BaseException as e:
self.exc_info = (e, e.__traceback__)
finally:
self.done.set()
_ocr_queue = queue.Queue()
_ocr_worker = None
_ocr_worker_lock = threading.Lock()
_ocr_worker_ident = None
def _ocr_worker_loop():
global _ocr_worker_ident
_ocr_worker_ident = threading.get_ident()
while True:
job = _ocr_queue.get()
try:
job.run()
finally:
_ocr_queue.task_done()
def _ensure_ocr_worker():
global _ocr_worker
with _ocr_worker_lock:
if _ocr_worker is None or not _ocr_worker.is_alive():
_ocr_worker = threading.Thread(
target=_ocr_worker_loop,
name='AlOcrQueue',
daemon=True,
)
_ocr_worker.start()
def _run_ocr_queued(func, *args, **kwargs):
if threading.get_ident() == _ocr_worker_ident:
return func(*args, **kwargs)
_ensure_ocr_worker()
job = _OcrJob(func, args, kwargs)
_ocr_queue.put(job)
job.done.wait()
if job.exc_info is not None:
exc, traceback = job.exc_info
raise exc.with_traceback(traceback)
return job.result
class RecOnlyOCR(RapidOCR):
"""只加载识别模型,跳过 det 和 cls 的 ONNX 模型加载。"""
@ -118,12 +182,15 @@ def _get_model(name):
def reset_ocr_model():
global _cn_model, _en_model, _jp_model, _tw_model
logger.info("Resetting OCR models")
_cn_model = None
_en_model = None
_jp_model = None
_tw_model = None
def _reset():
global _cn_model, _en_model, _jp_model, _tw_model
logger.info("Resetting OCR models")
_cn_model = None
_en_model = None
_jp_model = None
_tw_model = None
return _run_ocr_queued(_reset)
class AlOcr:
@ -193,7 +260,7 @@ class AlOcr:
# We don't want to crash the main process due to debug saving failure
logger.warning(f"Failed to save OCR debug image: {e}")
def ocr(self, img_fp):
def _ocr_direct(self, img_fp):
logger.debug(f"[VERBOSE] AlOcr.ocr: Ensure loaded...")
self._ensure_loaded()
@ -209,10 +276,13 @@ class AlOcr:
logger.error(f"AlOcr.ocr exception: {e}")
raise
def ocr(self, img_fp):
return _run_ocr_queued(self._ocr_direct, img_fp)
def ocr_for_single_line(self, img_fp):
return self.ocr(img_fp)
def ocr_for_single_lines(self, img_list):
def _ocr_for_single_lines_direct(self, img_list):
self._ensure_loaded()
results = []
for i, img in enumerate(img_list):
@ -229,6 +299,9 @@ class AlOcr:
raise
return results
def ocr_for_single_lines(self, img_list):
return _run_ocr_queued(self._ocr_for_single_lines_direct, img_list)
def set_cand_alphabet(self, cand_alphabet):
pass

View File

@ -86,6 +86,7 @@ class AzurStats:
LOCAL_MEOW_CSV = './log/azurstat_meowofficer_farming.csv'
LOCAL_GENRES = {'opsi_meowfficer_farming'}
_local_lock = threading.Lock()
_record_lock = threading.Lock()
def __init__(self, config):
"""
@ -348,9 +349,9 @@ class AzurStats:
save_thread.start()
if local:
local_thread = threading.Thread(
target=self._record_local, args=(image, genre, filename, combat_count))
local_thread.start()
logger.info(f'Local AzurStats parse start, genre={genre}')
with self._record_lock:
self._record_local(image, genre, filename, combat_count)
return True
@ -366,12 +367,16 @@ class AzurStats:
Returns:
DropImage:
"""
method_value = None
if isinstance(method, bool):
save = save or method
method = None
if method is not None:
method = str(method)
save = save or 'save' in method
method_value = str(method)
save = save or 'save' in method_value
if local is None:
local = genre in self.LOCAL_GENRES
if method_value is None:
local = genre in self.LOCAL_GENRES
else:
local = 'upload' in method_value and genre in self.LOCAL_GENRES
return DropImage(stat=self, genre=genre, save=save, local=local, info=info)