A/B variantsA/B варіанти NEW v13

v13 finding: Claw Master uses a custom SibirGames.OnlineConfigs framework (NOT Firebase Remote Config, NOT Unity Remote Config). Architecture: each gameplay config sheet is fetched live from Google Sheets on every boot; the "Experiment" sheet (loaded first, Order=-2) routes each user to a variant by hashing their stable user_id and bucketing into a weighted group, then the variant's sheet suffix (e.g., LevelList_VariantB) is downloaded instead of the default tab. Previous notes' "5 variants" was a miscount — actually 1 experiment × 4 arms (control + 3 variants, uniform 25/25/25/25 split). v13 знахідка: Claw Master використовує власний фреймворк SibirGames.OnlineConfigs. Кожен лист конфігу тягнеться з Google Sheets при кожному запуску; лист "Experiment" вантажиться першим і призначає користувача варіанту через хеш user_id. Замість 5 варіантів — насправді 1 експеримент × 4 руки (control + 3 варіанти, рівномірно 25/25/25/25).
FACTS / ASSUMPTIONS / MISSING:
FACT: framework architecture, class names, the baked-in TableExperiment row, group weights, sheet names, the remote endpoint URL.
INFERRED: the mapping TargetSheets="Level" → real sheet name LevelList (the LevelList sheet is the only one starting with "Level").
MISSING: the actual variant override values — they live in Google Sheets tabs LevelList_VariantB/C/D that the APK never sees. To close this gap, fetch the public Apps Script endpoint.

🧪 Active experiments — summary🧪 Активні експерименти — підсумок

⚠ ZERO active experiments in this APK snapshot. 1 experiment row exists (name='default', target=LevelList sheet, 4-arm 25/25/25/25 split) but is_active=0 (dormant). The Google Sheet at id 1q4LO8smTzrYZB...

MdafXt8-TvQK5ZlWdf2TizYZbKcSZ4, tab 'Experiment', is the source of truth at runtime — it overwrites the baked-in TableExperiment asset on every boot (LastUpdateDate is empty, Order=-2). To see what's REALLY running, fetch that sheet.

🎯 The one experiment in this APK🎯 Єдиний експеримент у цьому APK

Experiment nameНазва експерименту
default
Is activeАктивний
NO (dormant) — FACT (IsActive=0 in extracted typetree)
AudienceАудиторія
100% of all installs
Target sheetsЦільові листи
Level → resolves to LevelList (LevelsListConfig)
What it controlsЩо контролює
Master list of all 16 biomes/levels (Neon District, Dark Catacombs, Blazing Caves, Abandoned City, Ghostly Swamp, Ancient Ruins, Frozen Tundra, Desert Oasis, Clockwork Factory, Poisonous Marsh, Scrapyard, Glacial Peaks, Mystic Woods, Crystal Caves, Enchanted Forest, Molten Fields) and per-level metadata. Could be wave counts, biome unlock order, level rewards table linkage.
Rollout splitРозподіл rollout
25/25/25/25 (each group weight = 25)
Variant countКількість варіантів
4

📋 The 4 variant arms📋 Чотири варіанти

VariantВаріант WeightВага Rollout %Rollout % Sheet suffixСуфікс листа MeaningЗначення Override valuesЗначення оверрайдів
variant_a CONTROL2525%(empty = control)Empty suffix = control / default LevelList sheet. Player gets the same data as if they were not in any experiment.unknown — variant_a uses the base LevelList sheet which is fetched live from Google Sheets. No baked-in override values in the APK.
variant_b VARIANT2525%_VariantBPlayer downloads sheet tab named 'LevelList_VariantB' instead of 'LevelList'.unknown — content of LevelList_VariantB tab lives on Google Sheets, not in the APK. Could not be extracted.
variant_c VARIANT2525%_VariantCPlayer downloads sheet tab named 'LevelList_VariantC' instead of 'LevelList'.unknown — content of LevelList_VariantC tab lives on Google Sheets, not in the APK. Could not be extracted.
variant_d VARIANT2525%_VariantDPlayer downloads sheet tab named 'LevelList_VariantD' instead of 'LevelList'.unknown — content of LevelList_VariantD tab lives on Google Sheets, not in the APK. Could not be extracted.

