Reordered directory Disp/Settings

This commit is contained in:
Daniël van Noord
2021-04-03 09:09:14 +02:00
parent 08a1e5aa6b
commit 812a2aaa69
9 changed files with 27 additions and 28 deletions

View File

@@ -0,0 +1,178 @@
/** Main function to create the sections of Cookie Monster on the Statistics page */
import { AddMissingUpgrades } from './CreateMissingUpgrades';
import * as CreateSections from './CreateStatsSections';
import * as CreateElements from './CreateDOMElements';
import * as GameData from '../../../Data/Gamedata';
import { CMOptions } from '../../../Config/VariablesAndData';
import {
CacheAverageClicks,
CacheWrinklersFattest,
CacheWrinklersNormal,
CacheWrinklersTotal,
} from '../../../Cache/VariablesAndData';
import PopAllNormalWrinklers from '../../HelperFunctions/PopWrinklers';
import { ClickTimes, CookieTimes } from '../../VariablesAndData';
import GetCPS from '../../HelperFunctions/GetCPS';
import { Beautify } from '../../BeautifyAndFormatting/BeautifyFormatting';
/**
* This function adds stats created by CookieMonster to the stats page
* It is called by CM.Disp.AddMenu
* @param {object} title On object that includes the title of the menu
*/
export default function AddMenuStats(title) {
const stats = document.createElement('div');
stats.className = 'subsection';
stats.appendChild(title);
stats.appendChild(CreateElements.StatsHeader('Lucky Cookies', 'Lucky'));
if (CMOptions.Header.Lucky) {
stats.appendChild(CreateSections.LuckySection());
}
stats.appendChild(CreateElements.StatsHeader('Chain Cookies', 'Chain'));
if (CMOptions.Header.Chain) {
stats.appendChild(CreateSections.ChainSection());
}
if (Game.Objects['Wizard tower'].minigameLoaded) {
stats.appendChild(CreateElements.StatsHeader('Spells', 'Spells'));
if (CMOptions.Header.Spells) {
stats.appendChild(CreateSections.SpellsSection());
}
}
if (Game.Objects.Farm.minigameLoaded) {
stats.appendChild(CreateElements.StatsHeader('Garden', 'Garden'));
if (CMOptions.Header.Garden) {
stats.appendChild(CreateSections.GardenSection());
}
}
stats.appendChild(CreateElements.StatsHeader('Prestige', 'Prestige'));
if (CMOptions.Header.Prestige) {
stats.appendChild(CreateSections.PrestigeSection());
}
if (Game.cpsSucked > 0) {
stats.appendChild(CreateElements.StatsHeader('Wrinklers', 'Wrink'));
if (CMOptions.Header.Wrink) {
const popAllFrag = document.createDocumentFragment();
popAllFrag.appendChild(
document.createTextNode(
`${Beautify(CacheWrinklersTotal)} / ${Beautify(
CacheWrinklersNormal,
)} `,
),
);
const popAllA = document.createElement('a');
popAllA.textContent = 'Pop All Normal';
popAllA.className = 'option';
popAllA.onclick = function () {
PopAllNormalWrinklers();
};
popAllFrag.appendChild(popAllA);
stats.appendChild(
CreateElements.StatsListing(
'basic',
'Rewards of Popping (All/Normal)',
popAllFrag,
),
);
const popFattestFrag = document.createDocumentFragment();
popFattestFrag.appendChild(
document.createTextNode(`${Beautify(CacheWrinklersFattest[0])} `),
);
const popFattestA = document.createElement('a');
popFattestA.textContent = 'Pop Single Fattest';
popFattestA.className = 'option';
popFattestA.onclick = function () {
if (CacheWrinklersFattest[1] !== null)
Game.wrinklers[CacheWrinklersFattest[1]].hp = 0;
};
popFattestFrag.appendChild(popFattestA);
stats.appendChild(
CreateElements.StatsListing(
'basic',
`Rewards of Popping Single Fattest Non-Shiny Wrinkler (id: ${
CacheWrinklersFattest[1] !== null
? CacheWrinklersFattest[1]
: 'None'
})`,
popFattestFrag,
),
);
}
}
stats.appendChild(CreateSections.SeasonSection());
stats.appendChild(CreateElements.StatsHeader('Miscellaneous', 'Misc'));
if (CMOptions.Header.Misc) {
stats.appendChild(
CreateElements.StatsListing(
'basic',
`Average Cookies Per Second (Past ${
CookieTimes[CMOptions.AvgCPSHist] < 60
? `${CookieTimes[CMOptions.AvgCPSHist]} seconds`
: CookieTimes[CMOptions.AvgCPSHist] / 60 +
(CMOptions.AvgCPSHist === 3 ? ' minute' : ' minutes')
})`,
document.createTextNode(Beautify(GetCPS(), 3)),
),
);
stats.appendChild(
CreateElements.StatsListing(
'basic',
`Average Cookie Clicks Per Second (Past ${
ClickTimes[CMOptions.AvgClicksHist]
}${CMOptions.AvgClicksHist === 0 ? ' second' : ' seconds'})`,
document.createTextNode(Beautify(CacheAverageClicks, 1)),
),
);
if (Game.Has('Fortune cookies')) {
const fortunes = [];
Object.keys(GameData.Fortunes).forEach((i) => {
if (!Game.Has(GameData.Fortunes[i])) {
fortunes.push(GameData.Fortunes[i]);
}
});
if (fortunes.length !== 0)
stats.appendChild(
CreateElements.StatsListing(
'basic',
'Fortune Upgrades Left to Buy',
CreateElements.StatsMissDisp(fortunes),
),
);
}
if (CMOptions.ShowMissedGC) {
stats.appendChild(
CreateElements.StatsListing(
'basic',
'Missed Golden Cookies',
document.createTextNode(Beautify(Game.missedGoldenClicks)),
),
);
}
if (Game.prefs.autosave) {
const timer = document.createElement('span');
timer.id = 'CMStatsAutosaveTimer';
timer.innerText = Game.sayTime(
Game.fps * 60 - (Game.OnAscend ? 0 : Game.T % (Game.fps * 60)),
4,
);
stats.appendChild(
CreateElements.StatsListing('basic', 'Time till autosave', timer),
);
}
}
l('menu').insertBefore(stats, l('menu').childNodes[2]);
if (CMOptions.MissingUpgrades) {
AddMissingUpgrades();
}
}

