feat: pogoda, poprawki w wyświetlaniu. Clean Architecture

This commit is contained in:
2026-06-05 16:36:43 +02:00
parent 7ba9c55e27
commit 856990f232
17 changed files with 1517 additions and 634 deletions
+220
View File
@@ -0,0 +1,220 @@
#include <unity.h>
#include "BuddyLogic.h"
static int32_t fixed_rng(int32_t lo, int32_t hi) { (void)hi; return lo; }
void setUp() {}
void tearDown() {}
// ── initBuddy ──────────────────────────────────────────────────────────────
void test_initBuddy_sets_open_blink() {
BuddyState b{};
initBuddy(b, 0);
TEST_ASSERT_EQUAL(BLINK_OPEN, b.blinkState);
TEST_ASSERT_EQUAL(EYE_RY, b.blinkRy);
}
void test_initBuddy_sets_normal_mood() {
BuddyState b{};
initBuddy(b, 0);
TEST_ASSERT_EQUAL(MOOD_NORMAL, b.mood);
}
void test_initBuddy_timestamps_relative_to_now() {
BuddyState b{};
initBuddy(b, 1000);
TEST_ASSERT_EQUAL(1000u, b.lastEvent);
TEST_ASSERT_EQUAL(1000u + 3000, b.nextBlink);
TEST_ASSERT_EQUAL(1000u + 2000, b.nextLook);
}
// ── setBuddyMood ───────────────────────────────────────────────────────────
void test_setBuddyMood_no_duration_sets_revertAt_zero() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 1000, 0);
TEST_ASSERT_EQUAL(0u, b.revertAt);
}
void test_setBuddyMood_with_duration_sets_revertAt() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 1000, 4000);
TEST_ASSERT_EQUAL(5000u, b.revertAt);
}
void test_setBuddyMood_updates_lastEvent() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 5000);
TEST_ASSERT_EQUAL(5000u, b.lastEvent);
}
void test_setBuddyMood_happy_sets_pupil_target_up() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 0);
TEST_ASSERT_EQUAL( 0, b.pupilTargetDx);
TEST_ASSERT_EQUAL(-2, b.pupilTargetDy);
}
void test_setBuddyMood_sad_sets_pupil_target_down() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_SAD, 0);
TEST_ASSERT_EQUAL(0, b.pupilTargetDx);
TEST_ASSERT_EQUAL(4, b.pupilTargetDy);
}
// ── updateBuddyAnim — mood revert ─────────────────────────────────────────
void test_updateBuddyAnim_reverts_mood_when_revertAt_passed() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 0, 4000); // revertAt = 4000
updateBuddyAnim(b, 5000, fixed_rng); // now > revertAt
TEST_ASSERT_EQUAL(MOOD_NORMAL, b.mood);
TEST_ASSERT_EQUAL(0u, b.revertAt);
}
void test_updateBuddyAnim_does_not_revert_before_revertAt() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_HAPPY, 0, 4000);
updateBuddyAnim(b, 3999, fixed_rng);
TEST_ASSERT_EQUAL(MOOD_HAPPY, b.mood);
}
void test_updateBuddyAnim_goes_sleepy_after_idle() {
BuddyState b{};
initBuddy(b, 0); // lastEvent = 0, mood = NORMAL
updateBuddyAnim(b, 300001, fixed_rng);
TEST_ASSERT_EQUAL(MOOD_SLEEPY, b.mood);
}
void test_updateBuddyAnim_no_sleepy_before_idle() {
BuddyState b{};
initBuddy(b, 0);
updateBuddyAnim(b, 299999, fixed_rng);
TEST_ASSERT_EQUAL(MOOD_NORMAL, b.mood);
}
// ── Blink state machine ────────────────────────────────────────────────────
void test_blink_open_to_closing_when_nextBlink_passed() {
BuddyState b{};
initBuddy(b, 0); // nextBlink = 3000
updateBuddyAnim(b, 3001, fixed_rng);
TEST_ASSERT_EQUAL(BLINK_CLOSING, b.blinkState);
}
void test_blink_closing_decrements_blinkRy() {
BuddyState b{};
initBuddy(b, 0);
b.blinkState = BLINK_CLOSING;
b.blinkRy = 15;
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(11, b.blinkRy);
TEST_ASSERT_EQUAL(BLINK_CLOSING, b.blinkState);
}
void test_blink_closing_reaches_closed_when_small() {
BuddyState b{};
initBuddy(b, 0);
b.blinkState = BLINK_CLOSING;
b.blinkRy = 3;
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(BLINK_CLOSED, b.blinkState);
TEST_ASSERT_EQUAL(1, b.blinkRy);
}
void test_blink_closed_ticks_to_opening() {
BuddyState b{};
initBuddy(b, 0);
b.blinkState = BLINK_CLOSED;
b.closedTicks = 2;
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(BLINK_OPENING, b.blinkState);
}
void test_blink_opening_increments_blinkRy() {
BuddyState b{};
initBuddy(b, 0);
b.blinkState = BLINK_OPENING;
b.blinkRy = 7; // 7+4=11 < EYE_RY(15), stays OPENING
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(11, b.blinkRy);
TEST_ASSERT_EQUAL(BLINK_OPENING, b.blinkState);
}
void test_blink_opening_returns_to_open_at_eye_ry() {
BuddyState b{};
initBuddy(b, 0);
b.blinkState = BLINK_OPENING;
b.blinkRy = 13; // 13+4=17 >= EYE_RY(15) → OPEN
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(BLINK_OPEN, b.blinkState);
TEST_ASSERT_EQUAL(EYE_RY, b.blinkRy);
}
void test_surprised_does_not_blink() {
BuddyState b{};
initBuddy(b, 0);
setBuddyMood(b, MOOD_SURPRISED, 0);
b.nextBlink = 0; // past-due
updateBuddyAnim(b, 1000, fixed_rng);
TEST_ASSERT_EQUAL(BLINK_OPEN, b.blinkState); // no transition
TEST_ASSERT_EQUAL(EYE_RY, b.blinkRy); // stays full
}
// ── Pupil saccade ──────────────────────────────────────────────────────────
void test_pupil_moves_fast_when_far() {
BuddyState b{};
initBuddy(b, 0);
b.pupilDx = 0;
b.pupilTargetDx = 8; // |delta| = 8 >= 4 → step 3
b.pupilDy = b.pupilTargetDy = 0;
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(3, b.pupilDx);
}
void test_pupil_moves_slow_when_close() {
BuddyState b{};
initBuddy(b, 0);
b.pupilDx = 0;
b.pupilTargetDx = 2; // |delta| = 2 < 4 → step 1
b.pupilDy = b.pupilTargetDy = 0;
updateBuddyAnim(b, 0, fixed_rng);
TEST_ASSERT_EQUAL(1, b.pupilDx);
}
// ── main ──────────────────────────────────────────────────────────────────
int main() {
UNITY_BEGIN();
RUN_TEST(test_initBuddy_sets_open_blink);
RUN_TEST(test_initBuddy_sets_normal_mood);
RUN_TEST(test_initBuddy_timestamps_relative_to_now);
RUN_TEST(test_setBuddyMood_no_duration_sets_revertAt_zero);
RUN_TEST(test_setBuddyMood_with_duration_sets_revertAt);
RUN_TEST(test_setBuddyMood_updates_lastEvent);
RUN_TEST(test_setBuddyMood_happy_sets_pupil_target_up);
RUN_TEST(test_setBuddyMood_sad_sets_pupil_target_down);
RUN_TEST(test_updateBuddyAnim_reverts_mood_when_revertAt_passed);
RUN_TEST(test_updateBuddyAnim_does_not_revert_before_revertAt);
RUN_TEST(test_updateBuddyAnim_goes_sleepy_after_idle);
RUN_TEST(test_updateBuddyAnim_no_sleepy_before_idle);
RUN_TEST(test_blink_open_to_closing_when_nextBlink_passed);
RUN_TEST(test_blink_closing_decrements_blinkRy);
RUN_TEST(test_blink_closing_reaches_closed_when_small);
RUN_TEST(test_blink_closed_ticks_to_opening);
RUN_TEST(test_blink_opening_increments_blinkRy);
RUN_TEST(test_blink_opening_returns_to_open_at_eye_ry);
RUN_TEST(test_surprised_does_not_blink);
RUN_TEST(test_pupil_moves_fast_when_far);
RUN_TEST(test_pupil_moves_slow_when_close);
return UNITY_END();
}