Skip to content

Merging multiple new experiment features (classes, advantaged pay, clean aborts)#263

Open
kodacapo wants to merge 44 commits into
jorgearanda:masterfrom
kodacapo:master
Open

Merging multiple new experiment features (classes, advantaged pay, clean aborts)#263
kodacapo wants to merge 44 commits into
jorgearanda:masterfrom
kodacapo:master

Conversation

@kodacapo
Copy link
Copy Markdown
Contributor

@kodacapo kodacapo commented Jun 5, 2026

Three new features, mostly driven by experiments where Fish is invoked from, and returns to, a subject provider such as Gorilla.

(1) The "Class" feature allows subjects to be associated with one of several classes (female/male, progressive/conservative, poor/average/rich, etc). Subjects' class associations are displayed using class-specific emojis. The "Class" feature is implemented using URL params and microworld settings. See the "EXPLAIN" button on the Microworld definition page.

(2) The "Advantage" feature allows experimenters to assign different payments to classes. The "Advantage" feature is implemented using URL params and microworld settings. See the "EXPLAIN" button on the Microworld definition page.

(3) The "Clean Abort" feature uses timeouts to ask the user whether to continue reading the instructions when they first connect to Fish, or continue to wait for additional fishers to join before a Fish simulation can start. The experimenter has full control over the number, the durations and the displayed messages of timeouts, and the URL to where aborting subjects are directed. The "Clean Abort" feature is implemented using microworld settings. See the "EXPLAIN" button in the Microworld definition page.

kodacapo and others added 30 commits January 15, 2026 17:09
- Add family: 4 option to mongoose.connect() to force IPv4
  (localhost was resolving to IPv6 ::1 which MongoDB wasn't listening on)
- Modernize unit-utils.js to use async/await and handle connection states
- Update test helper functions to use modern Mongoose promise API
  instead of deprecated callback syntax

All 287 tests now pass (was 127 passing, 21 failing).
Coverage improved from 43% to 52%.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…antageicon, pfishvalue)

- Add pisadvantaged URL parameter (boolean: true/false/1/0, defaults to false)
- Add padvantageicon URL parameter for advantage status icon display
- Add pfishvalue URL parameter for per-participant fish value override
- Pass pParams through socket events from client to Fisher constructor
- Refactor Fisher to use params object consistently (no duplicate properties)
- Display both pClassIcon and pAdvantageIcon with space between them
- Show icons even when showFisherNames is false
- Fix tests to use params object structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split the "Disable profit columns" checkbox into three separate toggles:
- Disable season profit column (default: off)
- Disable overall profit column (default: off)
- Disable profit diff column (default: on)

Each toggle independently controls its column's visibility in the game
view. Backward compatible with existing microworlds that use the legacy
profitDisplayDisabled field. All 316 tests passing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix pay gap calculation: compare effective fish values instead of
  relying on pHasAdvantage flag, which was not being set correctly
