Skip to content

Fix squid lifetime statistics tracking - #41

Merged
ViciousSquid merged 7 commits into
ViciousSquid:2.6.5.0_LatestVersionfrom
snowyukitty:fix/squid-statistics-tracking
Jul 30, 2026
Merged

ViciousSquid merged 7 commits into
ViciousSquid:2.6.5.0_LatestVersionfrom
snowyukitty:fix/squid-statistics-tracking

Conversation

@snowyukitty

@snowyukitty snowyukitty commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • make SquidStatistics the canonical source and persist it directly
  • count sleep from elapsed simulation callbacks and sickness only on false-to-true transitions
  • emit completed neurogenesis births once across threaded, synchronous, and orphan-rescue paths
  • record each accepted startle and resulting ink cloud at most once
  • route food, poop, rock, plant, colour, and distance events through the model even when the statistics tab is absent
  • preserve current and lifetime neuron counts through pruning, loading, and statistics resets
  • preserve lifetime poop and memory maxima and derive age from the persistent model clock
  • keep the statistics tab as a read-only projection of the model

Testing

  • python -m unittest discover -s tests -v (28 passed)
  • python android/tests/test_engine.py (7/7 passed)
  • python -m compileall -q src main.py tests

Closes #26

Summary by CodeRabbit

  • New Features
    • Statistics now sync from the canonical statistics model when the tab becomes visible, with improved model-driven reporting for distance, sleep timing, sickness, and neuron/life counters.
  • Bug Fixes
    • Fixed neuron creation notification behavior to avoid duplicates/missing signals, and aligned ink-cloud/startle, interaction counters, and rock/poop/plant event tracking.
    • Corrected reset/save/load so current and lifetime neuron counts (and related maxima) stay consistent; updated “Max Neurons” export fallback.
  • Tests
    • Expanded wiring, persistence, and reset regression coverage for tab/no-tab and lifetime maxima invariants.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Statistics ownership moved to SquidStatistics, with explicit event, sickness, neuron-count, distance, update, and persistence APIs. TamagotchiLogic and neurogenesis now feed those APIs, while StatisticsTab displays synchronized model state and interaction paths avoid duplicate updates.

Changes

Statistics and neurogenesis synchronization

Layer / File(s) Summary
Canonical statistics model
src/squid_statistics.py, tests/test_squid_statistics.py, tests/test_statistics_persistence.py
SquidStatistics now owns persistence, distance, elapsed-time updates, sickness transitions, neuron counts, serialization, and lifetime maxima.
Simulation and lifecycle integration
src/tamagotchi_logic.py, tests/test_statistics_event_wiring.py
Simulation ticks, gameplay events, sickness state, neurogenesis counts, and save/load flows now use canonical statistics methods.
Neurogenesis event delivery
src/neurogenesis.py, src/brain_widget.py, tests/test_statistics_event_wiring.py
Neuron creation and orphan rescue emit notifications through a shared helper; synchronous completion avoids duplicate handling.
Statistics tab and interaction projection
src/brain_statistics_tab.py, src/brain_about_tab.py, src/interactions.py, src/interactions2.py, src/squid.py
The tab synchronizes from canonical state, compatibility bridges forward events, and interaction paths stop mutating tab-local or duplicate counters.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Neurogenesis
  participant TamagotchiLogic
  participant SquidStatistics
  participant StatisticsTab
  Neurogenesis->>TamagotchiLogic: neuronCreated(neuron_name)
  TamagotchiLogic->>SquidStatistics: record neuron birth and live count
  TamagotchiLogic->>StatisticsTab: update_statistics()
  StatisticsTab->>SquidStatistics: synchronize display data
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #26 by fixing sleep time, sickness episodes, and related lifetime stats via the canonical statistics model.
Out of Scope Changes check ✅ Passed The broader refactor still supports the statistics-tracking fix and persistence/event wiring described by the issue.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing squid lifetime statistics tracking across the model and persistence paths.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/tamagotchi_logic.py (1)

1153-1165: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Ink-cloud follow-up is now gated on the statistics tab, not on the ink cloud actually being created.

Lines 1160-1164 (status "fleeing!", the ink_cloud memory, and the end_ink_flee timer) sit inside if hasattr(self.brain_window, 'statistics_tab'). They therefore run on every startle when the tab exists — even when the 25% ink-cloud roll on Line 1153 failed — and never run when the tab is missing. Those statements belong to the ink-cloud branch.

