From 2494459945c3c1a1da512cbfe5708c7c2ed71fd1 Mon Sep 17 00:00:00 2001 From: NINI Date: Sat, 10 Oct 2026 08:11:20 +0900 Subject: [PATCH] Order depth fixture camera like the serialized Unity DTO --- tools/android/exercise-playground.ps1 | 2 +- tools/android/test-playground-contracts.ps1 | 28 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tools/android/exercise-playground.ps1 b/tools/android/exercise-playground.ps1 index 77a2c7e..b4e08f3 100644 --- a/tools/android/exercise-playground.ps1 +++ b/tools/android/exercise-playground.ps1 @@ -233,7 +233,7 @@ try { $after=HoldDrag 'thin-fast-reverse' $before.latestFreePlay $thin.ballId ([int][Math]::Round($thin.end.x)) ([int][Math]::Round($thin.end.y)) 300 -ReversePixels 80 $stopped=@($thin.expected.balls|Where-Object id -eq $thin.ballId)[0].position;$reversed=@($after.latestFreePlay.balls|Where-Object id -eq $thin.ballId)[0].position Check 'thin-fast-reverse-opposite-immediate-safe-drop' ($reversed.x-lt$stopped.x-.05-and(SameMembership $thin.source $after.latestFreePlay)-and(InBounds $after.latestFreePlay 1)-and(Same $thin.source.camera $after.latestFreePlay.camera)) 'Actual opposite move from blocked last-safe point reacts immediately and drops with both exact groups preserved' - $depth=Clone $fixtures.restores[0].freeSource;$depth.sourceStageId=1;$depth.camera=[pscustomobject]@{target=@{x=0;y=2.35;z=0};distance=14;rotation=@{x=0;y=0;z=0;w=1}} + $depth=Clone $fixtures.restores[0].freeSource;$depth.sourceStageId=1;$depth.camera=[pscustomobject][ordered]@{target=[pscustomobject][ordered]@{x=0;y=2.35;z=0};rotation=[pscustomobject][ordered]@{x=0;y=0;z=0;w=1};distance=14} $depth.balls=@(@{id='native-depth-front';position=@{x=-1;y=3;z=0}},@{id='native-depth-back';position=@{x=1;y=3;z=4}}) $depth.groups=@(@{id='native-depth-front-group';ballIds=@('native-depth-front')},@{id='native-depth-back-group';ballIds=@('native-depth-back')}) $short=$null diff --git a/tools/android/test-playground-contracts.ps1 b/tools/android/test-playground-contracts.ps1 index 06ccfe8..afa3f6f 100644 --- a/tools/android/test-playground-contracts.ps1 +++ b/tools/android/test-playground-contracts.ps1 @@ -1,4 +1,4 @@ -param([Parameter(Mandatory)][string]$EvidenceDir,[string]$FinalSource=(Join-Path $PSScriptRoot 'exercise-final.ps1'),[string]$PlaygroundSource=(Join-Path $PSScriptRoot 'exercise-playground.ps1'),[string]$PreservationFixtureDir,[string]$BoardReadyPng,[string]$HomePng,[string]$ReentryFixtureDir) +param([Parameter(Mandatory)][string]$EvidenceDir,[string]$FinalSource=(Join-Path $PSScriptRoot 'exercise-final.ps1'),[string]$PlaygroundSource=(Join-Path $PSScriptRoot 'exercise-playground.ps1'),[string]$PreservationFixtureDir,[string]$BoardReadyPng,[string]$HomePng,[string]$ReentryFixtureDir,[string]$DepthFixtureDir) $ErrorActionPreference='Stop' New-Item -ItemType Directory -Path $EvidenceDir -Force|Out-Null $checks=[Collections.Generic.List[object]]::new() @@ -95,6 +95,32 @@ exit ([int]$env:PLAYGROUND_CONTROL_TOUCH_EXIT) Probe "actual-preservation-float32-$kind" ($accepted-eq($kind-eq'same-float32')) @{accepted=$accepted;expectedPass=$kind-eq'same-float32'} } Probe 'actual-manual-camera-float32-exact' (Same $floatSource.latestFreePlay.camera $floatProduction.latestFreePlay.camera) 'Same float32 camera components and distance, different JSON decimal representation' + $depthCamera=$gestureAst.Find({param($node)$node-is[Management.Automation.Language.AssignmentStatementAst]-and$node.Left.Extent.Text-ceq'$depth.camera'},$true) + if(!$depthCamera){throw 'Missing actual depth-fixture camera assignment'} + $depth=Clone $floatSource.latestFreePlay;$depthBefore=Clone $depth + & ([scriptblock]::Create($depthCamera.Extent.Text)) + $canonicalCamera='{"target":{"x":0,"y":2.35,"z":0},"rotation":{"x":0,"y":0,"z":0,"w":1},"distance":14}'|ConvertFrom-Json + Probe 'actual-depth-fixture-camera-canonical-dto' (Same $depth.camera $canonicalCamera) @{assignment=$depthCamera.Extent.Text;camera=$depth.camera;scope='Execute actual fixture assignment, then strict DTO comparison'} + Probe 'actual-depth-fixture-camera-property-order' (($depth.camera.PSObject.Properties.Name-join',')-ceq'target,rotation,distance'-and($depth.camera.target.PSObject.Properties.Name-join',')-ceq'x,y,z'-and($depth.camera.rotation.PSObject.Properties.Name-join',')-ceq'x,y,z,w') 'Fixture uses the exact serialized Unity camera property sequence' + $depthUnchanged=Clone $depth;$depthUnchanged.camera=$depthBefore.camera + Probe 'actual-depth-fixture-assignment-only-camera' (Same $depthBefore $depthUnchanged) 'Executing the camera assignment leaves balls, groups, IDs and source unchanged' + foreach($kind in @('target-one-ulp','rotation-one-ulp','distance-one-ulp','changed-rotation','changed-distance')){ + $changed=Clone $canonicalCamera + switch($kind){ + 'target-one-ulp'{$changed.target.y=[double][MathF]::BitIncrement([single]$changed.target.y)} + 'rotation-one-ulp'{$changed.rotation.w=[double][MathF]::BitIncrement([single]$changed.rotation.w)} + 'distance-one-ulp'{$changed.distance=[double][MathF]::BitIncrement([single]$changed.distance)} + 'changed-rotation'{$changed.rotation.y=.1} + 'changed-distance'{$changed.distance=15} + } + Probe "actual-depth-fixture-camera-rejects-$kind" (!(Same $depth.camera $changed)) 'Strict Same must reject camera value mutations against the actual fixture' + } + if($DepthFixtureDir){ + $enteredPath=Join-Path $DepthFixtureDir 'stationary-150-entered.json';$droppedPath=Join-Path $DepthFixtureDir 'stationary-150-dropped.json' + $entered=Get-Content -LiteralPath $enteredPath -Raw|ConvertFrom-Json;$dropped=Get-Content -LiteralPath $droppedPath -Raw|ConvertFrom-Json + Probe 'actual-native-depth-fixture-camera-exact' (Same $depth.camera $dropped.latestFreePlay.camera) @{assignment=$depthCamera.Extent.Text;dropped=$droppedPath;droppedSha256=(Get-FileHash -LiteralPath $droppedPath).Hash;scope='Actual assignment versus NativePreflight7 raw save; replay only, no live native run'} + Probe 'actual-native-depth-entry-drop-camera-exact' (Same $entered.latestFreePlay.camera $dropped.latestFreePlay.camera) @{entered=$enteredPath;enteredSha256=(Get-FileHash -LiteralPath $enteredPath).Hash;dropped=$droppedPath;droppedSha256=(Get-FileHash -LiteralPath $droppedPath).Hash} + } $reentry=$gestureAst.Find({param($node)$node-is[Management.Automation.Language.FunctionDefinitionAst]-and$node.Name-eq'SameProgress'},$true) if($reentry){. ([scriptblock]::Create($reentry.Extent.Text))} Probe 'actual-reentry-comparator-present' ($null-ne$reentry) 'Only outer puzzleStates order may be canonicalized; Same remains strict'