test(upserver): 归档存档迁移与玩法闭环回归工具
This commit is contained in:
34
CodexOutput/upserver/ReviewLifecycleTests/generate.py
Normal file
34
CodexOutput/upserver/ReviewLifecycleTests/generate.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json
|
||||
root=Path('Client/Assets/Scripts'); out=Path('CodexOutput/upserver/ReviewLifecycleTests')
|
||||
def method(path, signature):
|
||||
text=(root/path).read_text(encoding='utf-8-sig'); start=text.index(signature); opening=text.index('{',start); depth=1; end=opening+1
|
||||
while depth:
|
||||
depth+=(text[end]=='{')-(text[end]=='}'); end+=1
|
||||
return text[start:end]
|
||||
parts=[('GetUiSubject','Stages/FishingAct.cs',['async void GetUI()','async void NewEnterMap(PlayableDirector camera_timeline)','async Task OnCameraSpeedEvent()']),('ManagerSubject','Core/SoundMgr.cs',['public async Task Init(System.Action<float> progress)','public void Release()']),('ServiceSubject','Sound/SoundService.cs',['public async Task InitAsync(string mixerAddr','public void Release()'])]
|
||||
generated='using System;using System.Linq;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;\n'
|
||||
evidence=[]
|
||||
for name,path,signatures in parts:
|
||||
generated+=f'public partial class {name} {{\n'
|
||||
for signature in signatures:
|
||||
# SoundService also has an interface Release; select class suffix.
|
||||
if name=='ServiceSubject' and signature=='public void Release()':
|
||||
text=(root/path).read_text(encoding='utf-8-sig'); text=text[text.index('public class SoundService'):]
|
||||
start=text.index(signature); opening=text.index('{',start); depth=1; end=opening+1
|
||||
while depth: depth+=(text[end]=='{')-(text[end]=='}'); end+=1
|
||||
raw=text[start:end]
|
||||
else: raw=method(path,signature)
|
||||
extracted=raw.replace('async void GetUI()', 'public async Task GetUI()').replace('async void NewEnterMap(', 'public async Task NewEnterMap(').replace('async Task OnCameraSpeedEvent()', 'public async Task OnCameraSpeedEvent()')
|
||||
generated+=extracted+'\n'
|
||||
evidence.append({'source':str(root/path),'signature':signature,'source_sha256':hashlib.sha256((root/path).read_bytes()).hexdigest(),'method_sha256':hashlib.sha256(raw.encode()).hexdigest(),'transformation':'async void -> public async Task only' if name=='GetUiSubject' else 'none'})
|
||||
generated+='}\n'
|
||||
stage_path='Stages/FishingStage.cs'; stage_text=(root/stage_path).read_text(encoding='utf-8-sig')
|
||||
prefix=stage_text[stage_text.index('public override async Task StartAsync()'):stage_text.index('//GContext.Publish()')].replace('public override async Task StartAsync()', 'public async Task RunPrefix()')
|
||||
stop=method(stage_path,'public override async Task Stop()')
|
||||
destroy=method(stage_path,'protected override void OnDestroy()')
|
||||
catch_start=stage_text.index('try { await base.StartAsync(); }'); catch_end=stage_text.index('//静默加载后续场景',catch_start); guard=stage_text[catch_start:catch_end]
|
||||
generated+='public partial class StageSubject : StageBase {\n'+prefix+'Applied=true; }\n'+stop+'\n'+destroy+'\npublic async Task RunCatch(){ var loginLifetime=UserService.LoginLifetime;\n'+guard+'CatchCompleted=true; }\n}\n'
|
||||
evidence.append({'source':str(root/stage_path),'source_sha256':hashlib.sha256((root/stage_path).read_bytes()).hexdigest(),'transformation':'StartAsync prefix ends before //GContext.Publish(); Stop and OnDestroy complete; actual base.StartAsync catch segment through next-scene comment; only wrapper names/assertion markers added'})
|
||||
(out/'Generated.cs').write_text(generated,encoding='utf-8')
|
||||
(out/'extraction.json').write_text(json.dumps(evidence,ensure_ascii=False,indent=2),encoding='utf-8')
|
||||
Reference in New Issue
Block a user