- Fix column hide functions: use attribute selector instead of iterating
  st.fishers (which isn't populated when setupOcean runs)
- Remove references to non-existent #profit-season-th and #profit-total-th
- Add Pay Gap localization key (info_payGap) to all 8 languages
- Display positive gap values with + prefix in blue, negative in red

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… test assertions

Use querySelectorAll instead of querySelector in the jQuery mock so
attribute selectors like $('[id$="-profit-season"]') operate on all
matching elements. Also add css() to the mock and remove assertions
for #profit-season-th and #profit-total-th which don't exist in the
actual template.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New microworld settings section "Fisher Classes" with:
- Enable toggle to activate the feature
- List of class names (array of strings)
- Number of fishers per class (object indexed by class name)
- Emojis for each class (object indexed by class name)
- EXPLAIN button with modal documentation

Validation ensures counts match class names and sum to total fishers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Server-side addFisher() now validates and assigns the default fisher
class when fClass is missing or invalid, matching the client-side
validateFisherClass() logic. Previously, fishers joining without URL
parameters had fClass=null on the server, so status broadcasts never
included a valid class for emoji lookup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ale/Male

Fisher class names are now validated case-insensitively and normalized
to their canonical (capitalized) form in microworld config, client-side
URL param parsing, and server-side addFisher(). Default class names
changed from Class A/Class B to Female/Male with ♀︎/♂︎ emojis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e sub-controls

- Add fish value pay gap, advantage/no-advantage emoji fields to microworld config
- Change profit gap column from "Disable" (default on) to "Enable" (default off)
- Show/hide sub-controls for catch intentions, fisher classes, and fisher advantage
- Implement advantage pay gap in fisher earnings (server-side)
- Use microworld emojis for advantage display instead of URL parameter
- Rename phasadvantage URL param to fhasadvantage, gate on fisherAdvantageEnabled
- Remove pfishvalue/padvantageicon URL params and unicodeToChar (now from microworld)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cy profitDisplayDisabled

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow experimenters to assign a class (e.g., Female/Male) and advantage
status to each bot. Transpose the bot configuration table so properties
are rows and bots are columns. Validate bot class assignments against
class count limits and adjust classesNeeded to account for bot slots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap fisher name emojis in fixed-width spans so names align regardless
of emoji choice. Validate that advantage, no-advantage, and class emojis
are each a single character. Rename advantageIcon to advantageEmoji.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Require fish value pay gap to be at least 0.01 when fisher advantage is
enabled. Update fisher classes and fisher advantage explanation pages
with accurate descriptions of how the features work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows a waiting-room table during ocean setup phase displaying each
fisher's lobby status (reading rules / ready and waiting / missing)
and how long they've been waiting. The current player's row shows
"You". Bot fishers receive staggered timestamps so they can't be
identified. All labels and headers are wired into the translation
system (8 languages).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Clamp readyMins/entryMins to max(0,min(99,...)) to guard against
negative times from client/server clock skew. Emit lobbyStatus to
the room after removeFisherFromOcean so remaining fishers see the
departed fisher removed immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements configurable timeouts for the read-rules and lobby-wait
phases: ocean tracks per-fisher timers, notifies clients via
abortPrompt/forceAbort events, and handles keepReading/proceedToLobby/
keepWaiting/abortFish responses. Adds readRulesTimeout and
lobbyWaitTimeout params to microworld model and config UI, with
localization strings for all new prompts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Display wait times in mm:ss format (capped at 59:59), updating every second
- Randomize bot entry/ready times to rand(k*60, (k+1)*60) seconds before
  ocean creation to avoid suspiciously uniform gaps
- Remove setFisherNotifier call that belongs to clean-abort branch (was
  causing a crash when any human joined)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kodacapo and others added 14 commits May 15, 2026 14:18
… modal

- Microworld UI: wrap abort settings in Enable Clean Abort checkbox with EXPLAIN button
  and show/hide; reset read/wait timeouts to 0 when disabled
- Validation: range checks for abort fields (read/wait 0-10 min, prompt 10-60 sec,
  max timeouts 1-20) with error messages instead of silent clamping
- Fix save function to store integer defaults instead of null for abort fields
- Force-abort modal with OK button and countdown when forceAbort event received
- Refactor duplicate countdown logic into shared startCountdown() helper
- Remove spurious maxTimeouts truthy guard in onPlayerTimeout
- Add /explain-clean-abort page and route
- Lobby status: mm:ss wait time format, random bot entry offsets
- Update status_wait localization to 'Please wait in the lobby' in all 8 languages
- Rename section label 'Abort / timeout' to 'Clean Abort'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ocean.fisherClassesEnabled was not checked when computing classEmoji for
bots, so bots with fClass in their params displayed class icons regardless
of whether the feature was enabled. Human fishers were unaffected because
validateFisherClass() already clears pParams.fClass when the toggle is off.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add abortReadingRulesText, abortLobbyWaitText, forceAbortText fields to
  microworld model; experimenters can supply per-dialog messages or leave
  blank to use the auto-translated system default
- Rename #abort-modal to #maybe-abort-modal to distinguish from force-abort
- When the maybe-abort prompt countdown expires, show force-abort modal
  instead of silently aborting
- Interleave timeout value and message fields in the microworld editor
- Fix readRulesTimeout/lobbyWaitTimeout showing blank when value is 0
- Update EXPLAIN page to document new message fields and revised prompt flow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a participant opens a second tab or refreshes, the new socket now
takes over the existing fisher slot rather than adding a duplicate entry.
The stale socket is displaced (evicted from the room and notified), so it
stops receiving broadcasts and its disconnect no longer evicts the fisher.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When fisher-classes are enabled, a departing human's class slot was never
returned to classesNeeded, preventing new fishers of that class from joining.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dumps the fish database, zips it, and uploads to Dropbox via rclone.
Skips backup if no new runs since the last backup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant