Spaces:
Running
Running
| """悲しい負けモーションのテスト""" | |
| import pytest | |
| import numpy as np | |
| from rock_paper_scissors.config.settings import settings | |
| from rock_paper_scissors.robot.antenna_poses import AntennaPoses | |
| from rock_paper_scissors.robot.head_poses import HeadPoses | |
| from rock_paper_scissors.robot.animations import AnimationController | |
| from rock_paper_scissors.game.states import GameState, GameResult | |
| class TestSadHeadPose: | |
| """悲しい頭ポーズのテスト""" | |
| def test_sad_pitch_is_deep(self): | |
| """しょんぼりは深くうつむく(絶対値25度以上)""" | |
| # Reachy Miniではpitchがプラスで下向き | |
| assert abs(settings.head.sad_pitch) >= 25.0 | |
| def test_get_sad_slow_shake_varies_over_time(self): | |
| """悲しいゆっくり首振りは時間で変化する""" | |
| pose1 = HeadPoses.get_sad_slow_shake(0.0) | |
| pose2 = HeadPoses.get_sad_slow_shake(1.0) | |
| # 異なる時間で異なるポーズを返す(完全一致しない) | |
| assert not np.array_equal(pose1, pose2) | |
| def test_sad_slow_shake_frequency_is_very_slow(self): | |
| """悲しい首振りの周波数は非常に遅い(0.2Hz以下)- 公式サンプル準拠""" | |
| assert settings.head.sad_shake_frequency <= 0.2 | |
| def test_sad_slow_shake_amplitude_is_small(self): | |
| """悲しい首振りの振幅は小さい(3度以下)- 控えめな動き""" | |
| assert settings.head.sad_shake_amplitude <= 3.0 | |
| class TestSadAntennaPose: | |
| """悲しいアンテナポーズのテスト""" | |
| def test_get_sad_droopy_is_low_position(self): | |
| """悲しいアンテナは下がった位置""" | |
| pose = AntennaPoses.get_sad_droopy() | |
| # 両方のアンテナが内側に少し傾いている(小さい値) | |
| assert abs(pose[0]) <= 0.3 | |
| assert abs(pose[1]) <= 0.3 | |
| def test_sad_droopy_is_symmetrical(self): | |
| """悲しいアンテナは左右対称""" | |
| pose = AntennaPoses.get_sad_droopy() | |
| assert pose[0] == -pose[1] # 対称 | |
| class TestLoseAnimationSequence: | |
| """負けアニメーションシーケンスのテスト""" | |
| def test_lose_animation_stays_sad_for_first_1_5_seconds(self): | |
| """負けアニメーションは最初の1.5秒間は悲しいまま""" | |
| controller = AnimationController() | |
| controller.set_state(GameState.REACT, game_result=GameResult.LOSE) | |
| # 0.5秒後も悲しいポーズのはず(アンテナは下がった位置) | |
| head, antennas = controller._get_react_target(0.5) | |
| sad_droopy = AntennaPoses.get_sad_droopy() | |
| assert np.array_equal(antennas, sad_droopy) | |
| # 1.0秒後もまだ悲しいポーズ | |
| head2, antennas2 = controller._get_react_target(1.0) | |
| assert np.array_equal(antennas2, sad_droopy) | |
| def test_lose_animation_recovers_after_1_5_seconds(self): | |
| """負けアニメーションは1.5秒後から回復を始める""" | |
| controller = AnimationController() | |
| controller.set_state(GameState.REACT, game_result=GameResult.LOSE) | |
| # 2.0秒後は回復ポーズ | |
| head, antennas = controller._get_react_target(2.0) | |
| # アンテナが開いている(回復)ことを確認 | |
| open_wide = AntennaPoses.get_open_wide() | |
| assert np.array_equal(antennas, open_wide) | |
| def test_lose_animation_head_stays_still_during_sad_phase(self): | |
| """悲しいフェーズ中、頭は静かにうつむいたまま(動きなし)""" | |
| controller = AnimationController() | |
| controller.set_state(GameState.REACT, game_result=GameResult.LOSE) | |
| # 異なる時間でも頭のポーズは同じ(静止) | |
| head1, _ = controller._get_react_target(0.0) | |
| head2, _ = controller._get_react_target(0.5) | |
| # ポーズが同じ(静かにうつむいている) | |
| assert np.array_equal(head1, head2) | |
| class TestSadAnimationSettings: | |
| """悲しいアニメーション設定のテスト""" | |
| def test_sad_duration_exists(self): | |
| """悲しい状態の持続時間設定が存在する""" | |
| assert hasattr(settings.head, 'sad_duration') | |
| assert settings.head.sad_duration >= 1.0 | |
| def test_sad_shake_settings_exist(self): | |
| """悲しい首振りの設定が存在する""" | |
| assert hasattr(settings.head, 'sad_shake_frequency') | |
| assert hasattr(settings.head, 'sad_shake_amplitude') | |