🌐 Remote config endpoint (Google Sheets)🌐 Endpoint віддаленого конфігу (Google Sheets)

Apps Script URLURL Apps Script
https://script.google.com/macros/s/AKfycbxpqIS2yRH8Ext4RMAMOiOWt1H0eendUGfWRtsemN-RJJircsWalLDCOK4Kaei2LPts/exec
Spreadsheet keyКлюч таблиці
1q4LO8smTzrYZBMdafXt8-TvQK5ZlWdf2TizYZbKcSZ4
App nameНазва застосунку
ClawMasterBalance
Balance versionВерсія балансу
4
Experiment sheet nameНазва листа експериментів
Experiment
Last cachedКешовано останній раз
(empty in APK — never cached locally because Order=-2 forces fetch on every boot)

Why "Experiment sheet has no cache":Чому "лист Experiment не кешується":

The Experiment sheet has Order=-2, which forces the manager to fetch it on every boot — bypassing local cache. This means: (a) the experiment state can change at any time without an APK update, (b) the only authoritative source of "what's running right now" is the live Google Sheet, not the APK.Лист Experiment має Order=-2, що змушує менеджер тягнути його при кожному запуску — обходячи локальний кеш. Це означає: (a) стан експерименту може змінитися без оновлення APK, (b) єдине справжнє джерело "що зараз працює" — це сам Google Sheet, не APK.

🏗️ Framework architecture (key classes)🏗️ Архітектура фреймворку (ключові класи)

ClassКлас PurposeПризначення
TableExperimentOnlineConfigBase, ISingletonConfig (dump.cs:878893). Top-level container. Field Experiments[].
ExperimentITableRecord (dump.cs:878908). Fields: ExperimentName(string), IsActive(bool), AudiencePercent(float), TargetSheets(string[]), Groups(TableExperimentGroup[]).
TableExperimentGroupITableRecord (dump.cs:878931). Fields: GroupName(string), GroupWeight(int), TableSuffix(string).
TableExperimentManagerdump.cs:879128. Methods: GetUserGroup, AssignUserToGroup, IsUserInAudience, ChangeUserGroup, RemoveUserFromExperiment, CheckExperiments, GetGroupForAnalitic. Uses GetStableHash on user id for deterministic bucketing.
ExperimentSaveDataPresentdump.cs:880236. PlayerPrefs key prefix: 'user_group_' → groupName. So your assigned variant survives across launches.
OnlineConfigManager.IsExperimentForSheetdump.cs:880064. Decides whether a given live sheet should be re-downloaded with a variant suffix. (Body not decompiled in dump.cs; matching against TargetSheets[] entries.)

Bucketing flow (verified from dump.cs)Логіка bucketing (перевірено з dump.cs)

  1. On boot, OnlineConfigManager fetches the Experiment sheet first (Order=-2).
  2. For each experiment row, TableExperimentManager.GetUserGroup hashes user's stable id with GetStableHash.
  3. If user falls within AudiencePercent, they're assigned to a variant weighted by GroupWeight.
  4. Assignment is saved to PlayerPrefs at key user_group_<experimentName>.
  5. For each sheet in TargetSheets[], the variant's TableSuffix is appended to download the variant-specific tab.
  6. The variant assignment is exposed to analytics via GetGroupForAnalitic (sic — typo in source).

⚠️ What's still missing⚠️ Що ще відсутнє

📝 Correction vs. previous notes📝 Виправлення стосовно попередніх нотаток

EXTRACTION_NOTES.md and README.md said: '5 variants known by name only (Default, variant_a/_VariantB, variant_b/_VariantC, variant_c/_VariantD, variant_d). Actual variant overrides are server-side via OnlineConfigs.'

Now confirmed:

Тепер підтверджено:

Still missing:

Все ще відсутнє:

🎯 Design implications for Claw Fight🎯 Дизайнерські висновки для Claw Fight