dankgrinder 8.103.0 → 8.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/grinder.js +64 -13
  2. package/package.json +1 -1
package/lib/grinder.js CHANGED
@@ -670,6 +670,7 @@ class AccountWorker {
670
670
  this._levelQuestActive = false;
671
671
  this._levelQuestQueue = [];
672
672
  this._levelQuestDone = new Set();
673
+ this._levelQuestProgressCache = new Map();
673
674
  this._questBetOverride = null;
674
675
  this._lastCommandMeta = null;
675
676
  this._commandRunning = false; // prevents grinding commands from overlapping with quest commands
@@ -1558,6 +1559,11 @@ class AccountWorker {
1558
1559
  if (lvMatch) {
1559
1560
  const targetLv = parseInt(lvMatch[1]);
1560
1561
  cmdResult.levelLocked = targetLv;
1562
+ const progress = this._parseLevelQuestProgress(targetLv, allDetectionText);
1563
+ if (progress) {
1564
+ cmdResult.levelQuestProgress = progress;
1565
+ this._mergeLevelQuestProgress(targetLv, progress);
1566
+ }
1561
1567
  this.log('warn', `Command /${cmdName} requires Level ${targetLv} quests`);
1562
1568
  }
1563
1569
  }
@@ -1746,10 +1752,10 @@ class AccountWorker {
1746
1752
  this._lastCommandMeta.nonPlay = true;
1747
1753
  this._lastCommandMeta.levelLocked = targetLv;
1748
1754
  this.log('warn', `Command /${cmdName} is LOCKED at Level ${targetLv} — starting quest unlock flow`);
1749
- if (this._startLevelQuests(targetLv)) {
1755
+ if (this._startLevelQuests(targetLv, cmdResult.levelQuestProgress || null)) {
1750
1756
  this.log('info', `[QUEST] Quest mode activated for Level ${targetLv} — grinding will resume after quests complete`);
1751
1757
  } else {
1752
- this.log('warn', `[QUEST] Level ${targetLv} quests already done or not defined — grinding continues (may re-trigger)`);
1758
+ this.log('warn', `[QUEST] Level ${targetLv} quests already done or not defined — waiting for verification`);
1753
1759
  }
1754
1760
  // Don't count as success — skip normal post-command processing
1755
1761
  return;
@@ -1924,11 +1930,56 @@ class AccountWorker {
1924
1930
  ],
1925
1931
  };
1926
1932
 
1927
- _startLevelQuests(targetLevel) {
1933
+ _parseLevelQuestProgress(targetLevel, rawText) {
1934
+ if (targetLevel !== 5) return null;
1935
+ const text = String(rawText || '');
1936
+ const out = {};
1937
+ const re = /(\d[\d,]*)\s*\/\s*50,000[\s\S]{0,180}?<\/(slots|cointoss|snakeeyes):/gi;
1938
+ let m;
1939
+ while ((m = re.exec(text)) !== null) {
1940
+ const cur = parseInt(String(m[1] || '').replace(/,/g, ''), 10);
1941
+ const cmd = String(m[2] || '').toLowerCase();
1942
+ if (Number.isFinite(cur) && cmd) out[cmd] = Math.max(0, cur);
1943
+ }
1944
+ return Object.keys(out).length > 0 ? out : null;
1945
+ }
1946
+
1947
+ _mergeLevelQuestProgress(targetLevel, progressHint) {
1948
+ if (!progressHint || targetLevel !== 5) return;
1949
+ const prev = this._levelQuestProgressCache.get(targetLevel) || {};
1950
+ const merged = { ...prev };
1951
+ for (const [cmd, val] of Object.entries(progressHint)) {
1952
+ const n = Number(val);
1953
+ if (!Number.isFinite(n) || n < 0) continue;
1954
+ merged[cmd] = Math.max(merged[cmd] || 0, n);
1955
+ }
1956
+ this._levelQuestProgressCache.set(targetLevel, merged);
1957
+ }
1958
+
1959
+ _startLevelQuests(targetLevel, progressHint = null) {
1928
1960
  if (this._levelQuestDone.has(targetLevel)) return false;
1929
1961
  const quests = AccountWorker.LEVEL_QUESTS[targetLevel];
1930
1962
  if (!quests || quests.length === 0) return false;
1931
- this._levelQuestQueue = quests.map(q => ({ ...q, level: targetLevel, _lostSoFar: 0 }));
1963
+
1964
+ this._mergeLevelQuestProgress(targetLevel, progressHint);
1965
+ const cached = this._levelQuestProgressCache.get(targetLevel) || {};
1966
+ const seededQueue = quests
1967
+ .map(q => {
1968
+ const target = Number(q.loseTarget || 0);
1969
+ const seeded = target > 0 ? Math.min(target, Math.max(0, Number(cached[q.cmd] || 0))) : 0;
1970
+ return { ...q, level: targetLevel, _lostSoFar: seeded };
1971
+ })
1972
+ .filter(q => !(q.loseTarget && q._lostSoFar >= q.loseTarget));
1973
+
1974
+ if (seededQueue.length === 0) {
1975
+ this.log('info', `[QUEST] Level ${targetLevel} tasks already complete from progress cache — verifying unlock`);
1976
+ this._verifyLevelUnlock = targetLevel;
1977
+ this.setStatus('verifying level...');
1978
+ this.commandQueue = null;
1979
+ return false;
1980
+ }
1981
+
1982
+ this._levelQuestQueue = seededQueue;
1932
1983
  this._levelQuestActive = true;
1933
1984
  this._questBetOverride = null;
1934
1985
  // Clear commandQueue so no stale grinding commands fire after quests finish
@@ -1936,7 +1987,10 @@ class AccountWorker {
1936
1987
  this._commandRunning = false; // cancel any in-flight grinding command
1937
1988
  this.log('info', `[QUEST] Level ${targetLevel} quests started — grinding PAUSED`);
1938
1989
  const questList = this._levelQuestQueue.map(q => {
1939
- if (q.loseTarget) return `"${q.cmd}" lose ⏣${q.loseTarget.toLocaleString()}`;
1990
+ if (q.loseTarget) {
1991
+ const rem = Math.max(0, q.loseTarget - (q._lostSoFar || 0));
1992
+ return `"${q.cmd}" lose ⏣${rem.toLocaleString()} more`;
1993
+ }
1940
1994
  return `"${q.cmd}" x${q.times}`;
1941
1995
  }).join(', ');
1942
1996
  this.log('info', `[QUEST] Quests: ${questList}`);
@@ -2204,11 +2258,13 @@ class AccountWorker {
2204
2258
  if (currentLv >= targetLv) {
2205
2259
  this.log('success', `[QUEST] Level ${targetLv} verified ✓ — level unlocked!`);
2206
2260
  this._level = currentLv;
2261
+ this._levelQuestProgressCache.delete(targetLv);
2207
2262
  } else {
2208
2263
  this.log('warn', `[QUEST] Level ${targetLv} NOT verified — still at ${currentLv}. Re-triggering quests.`);
2209
2264
  // Re-trigger quests for this level
2210
2265
  this._levelQuestDone.delete(targetLv);
2211
- this._startLevelQuests(targetLv);
2266
+ const cached = this._levelQuestProgressCache.get(targetLv) || null;
2267
+ this._startLevelQuests(targetLv, cached);
2212
2268
  this.tickTimeout = setTimeout(() => this.tick(), 2000);
2213
2269
  return;
2214
2270
  }
@@ -2231,7 +2287,6 @@ class AccountWorker {
2231
2287
  } else {
2232
2288
  this._questBetOverride = quest.bet || null;
2233
2289
  }
2234
- const questBetUsed = this._questBetOverride;
2235
2290
  const prefix = this.account.use_slash ? '/' : 'pls';
2236
2291
 
2237
2292
  if (quest.loseTarget) {
@@ -2250,7 +2305,7 @@ class AccountWorker {
2250
2305
  this._commandRunning = true;
2251
2306
  this.busy = true;
2252
2307
  await this.runCommand(quest.cmd, prefix);
2253
- const questMeta = this._lastCommandMeta || {};
2308
+ const questMeta = this._lastCommandMeta || {};
2254
2309
  this._commandRunning = false;
2255
2310
  this.busy = false;
2256
2311
  this._questBetOverride = null;
@@ -2270,13 +2325,9 @@ class AccountWorker {
2270
2325
  quest._minBet = Math.max(quest._minBet || 1, questMeta.newMinBet);
2271
2326
  }
2272
2327
 
2273
- // Fallback only for actual played rounds where parsed/observed loss was zero.
2274
- if (!nonPlay && lostThisRound === 0 && (questBetUsed || quest.bet)) {
2275
- lostThisRound = questBetUsed || quest.bet;
2276
- }
2277
-
2278
2328
  if (!nonPlay) {
2279
2329
  quest._lostSoFar = (quest._lostSoFar || 0) + lostThisRound;
2330
+ this._mergeLevelQuestProgress(quest.level, { [quest.cmd]: quest._lostSoFar });
2280
2331
  }
2281
2332
 
2282
2333
  this.log('info', `[QUEST] ${quest.cmd} — lost ⏣${quest._lostSoFar.toLocaleString()} / ⏣${quest.loseTarget.toLocaleString()}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dankgrinder",
3
- "version": "8.103.0",
3
+ "version": "8.107.0",
4
4
  "description": "Dank Memer automation engine — grind coins while you sleep",
5
5
  "bin": {
6
6
  "dankgrinder": "bin/dankgrinder.js"