View File

@@ -0,0 +1,135 @@
/** Section: Functions related to the creation of basic DOM elements page */
import { ToggleHeader } from '../../../Config/ToggleSetting';
import { CMOptions } from '../../../Config/VariablesAndData';
import { SimpleTooltipElements } from '../../VariablesAndData';
/**
* This function creates a header-object for the stats page
* It is called by CM.Disp.AddMenuStats()
* @param {string} config The name of the Config-group
* @param {string} text The to-be displayed name of the header
* @returns {object} div The header object
*/
export function StatsHeader(text, config) {
const div = document.createElement('div');
div.className = 'title';
div.style.padding = '0px 16px';
div.style.opacity = '0.7';
div.style.fontSize = '17px';
div.style.fontFamily = '"Kavoon", Georgia, serif';
div.appendChild(document.createTextNode(`${text} `));
const span = document.createElement('span');
span.style.cursor = 'pointer';
span.style.display = 'inline-block';
span.style.height = '14px';
span.style.width = '14px';
span.style.borderRadius = '7px';
span.style.textAlign = 'center';
span.style.backgroundColor = '#C0C0C0';
span.style.color = 'black';
span.style.fontSize = '13px';
span.style.verticalAlign = 'middle';
span.textContent = CMOptions.Header[config] ? '-' : '+';
span.onclick = function () {
ToggleHeader(config);
Game.UpdateMenu();
};
div.appendChild(span);
return div;
}
/**
* This function creates an stats-listing-object for the stats page
* It is called by CM.Disp.AddMenuStats()
* @param {string} type The type fo the listing
* @param {string} name The name of the option
* @param {object} text The text-object of the option
* @param {string} placeholder The id of the to-be displayed tooltip if applicable
* @returns {object} div The option object
*/
export function StatsListing(type, name, text, placeholder) {
const div = document.createElement('div');
div.className = 'listing';
const listingName = document.createElement('b');
listingName.textContent = name;
div.appendChild(listingName);
if (type === 'withTooltip') {
div.className = 'listing';
div.appendChild(document.createTextNode(' '));
const tooltip = document.createElement('span');
tooltip.onmouseout = function () {
Game.tooltip.hide();
};
tooltip.onmouseover = function () {
Game.tooltip.draw(
this,
escape(SimpleTooltipElements[placeholder].innerHTML),
);
};
tooltip.style.cursor = 'default';
tooltip.style.display = 'inline-block';
tooltip.style.height = '10px';
tooltip.style.width = '10px';
tooltip.style.borderRadius = '5px';
tooltip.style.textAlign = 'center';
tooltip.style.backgroundColor = '#C0C0C0';
tooltip.style.color = 'black';
tooltip.style.fontSize = '9px';
tooltip.style.verticalAlign = 'bottom';
tooltip.textContent = '?';
div.appendChild(tooltip);
}
div.appendChild(document.createTextNode(': '));
div.appendChild(text);
return div;
}
/**
* This function creates a tooltip containing all missing holiday items contained in the list theMissDisp
* @param {list} theMissDisp A list of the missing holiday items
* @returns {object} frag The tooltip object
*/
export function StatsMissDisp(theMissDisp) {
const frag = document.createDocumentFragment();
frag.appendChild(document.createTextNode(`${theMissDisp.length} `));
const span = document.createElement('span');
span.onmouseout = function () {
Game.tooltip.hide();
};
const placeholder = document.createElement('div');
const missing = document.createElement('div');
missing.style.minWidth = '140px';
missing.style.marginBottom = '4px';
const title = document.createElement('div');
title.className = 'name';
title.style.marginBottom = '4px';
title.style.textAlign = 'center';
title.textContent = 'Missing';
missing.appendChild(title);
Object.keys(theMissDisp).forEach((i) => {
const div = document.createElement('div');
div.style.textAlign = 'center';
div.appendChild(document.createTextNode(theMissDisp[i]));
missing.appendChild(div);
});
placeholder.appendChild(missing);
span.onmouseover = function () {
Game.tooltip.draw(this, escape(placeholder.innerHTML));
};
span.style.cursor = 'default';
span.style.display = 'inline-block';
span.style.height = '10px';
span.style.width = '10px';
span.style.borderRadius = '5px';
span.style.textAlign = 'center';
span.style.backgroundColor = '#C0C0C0';
span.style.color = 'black';
span.style.fontSize = '9px';
span.style.verticalAlign = 'bottom';
span.textContent = '?';
frag.appendChild(span);
return frag;
}

View File