🐛 Proposed fix for the nesting
             if source != "startled_awake" and random.random() < 0.25:
                 self.create_ink_cloud()
-            
-            # Track startle in statistics (was only in else block)
-            if hasattr(self.brain_window, 'statistics_tab'):
-                self.brain_window.statistics_tab.increment_stat('startles_experienced')
-                
                 self.squid.status = "fleeing!"
                 self.squid.memory_manager.add_short_term_memory(
                     'behaviour', 'ink_cloud', 'Startled! Created an ink cloud'
                 )
                 QtCore.QTimer.singleShot(5000, self.squid.end_ink_flee)
+
+            # Track startle in statistics
+            if hasattr(self.brain_window, 'statistics_tab'):
+                self.brain_window.statistics_tab.increment_stat('startles_experienced')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 1153 - 1165, Move the squid fleeing
follow-up from the statistics-tab guard into the branch that actually executes
after create_ink_cloud(), so status, short-term memory, and the end_ink_flee
timer run only when an ink cloud is created. Keep
increment_stat('startles_experienced') independently guarded by the
statistics_tab check.
🧹 Nitpick comments (4)
src/squid_statistics.py (2)

16-61: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate the key maps as ClassVar to satisfy RUF012.

These are immutable lookup tables; typing them as ClassVar[dict[str, str]] clears the three Ruff warnings and documents intent.

♻️ Proposed annotation
+from typing import ClassVar
+
 class SquidStatistics:
