Этап 41 ревизия 4 (финальная): размер рыбы — узловая таблица по степеням двойки, интерполяция по log2(веса). fishSizeFromW(w) + FISH_SIZE_KNOTS=[[0,16],[1,20],[2,25],[3,35],[4,48],[5,64],[6,80],[7,100],[8,120],[9,170],[log2(1000),256]] ([log2(w/0.1), длина px]) — явная таблица пользователя (веса степени двойки, «погрешность 10%»): степенная шкала ревизии 3 не покрыла таблицу в середине (на 25.6 кг было бы +24% к цифрам; локальный показатель кривой 0.26..0.61) — заменена узлами. Длина силуэта = 2.45·fs (тело 2·fs + хвост), интерполяция линейна по log2(w) — узлы бьются ТОЧНО (0% отклонения, проверено: 16/20/25/35/48/64/80/100/120/170/256 px), кривая монотонна (1000 точек); веса вне 0.1–100 кг клампятся в края (нижний кламп — только золотая рыбка 0.05–0.1 кг). Распределение: 0.1 кг → 16 px (0.25× лодки), 0.2 → 20, 0.4 → 25, 0.8 → 35, 1.6 → 48, 3.2 → 64 px (= лодка), 6.4 → 80, 12.8 → 100, 25.6 → 120, 51.2 → 170 px, 100 кг (кит max) → 256 px (4× лодки); 1 кг → 39.2 px, 10 кг → 92.9 px; босс 20–50 кг → 113–168 px (1.77–2.6×). Диапазон 16..256 px = ×16. Тесты: пинов на размер силуэта нет — 193/193 PASS, exit 0; check.mjs OK; скриншоты пересняты (кадр reel: 12.5 кг ≈ 99 px ≈ 1.55× лодки); узлы 100/3.2/0.1 кг проверены живыми кадрами headless-Chromium (численный контроль 16.0/64.0/256.0 px). Доки: DEVLOG (Этап 41 — таблица, интерполяция, пометки ревизий 3/4).
@@ -751,16 +751,16 @@ git add -A && git commit -m "что изменилось" && git push
|
||||
|
||||
## Этап 41. Размер рыбы при вываживании — от абсолютного веса (0.1 кг → минимум, 100 кг → 2× лодки)
|
||||
|
||||
**Задача:** «размер рыбы в воде (когда её вытягиваешь) должен соответствовать её весу в кг, а не минимальному/максимальному весу вида; диапазон больше: 0.1 кг — максимально маленькая как сейчас, 100 кг — в 2 раза больше лодки». Первая ревизия этапа была лог-шкалой (средние рыбы 1–10 кг подросли до 0.9–1.4× лодки — «все рыбы сильно большие»); по решению заменена на линейную. Вторая ревизия: минимум опустили ещё — 0.1 кг с длины 19.6 px до **8 px** («ещё меньше»). Третья ревизия: **100 кг → 256 px** (×2 к 128, т.е. 4× лодки) и **1 кг → 20 px**; предложенная квадратичная шкала 3 якоря не держит монотонно (парабола по w: пик ~420 px на 61 кг, затем схождение к 256 px на 100 кг — кит меньше «средней» рыбы; квадратичная по ln w: провал до ~4 px у 0.2 кг) — взята степенная `L = 3.95 + 16.05·w^0.598`, точная по всем трём якорям и монотонная.
|
||||
**Задача:** «размер рыбы в воде (когда её вытягиваешь) должен соответствовать её весу в кг, а не минимальному/максимальному весу вида; диапазон больше: 0.1 кг — максимально маленькая как сейчас, 100 кг — в 2 раза больше лодки». Первая ревизия этапа была лог-шкалой (средние рыбы 1–10 кг подросли до 0.9–1.4× лодки — «все рыбы сильно большие»); по решению заменена на линейную. Вторая ревизия: минимум опустили ещё — 0.1 кг с длины 19.6 px до **8 px** («ещё меньше»). Третья ревизия: **100 кг → 256 px** (×2 к 128, т.е. 4× лодки) и **1 кг → 20 px**; предложенная квадратичная шкала 3 якоря не держит монотонно (парабола по w: пик ~420 px на 61 кг, затем схождение к 256 px на 100 кг — кит меньше «средней» рыбы; квадратичная по ln w: провал до ~4 px у 0.2 кг) — взята степенная `L = 3.95 + 16.05·w^0.598`, точная по всем трём якорям и монотонная. Четвёртая ревизия (финальная): **явная узловая таблица пользователя** (веса — степени двойки, длины 16..256 px, «погрешность 10%»): степенная формула не покрыла таблицу в середине (на 25.6 кг было бы +24% к цифрам таблицы; локальный показатель кривой гуляет 0.26..0.61) — заменена линейной интерполяцией по log₂(веса) между узлами: узлы бьются точно (0%), кривая монотонна, вне 0.1–100 кг — кламп в края таблицы.
|
||||
|
||||
**Решения:**
|
||||
- **Новый хелпер `fishSizeFromW(w)`** (секция «ОТРИСОВКА», перед `drawHookedFish()`): **степенная по ДЛИНЕ силуэта** (длина = 2.45·fs: тело 2·fs + хвост): `fs = (3.95 + 16.05·(max(0.1,w))^0.5981)/2.45`. Якоря: **0.1 кг → 8 px** (мелочь-мелкая), **1 кг → 20 px**, **100 кг → 256 px = 4× лодки 64 px** из `drawBoat()` (`bx−32..bx+32`). Веса <0.1 кг клампятся в минимум (затрагивает только золотую рыбку 0.05–0.1 кг). Размер лодки (64 px) достигают ~9.1 кг; распределение: 0.1–1 кг 8..20 px (мелочь), 10 кг ≈ 1.05× лодки, 50 кг ≈ 2.7×, 100 кг = 4×.
|
||||
- **`drawHookedFish()`:** `fs = fishSizeFromW(reel.w)` (было `8+(reel.w/sp.wMax)*10+sp.rarity`). Убраны **`+sp.rarity`** (редкая рыбка не обязана быть крупнее — размер = вес) и **босс-множитель ×1.5** (М4): босс весит 20–50 кг (1.57–2.67× лодки по степенной шкале), с ×1.5 босс-рак 30 кг выглядел бы крупнее кита 100 кг — противоречие «крупнее вес → крупнее рыба»; драматизм босса теперь несёт аура + бейдж + фазы. Золотая аура босса сохранена (читает новый `fs`).
|
||||
- **Новый хелпер `fishSizeFromW(w)` + таблица `FISH_SIZE_KNOTS`** (секция «ОТРИСОВКА», перед `drawHookedFish()`): узлы `[log2(w/0.1), длина px] = [0,16],[1,20],[2,25],[3,35],[4,48],[5,64],[6,80],[7,100],[8,120],[9,170],[log2(1000),256]`, интерполяция линейна по log₂(веса) (узлы — степени двойки), длина силуэта = 2.45·fs (тело 2·fs + хвост). Узлы: **0.1 кг → 16 px** · 0.2 → 20 · 0.4 → 25 · 0.8 → 35 · 1.6 → 48 · 3.2 → 64 (= лодка) · 6.4 → 80 · 12.8 → 100 · 25.6 → 120 · 51.2 → 170 · **100 кг → 256 px = 4× лодки 64 px** из `drawBoat()` (`bx−32..bx+32`). Веса вне 0.1–100 кг клампятся в края таблицы (нижний кламп затрагивает только золотую рыбку 0.05–0.1 кг).
|
||||
- **`drawHookedFish()`:** `fs = fishSizeFromW(reel.w)` (было `8+(reel.w/sp.wMax)*10+sp.rarity`). Убраны **`+sp.rarity`** (редкая рыбка не обязана быть крупнее — размер = вес) и **босс-множитель ×1.5** (М4): босс весит 20–50 кг (113–168 px = 1.77–2.6× лодки по узловой шкале), с ×1.5 босс-рак 30 кг выглядел бы крупнее кита 100 кг — противоречие «крупнее вес → крупнее рыба»; драматизм босса теперь несёт аура + бейдж + фазы. Золотая аура босса сохранена (читает новый `fs`).
|
||||
- **Не тронуто:** подплывающая рыба до подсечки (APPROACH/BITE, `12+rarity*2.5` — вес к моменту подплывания ещё не зароллен, `hook()` роллит его при подсечке), фоновые рыбы `rand(8,22)`, 🐟-маркер на дистанционной полосе, emoji-карточка улова. Баланс/роллы не задеты: `wMin/wMax` остаются только в `rollWeight()`/`hook()`/`st0`.
|
||||
|
||||
**Размеры (полная длина силуэта; лодка = 64 px):** 0.1 кг → 8 px (0.13×) · 1 кг → 20 px (0.31×) · 5 кг → 46 px (0.72×) · 10 кг → 67.6 px (1.05×) · 20 кг (босс min) → 100 px (1.57×) · 50 кг (босс max) → 170.6 px (2.67×) · 100 кг (кит max) → 256 px (**4×**). Диапазон 8..256 px = ×32 (в исходной формуле ~20..54 px = ×2.7). Тяжёлая рыба в конце вываживания (позиция `boatX+24`, поверх лодки) заметно перекрывает лодку — осознанный эффект «вывезена рядом с лодкой»; на мобильном 360 px кит ≈ 71% ширины экрана.
|
||||
**Размеры (полная длина силуэта; лодка = 64 px):** 0.1 кг → 16 px (0.25×) · 0.2 → 20 px (0.31×) · 0.4 → 25 px (0.39×) · 0.8 → 35 px (0.55×) · 1.6 → 48 px (0.75×) · 3.2 → 64 px (**1× = лодка**) · 6.4 → 80 px (1.25×) · 12.8 → 100 px (1.56×) · 25.6 → 120 px (1.88×) · 51.2 → 170 px (2.66×) · 100 кг (кит max) → 256 px (**4×**). Диапазон 16..256 px = ×16; между узлами — линейно по log₂(веса) (проверено: узлы 0% отклонения, монотонность 1000 точек). Тяжёлая рыба в конце вываживания (позиция `boatX+24`, поверх лодки) заметно перекрывает лодку — осознанный эффект «вывезена рядом с лодкой»; на мобильном 360 px кит ≈ 71% ширины экрана.
|
||||
|
||||
**Тесты:** пины на размер силуэта в `tests/test.js` отсутствуют (проверено: `drawFishShape`/`drawHookedFish`/`fishReelPos` не ассертятся; `reel.w` в тестах — для физики). Итого **193/193 PASS, exit 0**; `check.mjs` OK; `tools/balance.mjs` — пины без изменений (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). Скриншоты перегенерированы (`gen-screenshots.js`, 30 кадров; кадр `reel` форсит `reel.w=12.5` — рыба ~77 px ≈ 1.2× лодки).
|
||||
**Тесты:** пины на размер силуэта в `tests/test.js` отсутствуют (проверено: `drawFishShape`/`drawHookedFish`/`fishReelPos` не ассертятся; `reel.w` в тестах — для физики). Итого **193/193 PASS, exit 0**; `check.mjs` OK; `tools/balance.mjs` — пины без изменений (Река 65.1/125.9 · Озёра 194.1/249.0 · Море 297.3/476.7 · Океан 329.1/552.7). Скриншоты перегенерированы (`gen-screenshots.js`, 30 кадров; кадр `reel` форсит `reel.w=12.5` — рыба ~99 px ≈ 1.55× лодки).
|
||||
|
||||
## Этап 42. SVG-портреты рыб в дневнике и карточке улова
|
||||
|
||||
|
||||
@@ -2579,13 +2579,20 @@ function fishReelPos(){
|
||||
return {x:x,y:y};
|
||||
}
|
||||
/* Размер силуэта пойманной рыбы — от АБСОЛЮТНОГО веса (кг), не от wMin/wMax вида.
|
||||
Степенная шкала по ДЛИНЕ силуэта (длина = 2.45·fs: тело 2·fs + хвост), якоря:
|
||||
0.1 кг → 8 px (мелочь), 1 кг → 20 px, 100 кг → 256 px = 4× лодки 64 px.
|
||||
Буквально квадратичная шкала 3 якоря не держит (парабола по w пиковала ~420 px на 61 кг
|
||||
и сходилась к 100 кг; по ln w провисала до 4 px у 0.2 кг) — степенная A+B·w^0.598 точна и монотонна.
|
||||
Веса <0.1 кг клампятся в минимум. Средние (длина): 5 кг → 46 px, 10 кг → 67.6 px (размер лодки ~9.1 кг),
|
||||
20 кг → 100 px, 50 кг → 170.6 px. */
|
||||
const fishSizeFromW=w=>(3.95+16.05*Math.pow(Math.max(0.1,w),0.5981))/2.45;
|
||||
УЗЛОВАЯ ТАБЛИЦА (длина силуэта = 2.45·fs: тело 2·fs + хвост), узлы по степеням двойки:
|
||||
0.1 кг → 16 px · 0.2 → 20 · 0.4 → 25 · 0.8 → 35 · 1.6 → 48 · 3.2 → 64 (= лодка) ·
|
||||
6.4 → 80 · 12.8 → 100 · 25.6 → 120 · 51.2 → 170 · 100 → 256 px = 4× лодки 64 px.
|
||||
Интерполяция линейна по log2(веса) — узлы степени двойки, кривая монотонна, узлы бьёт точно.
|
||||
Веса <0.1 кг клампятся в 16 px, >100 кг — в 256 px. */
|
||||
const FISH_SIZE_KNOTS=[[0,16],[1,20],[2,25],[3,35],[4,48],[5,64],[6,80],[7,100],[8,120],[9,170],[Math.log2(1000),256]]; // [log2(w/0.1), длина px]
|
||||
function fishSizeFromW(w){
|
||||
const t=Math.log2(Math.max(0.1,Math.min(100,w))/0.1);
|
||||
for(let i=1;i<FISH_SIZE_KNOTS.length;i++){
|
||||
const t0=FISH_SIZE_KNOTS[i-1][0],l0=FISH_SIZE_KNOTS[i-1][1],t1=FISH_SIZE_KNOTS[i][0],l1=FISH_SIZE_KNOTS[i][1];
|
||||
if(t<=t1) return (l0+(l1-l0)*(t-t0)/(t1-t0))/2.45;
|
||||
}
|
||||
return 256/2.45;
|
||||
}
|
||||
function drawHookedFish(){
|
||||
if(state!=='REEL'||!reel) return;
|
||||
const sp=reel.sp;
|
||||
|
||||
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 244 KiB After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 266 KiB After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 229 KiB After Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 261 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 148 KiB |