@@ -0,0 +1,111 @@
/** Functions related to displaying the missing upgrades in the Statistics page */
import {
CacheMissingUpgrades,
CacheMissingUpgradesCookies,
CacheMissingUpgradesPrestige,
} from '../../../Cache/VariablesAndData';
/**
* This function creates the missing upgrades sections for prestige, normal and cookie upgrades
*/
export function AddMissingUpgrades() {
l('menu').childNodes.forEach((menuSection) => {
if (menuSection.children[0]) {
if (
menuSection.children[0].innerHTML === 'Prestige' &&
CacheMissingUpgradesPrestige
) {
const prestigeUpgradesMissing =
CacheMissingUpgradesPrestige.match(new RegExp('div', 'g') || [])
.length / 2;
const title = document.createElement('div');
title.id = 'CMMissingUpgradesPrestigeTitle';
title.className = 'listing';
const titlefrag = document.createElement('div');
titlefrag.innerHTML = `<b>Missing Prestige upgrades:</b> ${prestigeUpgradesMissing}/${
Game.PrestigeUpgrades.length
} (${Math.floor(
(prestigeUpgradesMissing / Game.PrestigeUpgrades.length) * 100,
)}%)`;
title.appendChild(titlefrag);
menuSection.appendChild(title);
const upgrades = document.createElement('div');
upgrades.className = 'listing crateBox';
upgrades.innerHTML = CacheMissingUpgradesPrestige;
menuSection.appendChild(upgrades);
} else if (menuSection.children[0].innerHTML === 'Upgrades') {
if (CacheMissingUpgrades) {
const normalUpgradesMissing =
CacheMissingUpgrades.match(new RegExp('div', 'g') || []).length / 2;
const title = document.createElement('div');
title.id = 'CMMissingUpgradesTitle';
title.className = 'listing';
const titlefrag = document.createElement('div');
titlefrag.innerHTML = `<b>Missing normal upgrades:</b> ${normalUpgradesMissing}/${
Game.UpgradesByPool[''].length + Game.UpgradesByPool.tech.length
} (${Math.floor(
(normalUpgradesMissing /
(Game.UpgradesByPool[''].length +
Game.UpgradesByPool.tech.length)) *
100,
)}%)`;
title.appendChild(titlefrag);
menuSection.insertBefore(title, menuSection.childNodes[3]);
const upgrades = document.createElement('div');
upgrades.className = 'listing crateBox';
upgrades.innerHTML = CacheMissingUpgrades;
menuSection.insertBefore(
upgrades,
document.getElementById('CMMissingUpgradesTitle').nextSibling,
);
}
if (CacheMissingUpgradesCookies) {
const cookieUpgradesMissing =
CacheMissingUpgradesCookies.match(new RegExp('div', 'g') || [])
.length / 2;
const title = document.createElement('div');
title.id = 'CMMissingUpgradesCookiesTitle';
title.className = 'listing';
const titlefrag = document.createElement('div');
titlefrag.innerHTML = `<b>Missing Cookie upgrades:</b> ${cookieUpgradesMissing}/${
Game.UpgradesByPool.cookie.length
} (${Math.floor(
(cookieUpgradesMissing / Game.UpgradesByPool.cookie.length) * 100,
)}%)`;
title.appendChild(titlefrag);
menuSection.appendChild(title);
const upgrades = document.createElement('div');
upgrades.className = 'listing crateBox';
upgrades.innerHTML = CacheMissingUpgradesCookies;
menuSection.appendChild(upgrades);
}
}
}
});
}
/**
* This function returns the "crates" (icons) for missing upgrades in the stats sections
* It returns a html string that gets appended to the respective CM.Cache.MissingUpgrades-variable by CM.Cache.CacheMissingUpgrades()
* @param {object} me The upgrade object
* @returns {string} ? The HTML string that creates the icon.
*/
export function crateMissing(me) {
let classes = 'crate upgrade missing';
if (me.pool === 'prestige') classes += ' heavenly';
let noFrame = 0;
if (!Game.prefs.crates) noFrame = 1;
if (noFrame) classes += ' noFrame';
let { icon } = me;
if (me.iconFunction) icon = me.iconFunction();
const tooltip = `function() {return Game.crateTooltip(Game.UpgradesById[${me.id}], 'stats');}`;
return `<div class="${classes}"
${Game.getDynamicTooltip(tooltip, 'top', true)}
style = "${`${
icon[2] ? `background-image: url(${icon[2]});` : ''
}background-position:${-icon[0] * 48}px ${-icon[1] * 48}px`};">
</div>`;
}

View File