@@
-    _PERSISTENCE_KEYS = {
+    _PERSISTENCE_KEYS: ClassVar[dict] = {
@@
-    _EVENT_KEYS = {
+    _EVENT_KEYS: ClassVar[dict] = {
@@
-    _NEURON_BIRTH_KEYS = {
+    _NEURON_BIRTH_KEYS: ClassVar[dict] = {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/squid_statistics.py` around lines 16 - 61, Annotate the class-level
lookup maps _PERSISTENCE_KEYS, _EVENT_KEYS, and _NEURON_BIRTH_KEYS as
ClassVar[dict[str, str]], adding the required ClassVar import if needed.
Preserve their existing mappings and values.

Source: Linters/SAST tools


118-129: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rollover logic is now duplicated with divergent behaviour.

update_distance (Lines 102-116) keeps its own single-increment rollover branch plus the user-facing message, while add_distance uses divmod and stays silent. Depending on which caller is used, the multiplier semantics and the rollover notification differ. Consider making update_distance compute the magnitude and delegate to add_distance.

♻️ Suggested consolidation
     def update_distance(self, dx, dy):
         '''Track distance traveled by squid with rollover protection'''
-        distance = math.sqrt(dx*dx + dy*dy)
-        self.distance_swam += distance
-
-        # Check for rollover and reset with multiplier
-        if self.distance_swam >= DISTANCE_ROLLOVER_LIMIT:
-            self.distance_swam = self.distance_swam - DISTANCE_ROLLOVER_LIMIT
-            self.distance_swam_multiplier += 1
-
-            # Log the rollover event
-            if hasattr(self.squid, 'tamagotchi_logic'):
-                self.squid.tamagotchi_logic.show_message(
-                    f"🌊 Distance counter rolled over! Now at {self.distance_swam_multiplier}x"
-                )
+        previous_multiplier = self.distance_swam_multiplier
+        self.add_distance(math.sqrt(dx * dx + dy * dy))
+        if (self.distance_swam_multiplier != previous_multiplier
+                and hasattr(self.squid, 'tamagotchi_logic')):
+            self.squid.tamagotchi_logic.show_message(
+                f"🌊 Distance counter rolled over! Now at {self.distance_swam_multiplier}x"
+            )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/squid_statistics.py` around lines 118 - 129, Consolidate distance
rollover handling by updating update_distance to calculate the distance
increment and delegate it to add_distance. Remove its separate rollover
arithmetic and preserve the existing user-facing rollover notification through
the shared path, ensuring both update_distance and add_distance use identical
multiplier semantics.
src/tamagotchi_logic.py (1)

1352-1358: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Direct attribute write bypasses the canonical-statistics API.

Every other lifetime stat now goes through an explicit SquidStatistics method, but max_poops_cleaned is mutated in place here. Consider an observe_poop_count(count) method on the model so the invariant (monotonic maximum) lives with the data.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 1352 - 1358, Update the SquidStatistics
model to expose an observe_poop_count(count) method that enforces the monotonic
max_poops_cleaned invariant, then replace the direct max_poops_cleaned
assignment in the current statistics update flow with that method while
preserving the existing statistics-tab refresh.
src/brain_statistics_tab.py (1)

243-249: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

View reaches into a private method on TamagotchiLogic.

self.tamagotchi_logic._observe_current_neuron_count() couples the read-only tab to logic internals. Exposing a public equivalent (e.g. refresh_neuron_count()) keeps the projection boundary intact. Also note that when squid_stats is absent the user confirms the reset and nothing happens — a message or a mirror reset would be clearer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/brain_statistics_tab.py` around lines 243 - 249, Replace the private
TamagotchiLogic call in the statistics reset flow with a public method such as
refresh_neuron_count(), adding that public equivalent to TamagotchiLogic while
preserving the existing behavior. Also handle the confirmed reset path when
squid_stats is absent by showing a clear user-facing message or resetting the
mirrored statistics state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/tamagotchi_logic.py`:
- Around line 1811-1820: The neuron-count logic in _observe_current_neuron_count
and the current_count calculation around lines 270-292 must exclude
brain_widget.excluded_neurons, matching the widget’s defined count; introduce or
reuse one shared helper for both sites. In src/tamagotchi_logic.py lines
1811-1820, update observe_neuron_count to use that helper; in lines 270-292,
derive current_count from the same helper. Also reconcile the model’s
current_neurons/max_neurons_reached default of 7 with the eight entries in
original_neuron_positions.
- Around line 1393-1400: Update the sleep-statistics update in the simulation
callback to scale the timer interval by self.simulation_speed before passing
elapsed_seconds to squid_statistics.update. Keep the existing
interval-to-seconds conversion and callback cadence unchanged so awake and
sleeping durations accumulate simulated in-game time.

---

Outside diff comments:
In `@src/tamagotchi_logic.py`:
- Around line 1153-1165: Move the squid fleeing follow-up from the
statistics-tab guard into the branch that actually executes after
create_ink_cloud(), so status, short-term memory, and the end_ink_flee timer run
only when an ink cloud is created. Keep increment_stat('startles_experienced')
independently guarded by the statistics_tab check.

---

Nitpick comments:
In `@src/brain_statistics_tab.py`:
- Around line 243-249: Replace the private TamagotchiLogic call in the
statistics reset flow with a public method such as refresh_neuron_count(),
adding that public equivalent to TamagotchiLogic while preserving the existing
behavior. Also handle the confirmed reset path when squid_stats is absent by
showing a clear user-facing message or resetting the mirrored statistics state.

In `@src/squid_statistics.py`:
- Around line 16-61: Annotate the class-level lookup maps _PERSISTENCE_KEYS,
_EVENT_KEYS, and _NEURON_BIRTH_KEYS as ClassVar[dict[str, str]], adding the
required ClassVar import if needed. Preserve their existing mappings and values.
- Around line 118-129: Consolidate distance rollover handling by updating
update_distance to calculate the distance increment and delegate it to
add_distance. Remove its separate rollover arithmetic and preserve the existing
user-facing rollover notification through the shared path, ensuring both
update_distance and add_distance use identical multiplier semantics.

In `@src/tamagotchi_logic.py`:
- Around line 1352-1358: Update the SquidStatistics model to expose an
observe_poop_count(count) method that enforces the monotonic max_poops_cleaned
invariant, then replace the direct max_poops_cleaned assignment in the current
statistics update flow with that method while preserving the existing
statistics-tab refresh.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ad915d9a-d338-4293-95a6-fe293df00cf5

📥 Commits

Reviewing files that changed from the base of the PR and between 3c155ac and ffa5f04.

📒 Files selected for processing (8)
  • src/brain_statistics_tab.py
  • src/brain_widget.py
  • src/neurogenesis.py
  • src/squid_statistics.py
  • src/tamagotchi_logic.py
  • tests/test_squid_statistics.py
  • tests/test_statistics_event_wiring.py
  • tests/test_statistics_persistence.py

Comment thread src/tamagotchi_logic.py
Comment on lines +1393 to +1400

# Record continuous model statistics once per simulation callback.
# The timer interval is explicit so accelerated timers and pauses do
# not turn a UI refresh cadence into the source of sleep duration.
squid_statistics = getattr(self.squid, 'statistics', None)
if squid_statistics:
elapsed_seconds = self.simulation_timer.interval() / 1000.0
squid_statistics.update(elapsed_seconds=elapsed_seconds)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F 'src/tamagotchi_logic.py' || true

echo "== relevant sections =="
wc -l src/tamagotchi_logic.py
sed -n '1320,1420p' src/tamagotchi_logic.py

echo "== search simulation_timer and simulation_speed usages =="
rg -n "simulation_timer|simulation_speed|interval\\(|total_sleep_time|sleep" src/tamagotchi_logic.py

Repository: ViciousSquid/Dosidicus

Length of output: 11874


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== search update_sim_statistics definitions/usages =="
rg -n "update_sim_statistics|elapsed_seconds|squid_statistics|statistics update" src/tamagotchi_logic.py

echo "== inspect update_sim_statistics definition if present =="
python3 - <<'PY'
from pathlib import Path
p=Path("src/tamagotchi_logic.py")
text=p.read_text()
needle="def update_sim_statistics"
idx=text.find(needle)
print("idx", idx)
if idx!=-1:
    start=max(0,idx-2000)
    end=min(len(text),idx+3000)
    print(text[start:end])
PY

Repository: ViciousSquid/Dosidicus

Length of output: 774


Use simulated time for sleep statistics.

interval() shrinks with simulation_speed, so at 4x the callback fires four times with quarter-second increments and accumulates one second per real second. Since the rest of the update loop scales state changes by self.simulation_speed, multiply the elapsed value by self.simulation_speed so awake/sleeping durations match in-game time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 1393 - 1400, Update the
sleep-statistics update in the simulation callback to scale the timer interval
by self.simulation_speed before passing elapsed_seconds to
squid_statistics.update. Keep the existing interval-to-seconds conversion and
callback cadence unchanged so awake and sleeping durations accumulate simulated
in-game time.

Comment thread src/tamagotchi_logic.py Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/tamagotchi_logic.py (1)

2825-2829: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate statistics-restore + sickness-resync logic across load_game and _apply_save_data.

Both methods repeat the exact same self.squid.statistics.load_statistics(...) followed by self._set_sickness_state(getattr(self.squid, 'is_sick', False)) pairing. Consider extracting a small helper (e.g. _restore_statistics_and_sickness(data)) to avoid the two call sites drifting apart in future changes.

Also applies to: 3063-3064

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 2825 - 2829, Extract the duplicated
statistics and sickness restoration sequence from load_game and _apply_save_data
into a shared helper such as _restore_statistics_and_sickness(data). Have the
helper call load_statistics with data.get('statistics', {}) and then
_set_sickness_state using the squid’s is_sick value, and replace both existing
call sites with the helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/tamagotchi_logic.py`:
- Around line 1150-1152: Consolidate ink-cloud creation in startle_squid so each
startle can invoke create_ink_cloud at most once. Remove the
_maybe_create_startle_ink_cloud(source) call from the startle flow and retain
the existing produce_ink, ink_chance, and is_first_startle decision logic,
including its established behavior and statistics updates; add or update an
integration test for startle_squid if the test structure supports it.

---

Nitpick comments:
In `@src/tamagotchi_logic.py`:
- Around line 2825-2829: Extract the duplicated statistics and sickness
restoration sequence from load_game and _apply_save_data into a shared helper
such as _restore_statistics_and_sickness(data). Have the helper call
load_statistics with data.get('statistics', {}) and then _set_sickness_state
using the squid’s is_sick value, and replace both existing call sites with the
helper.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 42a6ca39-2039-41fe-ab72-752bdb5ab416

📥 Commits

Reviewing files that changed from the base of the PR and between ffa5f04 and 4c44446.

📒 Files selected for processing (5)
  • src/brain_statistics_tab.py
  • src/squid_statistics.py
  • src/tamagotchi_logic.py
  • tests/test_squid_statistics.py
  • tests/test_statistics_event_wiring.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_squid_statistics.py

Comment thread src/tamagotchi_logic.py Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/tamagotchi_logic.py (2)

1284-1294: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Two call sites use hasattr instead of a None-safe check for the optional statistics_tab. hasattr(self.brain_window, 'statistics_tab') returns True even when the attribute holds None, unlike the corrected getattr(..., None) + truthiness pattern used in track_startle, track_neuron_creation, and refresh_neuron_count elsewhere in this same PR.

  • src/tamagotchi_logic.py#L1284-L1294: replace the hasattr check in create_ink_cloud with statistics_tab = getattr(self.brain_window, 'statistics_tab', None); if statistics_tab: ... to avoid an AttributeError when the tab is None.
  • src/tamagotchi_logic.py#L1333-L1345: apply the same fix in track_poop_created, and additionally hoist the squid_statistics.max_poops_cleaned update out of the tab-existence check so the canonical model updates even when the tab is absent.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 1284 - 1294, Update create_ink_cloud at
src/tamagotchi_logic.py:1284-1294 to retrieve statistics_tab with getattr(...,
None) and only call update_statistics when the result is truthy. Apply the same
None-safe pattern in track_poop_created at src/tamagotchi_logic.py:1333-1345,
while moving squid_statistics.max_poops_cleaned updates outside the tab check so
the canonical model is always updated.

2908-2909: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Persist the legacy tab statistics on the canonical model.

highest_anxiety, lowest_happiness, and max_short_term_memories / max_long_term_memories are still only updated on self.brain_window.statistics_tab.statistics and are not mapped from SquidStatistics; poops_thrown writes to the canonical model, but the session age direct-tab write is inconsistent with the model-only save path. Add these fields to SquidStatistics, update to_dict()/load_statistics()/_PERSISTENCE_KEYS, and migrate the legacy writes to the canonical model.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tamagotchi_logic.py` around lines 2908 - 2909, Move the legacy statistics
fields highest_anxiety, lowest_happiness, max_short_term_memories,
max_long_term_memories, and session age into SquidStatistics, including them in
to_dict(), load_statistics(), and _PERSISTENCE_KEYS. Update all legacy tab write
sites to mutate self.squid.statistics instead, while preserving poops_thrown’s
canonical-model behavior and keeping the statistics tab read-only.
🧹 Nitpick comments (1)
tests/test_statistics_event_wiring.py (1)

216-274: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage of ink-cloud dedup, but create_ink_cloud internals stay untested.

This test mocks logic.create_ink_cloud = Mock(), so it validates the call-count/gating logic in startle_squid well, but never exercises create_ink_cloud's own body — which is where the hasattr(self.brain_window, 'statistics_tab') bug flagged in src/tamagotchi_logic.py (Lines 1284-1294) lives. Consider adding a case that lets create_ink_cloud run for real with statistics_tab=None to catch this class of regression going forward.

Want me to draft that test?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_statistics_event_wiring.py` around lines 216 - 274, Extend
test_one_startle_creates_at_most_one_ink_cloud so at least one case invokes
create_ink_cloud directly instead of mocking it, while keeping
brain_window.statistics_tab set to None. Assert the real create_ink_cloud path
completes without error and preserves the expected cloud behavior, covering the
statistics_tab handling in create_ink_cloud while retaining the existing
startle_squid gating assertions for the other cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/tamagotchi_logic.py`:
- Around line 1284-1294: Update create_ink_cloud at
src/tamagotchi_logic.py:1284-1294 to retrieve statistics_tab with getattr(...,
None) and only call update_statistics when the result is truthy. Apply the same
None-safe pattern in track_poop_created at src/tamagotchi_logic.py:1333-1345,
while moving squid_statistics.max_poops_cleaned updates outside the tab check so
the canonical model is always updated.
- Around line 2908-2909: Move the legacy statistics fields highest_anxiety,
lowest_happiness, max_short_term_memories, max_long_term_memories, and session
age into SquidStatistics, including them in to_dict(), load_statistics(), and
_PERSISTENCE_KEYS. Update all legacy tab write sites to mutate
self.squid.statistics instead, while preserving poops_thrown’s canonical-model
behavior and keeping the statistics tab read-only.

---

Nitpick comments:
In `@tests/test_statistics_event_wiring.py`:
- Around line 216-274: Extend test_one_startle_creates_at_most_one_ink_cloud so
at least one case invokes create_ink_cloud directly instead of mocking it, while
keeping brain_window.statistics_tab set to None. Assert the real
create_ink_cloud path completes without error and preserves the expected cloud
behavior, covering the statistics_tab handling in create_ink_cloud while
retaining the existing startle_squid gating assertions for the other cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d8bedbb8-e372-4e57-acfd-16a633c642a1

📥 Commits

Reviewing files that changed from the base of the PR and between 4c44446 and e1d1e70.

📒 Files selected for processing (2)
  • src/tamagotchi_logic.py
  • tests/test_statistics_event_wiring.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/squid_statistics.py`:
- Around line 269-271: The reset method currently loses neuron counts by
reinitializing them through __init__. Preserve current_neurons and
max_neurons_reached before reinitialization, invoke __init__(self.squid), then
restore the lifetime maximum and restore current_neurons only as needed to
maintain the minimum current-neuron invariant before statistics are serialized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8ba0eaf2-c4b9-4767-b13a-344ec9f3cdf6

📥 Commits

Reviewing files that changed from the base of the PR and between e1d1e70 and 9f69f64.

📒 Files selected for processing (9)
  • src/brain_about_tab.py
  • src/brain_statistics_tab.py
  • src/interactions.py
  • src/interactions2.py
  • src/squid.py
  • src/squid_statistics.py
  • src/tamagotchi_logic.py
  • tests/test_squid_statistics.py
  • tests/test_statistics_event_wiring.py

Comment thread src/squid_statistics.py Resolved
@ViciousSquid
ViciousSquid merged commit c575b2e into ViciousSquid:2.6.5.0_LatestVersion Jul 30, 2026
1 check passed
ViciousSquid added a commit that referenced this pull request Jul 30, 2026
…tracking"

This reverts commit c575b2e, reversing
changes made to 3c155ac.
@ViciousSquid

Copy link
Copy Markdown
Owner

I merged these changes but had to revert since NONE of the stats were displaying correctly afterwards.
This PR made things worse x
REVERTED BACK TO 2.6.5.0

@snowyukitty

Copy link
Copy Markdown
Contributor Author

I'm sincerely sorry for #41. My change made the Statistics tab worse, and you had to spend your time merging, testing, and reverting it. You were right to revert it. I should have tested the real desktop Qt startup lifecycle before asking you to merge the change; I did not, and that validation failure was mine.

Both desktop entrypoints create SquidBrainWindow before TamagotchiLogic, then attach the completed logic object later. When I changed StatisticsTab into a view of the canonical SquidStatistics model, I failed to update that late-injection path. The propagation list omitted statistics_tab and personality_tab and referenced learning_tab instead of the real nn_viz_tab. The Statistics tab therefore never received the model it had been changed to display, so refreshes returned early and the labels remained at their initial placeholder values.

The tests I submitted with #41 covered model, event, persistence, and reset behavior with fakes, but none constructed the real seven-tab window in its actual startup order. I mistook unit coverage for GUI integration coverage.

I also do not want to pretend that adding the missing tab name was enough. During the repair review, we found and fixed additional ways the restored statistics could still be untruthful: partial or missing statistics files could retain values from the current session; movement used a fixed estimate and missed direct and sleeping paths; a rejected poop spawn could be counted; a click wake was not counted as a startle; and a stopped game could leave its neurogenesis listener attached.

The repair now:

  • binds, clears, and rebinds all seven real tabs and immediately renders the model;
  • treats both save-loading entrypoints as replacement loads, including old saves with no statistics file;
  • records actual post-boundary Euclidean movement once for normal, direct, diagonal, clipped, and sleeping paths;
  • counts only successful events; and
  • disconnects the old neurogenesis listener when a game stops.

The offscreen regression constructs the real SquidBrainWindow and verifies every one of the 17 displayed statistics with distinct nonzero values on both initial binding and replacement rebinding. The exact candidate passes 45 desktop tests and 7 Android engine tests. Adversarial mutation checks also prove the suite fails if the lifecycle sync, empty-load reset, Euclidean distance, event acceptance, signal cleanup, or key UI projections are removed.

I'm very sorry for the extra work and for giving you a change you could not rely on. There is no excuse for asking you to be the integration test.

@ViciousSquid

ViciousSquid commented Jul 30, 2026 •

Copy link
Copy Markdown
Owner

Please submit a brief video or GIF as proof showing that the statistics have indeed been fixed and create a new PR.
I am not willing to take the risk again otherwise x

Thank you for your contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(non serious bug) Some squid statistics not working

2 participants