@@ -0,0 +1,995 @@
/** Functions to create the individual sections of the Statistics page */
import * as GameData from '../../../Data/Gamedata';
import { MaxChainCookieReward } from '../../../Cache/Stats/ChainCookies';
import {
CacheAvgCPSWithChoEgg,
CacheCentEgg,
CacheChainFrenzyMaxReward,
CacheChainFrenzyRequired,
CacheChainFrenzyRequiredNext,
CacheChainFrenzyWrathRequired,
CacheChainFrenzyWrathRequiredNext,
CacheChainMaxReward,
CacheChainRequired,
CacheChainRequiredNext,
CacheChainWrathMaxReward,
CacheChainWrathRequired,
CacheChainWrathRequiredNext,
CacheConjure,
CacheConjureReward,
CacheDragonsFortuneMultAdjustment,
CacheEdifice,
CacheEdificeBuilding,
CacheGoldenCookiesMult,
CacheHCPerSecond,
CacheLastChoEgg,
CacheLucky,
CacheLuckyFrenzy,
CacheLuckyReward,
CacheLuckyRewardFrenzy,
CacheLuckyWrathReward,
CacheLuckyWrathRewardFrenzy,
CacheNoGoldSwitchCookiesPS,
CacheRealCookiesEarned,
CacheSeaSpec,
CacheWrathCookiesMult,
CacheWrinklersTotal,
} from '../../../Cache/VariablesAndData';
import { CMOptions } from '../../../Config/VariablesAndData';
import ResetBonus from '../../../Sim/SimulationEvents/ResetAscension';
import {
Beautify,
FormatTime,
} from '../../BeautifyAndFormatting/BeautifyFormatting';
import GetCPS from '../../HelperFunctions/GetCPS';
import GetWrinkConfigBank from '../../HelperFunctions/GetWrinkConfigBank';
import { ColourGreen, ColourRed, ColourTextPre } from '../../VariablesAndData';
import { StatsListing, StatsHeader, StatsMissDisp } from './CreateDOMElements';
/**
* This function creates the "Lucky" section of the stats page
* @returns {object} section The object contating the Lucky section
*/
export function LuckySection() {
// This sets which tooltip to display for certain stats
const goldCookTooltip = Game.auraMult("Dragon's Fortune")
? 'GoldCookDragonsFortuneTooltipPlaceholder'
: 'GoldCookTooltipPlaceholder';
const section = document.createElement('div');
section.className = 'CMStatsLuckySection';
const luckyColour =
Game.cookies + GetWrinkConfigBank() < CacheLucky ? ColourRed : ColourGreen;
const luckyTime =
Game.cookies + GetWrinkConfigBank() < CacheLucky
? FormatTime(
(CacheLucky - (Game.cookies + GetWrinkConfigBank())) / GetCPS(),
)
: '';
const luckyReqFrag = document.createDocumentFragment();
const luckyReqSpan = document.createElement('span');
luckyReqSpan.style.fontWeight = 'bold';
luckyReqSpan.className = ColourTextPre + luckyColour;
luckyReqSpan.textContent = Beautify(CacheLucky);
luckyReqFrag.appendChild(luckyReqSpan);
if (luckyTime !== '') {
const luckyReqSmall = document.createElement('small');
luckyReqSmall.textContent = ` (${luckyTime})`;
luckyReqFrag.appendChild(luckyReqSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Lucky!" Cookies Required',
luckyReqFrag,
goldCookTooltip,
),
);
const luckyColourFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheLuckyFrenzy
? ColourRed
: ColourGreen;
const luckyTimeFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheLuckyFrenzy
? FormatTime(
(CacheLuckyFrenzy - (Game.cookies + GetWrinkConfigBank())) / GetCPS(),
)
: '';
const luckyReqFrenFrag = document.createDocumentFragment();
const luckyReqFrenSpan = document.createElement('span');
luckyReqFrenSpan.style.fontWeight = 'bold';
luckyReqFrenSpan.className = ColourTextPre + luckyColourFrenzy;
luckyReqFrenSpan.textContent = Beautify(CacheLuckyFrenzy);
luckyReqFrenFrag.appendChild(luckyReqFrenSpan);
if (luckyTimeFrenzy !== '') {
const luckyReqFrenSmall = document.createElement('small');
luckyReqFrenSmall.textContent = ` (${luckyTimeFrenzy})`;
luckyReqFrenFrag.appendChild(luckyReqFrenSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Lucky!" Cookies Required (Frenzy)',
luckyReqFrenFrag,
goldCookTooltip,
),
);
const luckySplit = CacheLuckyReward !== CacheLuckyWrathReward;
const luckyRewardMaxSpan = document.createElement('span');
luckyRewardMaxSpan.style.fontWeight = 'bold';
luckyRewardMaxSpan.className = ColourTextPre + CacheLuckyReward;
luckyRewardMaxSpan.textContent =
Beautify(CacheLuckyReward) +
(luckySplit ? ` / ${Beautify(CacheLuckyWrathReward)}` : '');
section.appendChild(
StatsListing(
'withTooltip',
`"Lucky!" Reward (MAX)${luckySplit ? ' (Golden / Wrath)' : ''}`,
luckyRewardMaxSpan,
goldCookTooltip,
),
);
const luckyRewardFrenzyMaxSpan = document.createElement('span');
luckyRewardFrenzyMaxSpan.style.fontWeight = 'bold';
luckyRewardFrenzyMaxSpan.className = ColourTextPre + luckyRewardFrenzyMaxSpan;
luckyRewardFrenzyMaxSpan.textContent =
Beautify(CacheLuckyRewardFrenzy) +
(luckySplit ? ` / ${Beautify(CacheLuckyWrathRewardFrenzy)}` : '');
section.appendChild(
StatsListing(
'withTooltip',
`"Lucky!" Reward (MAX) (Frenzy)${luckySplit ? ' (Golden / Wrath)' : ''}`,
luckyRewardFrenzyMaxSpan,
goldCookTooltip,
),
);
const luckyCurBase =
Math.min(
(Game.cookies + GetWrinkConfigBank()) * 0.15,
CacheNoGoldSwitchCookiesPS * CacheDragonsFortuneMultAdjustment * 60 * 15,
) + 13;
const luckyCurSpan = document.createElement('span');
luckyCurSpan.style.fontWeight = 'bold';
luckyCurSpan.className = ColourTextPre + luckyCurSpan;
luckyCurSpan.textContent =
Beautify(CacheGoldenCookiesMult * luckyCurBase) +
(luckySplit ? ` / ${Beautify(CacheWrathCookiesMult * luckyCurBase)}` : '');
section.appendChild(
StatsListing(
'withTooltip',
`"Lucky!" Reward (CUR)${luckySplit ? ' (Golden / Wrath)' : ''}`,
luckyCurSpan,
goldCookTooltip,
),
);
return section;
}
/**
* This function creates the "Chain" section of the stats page
* @returns {object} section The object contating the Chain section
*/
export function ChainSection() {
// This sets which tooltip to display for certain stats
const goldCookTooltip = Game.auraMult("Dragon's Fortune")
? 'GoldCookDragonsFortuneTooltipPlaceholder'
: 'GoldCookTooltipPlaceholder';
const section = document.createElement('div');
section.className = 'CMStatsChainSection';
const chainColour =
Game.cookies + GetWrinkConfigBank() < CacheChainRequired
? ColourRed
: ColourGreen;
const chainTime =
Game.cookies + GetWrinkConfigBank() < CacheChainRequired
? FormatTime(
(CacheChainRequired - (Game.cookies + GetWrinkConfigBank())) /
GetCPS(),
)
: '';
const chainReqFrag = document.createDocumentFragment();
const chainReqSpan = document.createElement('span');
chainReqSpan.style.fontWeight = 'bold';
chainReqSpan.className = ColourTextPre + chainColour;
chainReqSpan.textContent = Beautify(CacheChainRequired);
chainReqFrag.appendChild(chainReqSpan);
if (chainTime !== '') {
const chainReqSmall = document.createElement('small');
chainReqSmall.textContent = ` (${chainTime})`;
chainReqFrag.appendChild(chainReqSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Cookies Required',
chainReqFrag,
goldCookTooltip,
),
);
const chainWrathColour =
Game.cookies + GetWrinkConfigBank() < CacheChainWrathRequired
? ColourRed
: ColourGreen;
const chainWrathTime =
Game.cookies + GetWrinkConfigBank() < CacheChainWrathRequired
? FormatTime(
(CacheChainWrathRequired - (Game.cookies + GetWrinkConfigBank())) /
GetCPS(),
)
: '';
const chainWrathReqFrag = document.createDocumentFragment();
const chainWrathReqSpan = document.createElement('span');
chainWrathReqSpan.style.fontWeight = 'bold';
chainWrathReqSpan.className = ColourTextPre + chainWrathColour;
chainWrathReqSpan.textContent = Beautify(CacheChainWrathRequired);
chainWrathReqFrag.appendChild(chainWrathReqSpan);
if (chainWrathTime !== '') {
const chainWrathReqSmall = document.createElement('small');
chainWrathReqSmall.textContent = ` (${chainWrathTime})`;
chainWrathReqFrag.appendChild(chainWrathReqSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Cookies Required (Wrath)',
chainWrathReqFrag,
goldCookTooltip,
),
);
const chainColourFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyRequired
? ColourRed
: ColourGreen;
const chainTimeFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyRequired
? FormatTime(
(CacheChainFrenzyRequired - (Game.cookies + GetWrinkConfigBank())) /
GetCPS(),
)
: '';
const chainReqFrenFrag = document.createDocumentFragment();
const chainReqFrenSpan = document.createElement('span');
chainReqFrenSpan.style.fontWeight = 'bold';
chainReqFrenSpan.className = ColourTextPre + chainColourFrenzy;
chainReqFrenSpan.textContent = Beautify(CacheChainFrenzyRequired);
chainReqFrenFrag.appendChild(chainReqFrenSpan);
if (chainTimeFrenzy !== '') {
const chainReqFrenSmall = document.createElement('small');
chainReqFrenSmall.textContent = ` (${chainTimeFrenzy})`;
chainReqFrenFrag.appendChild(chainReqFrenSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Cookies Required (Frenzy)',
chainReqFrenFrag,
goldCookTooltip,
),
);
const chainWrathColourFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyWrathRequired
? ColourRed
: ColourGreen;
const chainWrathTimeFrenzy =
Game.cookies + GetWrinkConfigBank() < CacheChainFrenzyWrathRequired
? FormatTime(
(CacheChainFrenzyWrathRequired -
(Game.cookies + GetWrinkConfigBank())) /
GetCPS(),
)
: '';
const chainWrathReqFrenFrag = document.createDocumentFragment();
const chainWrathReqFrenSpan = document.createElement('span');
chainWrathReqFrenSpan.style.fontWeight = 'bold';
chainWrathReqFrenSpan.className = ColourTextPre + chainWrathColourFrenzy;
chainWrathReqFrenSpan.textContent = Beautify(CacheChainFrenzyWrathRequired);
chainWrathReqFrenFrag.appendChild(chainWrathReqFrenSpan);
if (chainWrathTimeFrenzy !== '') {
const chainWrathReqFrenSmall = document.createElement('small');
chainWrathReqFrenSmall.textContent = ` (${chainWrathTimeFrenzy})`;
chainWrathReqFrenFrag.appendChild(chainWrathReqFrenSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Cookies Required (Frenzy) (Wrath)',
chainWrathReqFrenFrag,
goldCookTooltip,
),
);
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Reward (MAX) (Golden / Wrath)',
document.createTextNode(
`${Beautify(CacheChainMaxReward[0])} / ${Beautify(
CacheChainWrathMaxReward[0],
)}`,
),
goldCookTooltip,
),
);
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Reward (MAX) (Frenzy) (Golden / Wrath)',
document.createTextNode(
`${Beautify(CacheChainFrenzyMaxReward[0])} / ${Beautify(
CacheChainFrenzyMaxReward[0],
)}`,
),
goldCookTooltip,
),
);
const chainCurMax = Math.min(
Game.cookiesPs * 60 * 60 * 6 * CacheDragonsFortuneMultAdjustment,
Game.cookies * 0.5,
);
const chainCur = MaxChainCookieReward(
7,
chainCurMax,
CacheGoldenCookiesMult,
)[0];
const chainCurWrath = MaxChainCookieReward(
6,
chainCurMax,
CacheWrathCookiesMult,
)[0];
section.appendChild(
StatsListing(
'withTooltip',
'"Chain" Reward (CUR) (Golden / Wrath)',
document.createTextNode(
`${Beautify(chainCur)} / ${Beautify(chainCurWrath)}`,
),
goldCookTooltip,
),
);
section.appendChild(
StatsListing(
'withTooltip',
'CPS Needed For Next Level (G / W)',
document.createTextNode(
`${Beautify(CacheChainRequiredNext)} / ${Beautify(
CacheChainWrathRequiredNext,
)}`,
),
'ChainNextLevelPlaceholder',
),
);
section.appendChild(
StatsListing(
'withTooltip',
'CPS Needed For Next Level (Frenzy) (G / W)',
document.createTextNode(
`${Beautify(CacheChainFrenzyRequiredNext)} / ${Beautify(
CacheChainFrenzyWrathRequiredNext,
)}`,
),
'ChainNextLevelPlaceholder',
),
);
return section;
}
/**
* This function creates the "Spells" section of the stats page
* @returns {object} section The object contating the Spells section
*/
export function SpellsSection() {
const section = document.createElement('div');
section.className = 'CMStatsSpellsSection';
const conjureColour =
Game.cookies + GetWrinkConfigBank() < CacheConjure
? ColourRed
: ColourGreen;
const conjureTime =
Game.cookies + GetWrinkConfigBank() < CacheConjure
? FormatTime(
(CacheConjure - (Game.cookies + GetWrinkConfigBank())) / GetCPS(),
)
: '';
const conjureReqFrag = document.createDocumentFragment();
const conjureReqSpan = document.createElement('span');
conjureReqSpan.style.fontWeight = 'bold';
conjureReqSpan.className = ColourTextPre + conjureColour;
conjureReqSpan.textContent = Beautify(CacheConjure);
conjureReqFrag.appendChild(conjureReqSpan);
if (conjureTime !== '') {
const conjureReqSmall = document.createElement('small');
conjureReqSmall.textContent = ` (${conjureTime})`;
conjureReqFrag.appendChild(conjureReqSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Conjure Baked Goods" Cookies Required',
conjureReqFrag,
'GoldCookTooltipPlaceholder',
),
);
section.appendChild(
StatsListing(
'withTooltip',
'"Conjure Baked Goods" Reward (MAX)',
document.createTextNode(Beautify(CacheConjureReward)),
'GoldCookTooltipPlaceholder',
),
);
const conjureFrenzyColour =
Game.cookies + GetWrinkConfigBank() < CacheConjure * 7
? ColourRed
: ColourGreen;
const conjureFrenzyCur = Math.min(
(Game.cookies + GetWrinkConfigBank()) * 0.15,
CacheNoGoldSwitchCookiesPS * 60 * 30,
);
const conjureFrenzyTime =
Game.cookies + GetWrinkConfigBank() < CacheConjure * 7
? FormatTime(
(CacheConjure * 7 - (Game.cookies + GetWrinkConfigBank())) / GetCPS(),
)
: '';
const conjureFrenzyReqFrag = document.createDocumentFragment();
const conjureFrenzyReqSpan = document.createElement('span');
conjureFrenzyReqSpan.style.fontWeight = 'bold';
conjureFrenzyReqSpan.className = ColourTextPre + conjureFrenzyColour;
conjureFrenzyReqSpan.textContent = Beautify(CacheConjure * 7);
conjureFrenzyReqFrag.appendChild(conjureFrenzyReqSpan);
if (conjureFrenzyTime !== '') {
const conjureFrenzyReqSmall = document.createElement('small');
conjureFrenzyReqSmall.textContent = ` (${conjureFrenzyTime})`;
conjureFrenzyReqFrag.appendChild(conjureFrenzyReqSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'"Conjure Baked Goods" Cookies Required (Frenzy)',
conjureFrenzyReqFrag,
'GoldCookTooltipPlaceholder',
),
);
section.appendChild(
StatsListing(
'withTooltip',
'"Conjure Baked Goods" Reward (MAX) (Frenzy)',
document.createTextNode(Beautify(CacheConjureReward * 7)),
'GoldCookTooltipPlaceholder',
),
);
section.appendChild(
StatsListing(
'withTooltip',
'"Conjure Baked Goods" Reward (CUR)',
document.createTextNode(Beautify(conjureFrenzyCur)),
'GoldCookTooltipPlaceholder',
),
);
if (CacheEdifice) {
section.appendChild(
StatsListing(
'withTooltip',
'"Spontaneous Edifice" Cookies Required (most expensive building)',
document.createTextNode(
`${Beautify(CacheEdifice)} (${CacheEdificeBuilding})`,
),
'GoldCookTooltipPlaceholder',
),
);
}
return section;
}
/**
* This function creates the "Garden" section of the stats page
* @returns {object} section The object contating the Spells section
*/
export function GardenSection() {
const section = document.createElement('div');
section.className = 'CMStatsGardenSection';
const bakeberryColour =
Game.cookies < Game.cookiesPs * 60 * 10 * 100 ? ColourRed : ColourGreen;
const bakeberryFrag = document.createElement('span');
bakeberryFrag.style.fontWeight = 'bold';
bakeberryFrag.className = ColourTextPre + bakeberryColour;
bakeberryFrag.textContent = Beautify(Game.cookiesPs * 60 * 10 * 100);
section.appendChild(
StatsListing(
'basic',
'Cookies required for max reward of Bakeberry: ',
bakeberryFrag,
),
);
const chocorootColour =
Game.cookies < Game.cookiesPs * 60 * 100 ? ColourRed : ColourGreen;
const chocorootFrag = document.createElement('span');
chocorootFrag.style.fontWeight = 'bold';
chocorootFrag.className = ColourTextPre + chocorootColour;
chocorootFrag.textContent = Beautify(Game.cookiesPs * 60 * 100);
section.appendChild(
StatsListing(
'basic',
'Cookies required for max reward of Chocoroot: ',
chocorootFrag,
),
);
const queenbeetColour =
Game.cookies < Game.cookiesPs * 60 * 60 * 25 ? ColourRed : ColourGreen;
const queenbeetFrag = document.createElement('span');
queenbeetFrag.style.fontWeight = 'bold';
queenbeetFrag.className = ColourTextPre + queenbeetColour;
queenbeetFrag.textContent = Beautify(Game.cookiesPs * 60 * 60 * 25);
section.appendChild(
StatsListing(
'basic',
'Cookies required for max reward of Queenbeet: ',
queenbeetFrag,
),
);
const duketaterColour =
Game.cookies < Game.cookiesPs * 60 * 15 * 100 ? ColourRed : ColourGreen;
const duketaterFrag = document.createElement('span');
duketaterFrag.style.fontWeight = 'bold';
duketaterFrag.className = ColourTextPre + duketaterColour;
duketaterFrag.textContent = Beautify(Game.cookiesPs * 60 * 15 * 100);
section.appendChild(
StatsListing(
'basic',
'Cookies required for max reward of Duketater: ',
duketaterFrag,
),
);
const missingPlantDrops = [];
Object.keys(GameData.PlantDrops).forEach((i) => {
if (!Game.HasUnlocked(GameData.PlantDrops[i])) {
missingPlantDrops.push(GameData.PlantDrops[i]);
}
});
if (missingPlantDrops.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Rare plant drops left to unlock',
StatsMissDisp(missingPlantDrops),
),
);
}
return section;
}
/**
* This function creates the "Prestige" section of the stats page
* @returns {object} section The object contating the Prestige section
*/
export function PrestigeSection() {
const section = document.createElement('div');
section.className = 'CMStatsPrestigeSection';
const possiblePresMax = Math.floor(
Game.HowMuchPrestige(
CacheRealCookiesEarned +
Game.cookiesReset +
CacheWrinklersTotal +
(Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg')
? CacheLastChoEgg
: 0),
),
);
section.appendChild(
StatsListing(
'withTooltip',
'Prestige Level (CUR / MAX)',
document.createTextNode(
`${Beautify(Game.prestige)} / ${Beautify(possiblePresMax)}`,
),
'PrestMaxTooltipPlaceholder',
),
);
const neededCook = Math.max(
0,
Game.HowManyCookiesReset(possiblePresMax + 1) -
(CacheRealCookiesEarned +
Game.cookiesReset +
CacheWrinklersTotal +
((
Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg')
? CacheLastChoEgg
: 0
)
? CacheLastChoEgg
: 0)),
);
const cookiesNextFrag = document.createDocumentFragment();
cookiesNextFrag.appendChild(document.createTextNode(Beautify(neededCook)));
const cookiesNextSmall = document.createElement('small');
cookiesNextSmall.textContent = ` (${FormatTime(
neededCook / CacheAvgCPSWithChoEgg,
1,
)})`;
cookiesNextFrag.appendChild(cookiesNextSmall);
section.appendChild(
StatsListing(
'withTooltip',
'Cookies To Next Level',
cookiesNextFrag,
'NextPrestTooltipPlaceholder',
),
);
section.appendChild(
StatsListing(
'withTooltip',
'Heavenly Chips (CUR / MAX)',
document.createTextNode(
`${Beautify(Game.heavenlyChips)} / ${Beautify(
possiblePresMax - Game.prestige + Game.heavenlyChips,
)}`,
),
'HeavenChipMaxTooltipPlaceholder',
),
);
section.appendChild(
StatsListing(
'basic',
'Heavenly Chips Per Second (last 5 seconds)',
document.createTextNode(Beautify(CacheHCPerSecond, 2)),
),
);
const HCTarget = Number(CMOptions.HeavenlyChipsTarget);
if (!Number.isNaN(HCTarget)) {
const CookiesTillTarget =
HCTarget -
Math.floor(Game.HowMuchPrestige(Game.cookiesReset + Game.cookiesEarned));
if (CookiesTillTarget > 0) {
section.appendChild(
StatsListing(
'basic',
'Heavenly Chips To Target Set In Settings (CUR)',
document.createTextNode(Beautify(CookiesTillTarget)),
),
);
section.appendChild(
StatsListing(
'basic',
'Time To Target (CUR, Current 5 Second Average)',
document.createTextNode(
FormatTime(CookiesTillTarget / CacheHCPerSecond),
),
),
);
}
}
const resetBonus = ResetBonus(possiblePresMax);
const resetFrag = document.createDocumentFragment();
resetFrag.appendChild(document.createTextNode(Beautify(resetBonus)));
const increase = Math.round((resetBonus / Game.cookiesPs) * 10000);
if (Number.isFinite(increase) && increase !== 0) {
const resetSmall = document.createElement('small');
resetSmall.textContent = ` (${increase / 100}% of income)`;
resetFrag.appendChild(resetSmall);
}
section.appendChild(
StatsListing(
'withTooltip',
'Reset Bonus Income',
resetFrag,
'ResetTooltipPlaceholder',
),
);
const currentPrestige = Math.floor(Game.HowMuchPrestige(Game.cookiesReset));
const willHave = Math.floor(
Game.HowMuchPrestige(Game.cookiesReset + Game.cookiesEarned),
);
const willGet = willHave - currentPrestige;
if (!Game.Has('Lucky digit')) {
let delta7 = 7 - (willHave % 10);
if (delta7 < 0) delta7 += 10;
const next7Reset = willGet + delta7;
const next7Total = willHave + delta7;
const frag7 = document.createDocumentFragment();
frag7.appendChild(
document.createTextNode(
`${next7Total.toLocaleString()} / ${next7Reset.toLocaleString()} (+${delta7})`,
),
);
section.appendChild(
StatsListing('basic', 'Next "Lucky Digit" (total / reset)', frag7),
);
}
if (!Game.Has('Lucky number')) {
let delta777 = 777 - (willHave % 1000);
if (delta777 < 0) delta777 += 1000;
const next777Reset = willGet + delta777;
const next777Total = willHave + delta777;
const frag777 = document.createDocumentFragment();
frag777.appendChild(
document.createTextNode(
`${next777Total.toLocaleString()} / ${next777Reset.toLocaleString()} (+${delta777})`,
),
);
section.appendChild(
StatsListing('basic', 'Next "Lucky Number" (total / reset)', frag777),
);
}
if (!Game.Has('Lucky payout')) {
let delta777777 = 777777 - (willHave % 1000000);
if (delta777777 < 0) delta777777 += 1000000;
const next777777Reset = willGet + delta777777;
const next777777Total = willHave + delta777777;
const frag777777 = document.createDocumentFragment();
frag777777.appendChild(
document.createTextNode(
`${next777777Total.toLocaleString()} / ${next777777Reset.toLocaleString()} (+${delta777777})`,
),
);
section.appendChild(
StatsListing('basic', 'Next "Lucky Payout" (total / reset)', frag777777),
);
}
return section;
}
/**
* This function creates the "Season Specials" section of the stats page
* @returns {object} section The object contating the Season Specials section
*/
export function SeasonSection() {
const section = document.createElement('div');
section.className = 'CMStatsSeasonSection';
let specDisp = false;
const missingHalloweenCookies = [];
Object.keys(GameData.HalloCookies).forEach((i) => {
if (!Game.Has(GameData.HalloCookies[i])) {
missingHalloweenCookies.push(GameData.HalloCookies[i]);
specDisp = true;
}
});
const missingChristmasCookies = [];
Object.keys(GameData.ChristCookies).forEach((i) => {
if (!Game.Has(GameData.ChristCookies[i])) {
missingChristmasCookies.push(GameData.ChristCookies[i]);
specDisp = true;
}
});
const missingValentineCookies = [];
Object.keys(GameData.ValCookies).forEach((i) => {
if (!Game.Has(GameData.ValCookies[i])) {
missingValentineCookies.push(GameData.ValCookies[i]);
specDisp = true;
}
});
const missingNormalEggs = [];
Object.keys(Game.eggDrops).forEach((i) => {
if (!Game.HasUnlocked(Game.eggDrops[i])) {
missingNormalEggs.push(Game.eggDrops[i]);
specDisp = true;
}
});
const missingRareEggs = [];
Object.keys(Game.rareEggDrops).forEach((i) => {
if (!Game.HasUnlocked(Game.rareEggDrops[i])) {
missingRareEggs.push(Game.rareEggDrops[i]);
specDisp = true;
}
});
const choEgg =
Game.HasUnlocked('Chocolate egg') && !Game.Has('Chocolate egg');
const centEgg = Game.Has('Century egg');
if (Game.season === 'christmas' || specDisp || choEgg || centEgg) {
section.appendChild(StatsHeader('Season Specials', 'Sea'));
if (CMOptions.Header.Sea) {
if (missingHalloweenCookies.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Halloween cookies left to buy',
StatsMissDisp(missingHalloweenCookies),
),
);
let failRateHalloween = 0.95;
if (Game.HasAchiev('Spooky cookies')) failRateHalloween = 0.8;
if (Game.Has('Starterror')) failRateHalloween *= 0.9;
failRateHalloween *= 1 / Game.dropRateMult();
if (Game.hasGod) {
const godLvl = Game.hasGod('seasons');
if (godLvl === 1) failRateHalloween *= 0.9;
else if (godLvl === 2) failRateHalloween *= 0.95;
else if (godLvl === 3) failRateHalloween *= 0.97;
}
const obtainedCookiesChance = missingHalloweenCookies.length / 7;
section.appendChild(
StatsListing(
'basic',
'Chance of receiving a cookie from wrinkler/shiny wrinkler',
document.createTextNode(
`${Beautify(
(1 - failRateHalloween) * obtainedCookiesChance * 100,
)}% / ${Beautify(
(1 - failRateHalloween * 0.9) * obtainedCookiesChance * 100,
)}%`,
),
),
);
}
if (missingChristmasCookies.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Christmas cookies left to buy',
StatsMissDisp(missingChristmasCookies),
),
);
let failRateChristmas = 0.8;
if (Game.HasAchiev('Let it snow')) failRateChristmas = 0.6;
failRateChristmas *= 1 / Game.dropRateMult();
if (Game.Has('Starsnow')) failRateChristmas *= 0.95;
if (Game.hasGod) {
const godLvl = Game.hasGod('seasons');
if (godLvl === 1) failRateChristmas *= 0.9;
else if (godLvl === 2) failRateChristmas *= 0.95;
else if (godLvl === 3) failRateChristmas *= 0.97;
}
const obtainedCookiesChance = missingChristmasCookies.length / 7;
section.appendChild(
StatsListing(
'basic',
'Chance of receiving a cookie from reindeer',
document.createTextNode(
`${Beautify(
(1 - failRateChristmas) * obtainedCookiesChance * 100,
)}%`,
),
),
);
}
if (missingValentineCookies.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Valentine cookies left to buy',
StatsMissDisp(missingValentineCookies),
),
);
}
const dropRateEgg = function (StartingFailRate) {
let failRateEgg = StartingFailRate * (1 / Game.dropRateMult());
if (Game.HasAchiev('Hide & seek champion')) failRateEgg *= 0.7;
if (Game.Has('Omelette')) failRateEgg *= 0.9;
if (Game.Has('Starspawn')) failRateEgg *= 0.9;
if (Game.hasGod) {
const godLvl = Game.hasGod('seasons');
if (godLvl === 1) failRateEgg *= 0.9;
else if (godLvl === 2) failRateEgg *= 0.95;
else if (godLvl === 3) failRateEgg *= 0.97;
}
// Calculations courtesy of @svschouw, at https://github.com/Aktanusa/CookieMonster/issues/25
const succesRateEgg = 1 - failRateEgg;
const obtainedEggs = Game.eggDrops.length - missingNormalEggs.length;
const obtainedRareEggs =
Game.rareEggDrops.length - missingRareEggs.length;
const pNormal1 =
succesRateEgg * 0.9 * (1 - obtainedEggs / Game.eggDrops.length);
const pRare1 =
succesRateEgg *
0.1 *
(1 - obtainedRareEggs / Game.rareEggDrops.length);
const pRedropNormal =
succesRateEgg * 0.9 * (obtainedEggs / Game.eggDrops.length);
const pRedropRare =
succesRateEgg * 0.1 * (obtainedRareEggs / Game.rareEggDrops.length);
const pRedrop = pRedropNormal + pRedropRare;
const pNormal2 =
pRedrop * 0.9 * (1 - obtainedEggs / Game.eggDrops.length);
const pRare2 =
pRedrop * 0.1 * (1 - obtainedRareEggs / Game.rareEggDrops.length);
return [pNormal1 + pNormal2, pRare1 + pRare2];
};
if (missingNormalEggs.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Normal easter eggs left to unlock',
StatsMissDisp(missingNormalEggs),
),
);
section.appendChild(
StatsListing(
'basic',
'Chance of receiving an egg from wrinkler/golden cookie',
document.createTextNode(
`${Beautify(dropRateEgg(0.98)[0] * 100)}% / ${Beautify(
dropRateEgg(0.9)[0] * 100,
)}%`,
),
),
);
}
if (missingRareEggs.length !== 0) {
section.appendChild(
StatsListing(
'basic',
'Rare easter eggs left to unlock',
StatsMissDisp(missingRareEggs),
),
);
section.appendChild(
StatsListing(
'basic',
'Chance of receiving a rare egg from wrinkler/golden cookie',
document.createTextNode(
`${Beautify(dropRateEgg(0.98)[1] * 100)}% / ${Beautify(
dropRateEgg(0.9)[1] * 100,
)}%`,
),
),
);
}
if (Game.season === 'christmas')
section.appendChild(
StatsListing(
'basic',
'Reindeer reward',
document.createTextNode(Beautify(CacheSeaSpec)),
),
);
if (choEgg) {
section.appendChild(
StatsListing(
'withTooltip',
'Chocolate egg cookies',
document.createTextNode(Beautify(CacheLastChoEgg)),
'ChoEggTooltipPlaceholder',
),
);
}
if (centEgg) {
section.appendChild(
StatsListing(
'basic',
'Century egg multiplier',
document.createTextNode(
`${Math.round((CacheCentEgg - 1) * 10000) / 100}%`,
),
),
);
}
}
}
return section;
}