Refactor notation system

This commit is contained in:
Andrei Andreev 2019-01-21 03:58:27 +03:00
parent ffb7d56c4d
commit f5772f7bda
15 changed files with 459 additions and 231 deletions

View File

@ -636,7 +636,7 @@
<script type="text/javascript" src="javascripts/core/app/player-progress.js"></script>
<script type="text/javascript" src="javascripts/core/app/modal.js"></script>
<script type="text/javascript" src="javascripts/core/app/themes.js"></script>
<script type="text/javascript" src="javascripts/core/app/notations.js"></script>
<script type="text/javascript" src="javascripts/core/notations.js"></script>
<script type="text/javascript" src="javascripts/core/app/options.js"></script>
<script type="text/javascript" src="javascripts/core/app/event-hub.js"></script>
<script type="text/javascript" src="javascripts/core/app/ui.js"></script>

View File

@ -53,6 +53,9 @@ Vue.component('normal-dim-row', {
buyUntil10: function() {
buyManyDimensionsBtnClick(this.tier);
},
showCostTitle: function(value) {
return value.exponent < 1000000;
}
},
template:
`<div v-show="isUnlocked" class="c-normal-dim-row">
@ -66,12 +69,12 @@ Vue.component('normal-dim-row', {
:enabled="isAffordable"
class="o-primary-btn--buy-nd o-primary-btn--buy-single-nd c-normal-dim-row__buy-button"
@click="buySingle"
>Cost: {{shortenCosts(singleCost)}}</primary-button>
><span v-if="showCostTitle(singleCost)">Cost: </span>{{shortenCosts(singleCost)}}</primary-button>
<primary-button
:enabled="isAffordableUntil10"
class="o-primary-btn--buy-nd o-primary-btn--buy-10-nd c-normal-dim-row__buy-button"
@click="buyUntil10"
>Until 10, Cost: {{shortenCosts(until10Cost)}}</primary-button>
>Until 10, <span v-if="showCostTitle(until10Cost)">Cost: </span>{{shortenCosts(until10Cost)}}</primary-button>
<div
v-for="text in floatingText"
:key="text.key"

View File

@ -56,6 +56,9 @@ Vue.component("game-header-tickspeed-row", {
if (this.isGameSpeedNormal) return undefined;
const displayValue = this.isGameSpeedSlow ? (1 / this.gameSpeedMult).toFixed(0) : this.formattedFastSpeed;
return `The game is running ${displayValue}x ${this.isGameSpeedSlow ? "slower." : "faster."}`;
},
showCostTitle: function() {
return this.cost.exponent < 1000000;
}
},
methods: {
@ -78,7 +81,7 @@ Vue.component("game-header-tickspeed-row", {
:enabled="isAffordable"
class="o-primary-btn--tickspeed"
onclick="buyTickSpeed()"
>Cost: {{shortenCosts(cost)}}</primary-button>
><span v-if="showCostTitle">Cost: </span>{{shortenCosts(cost)}}</primary-button>
<primary-button
:enabled="isAffordable"
class="o-primary-btn--buy-max"

View File

@ -55,10 +55,7 @@ Vue.component('modal-import', {
},
methods: {
formatMoney: function(money) {
forcePostBreakFormat = true;
let formatted = this.shorten(money, 2, 1);
forcePostBreakFormat = false;
return formatted;
return this.shortenPostBreak(money, 2, 1);
},
importSave: function() {
if (!this.inputIsValid) return;

View File

@ -20,10 +20,7 @@ Vue.component('modal-load-game', {
change_save(this.saveId);
},
formatMoney: function(money) {
forcePostBreakFormat = true;
let formatted = this.shorten(money, 2, 1);
forcePostBreakFormat = false;
return formatted;
return this.shortenPostBreak(money, 2, 1);
},
update() {
if (this.isSelected) {

View File

@ -1,34 +0,0 @@
var Notation = function Notation(name) {
this.name = name;
this.isCancer = function () {
return name === "Cancer";
};
this.isPain = function () {
return ["Standard", "Cancer", "Brackets"].includes(name);
};
};
Notation.current = function () {
return new Notation(player.options.notation);
};
Notation.set = function (name) {
if (name === undefined) {
name = "Standard";
}
if (name === "Mixed") {
name = "Mixed scientific";
}
if (name === "Default") {
name = "Brackets";
}
if (name === "Emojis") {
name = "Cancer";
}
player.options.notation = name;
if (name === "Cancer") {
ui.notify.success("😂😂😂");
}
};

View File

@ -7,21 +7,10 @@ class GameOptions {
}
static changeNotation() {
const notations = [
"Scientific",
"Engineering",
"Letters",
"Standard",
"Cancer",
"Mixed scientific",
"Mixed engineering",
"Logarithm",
"Brackets",
"Infinity"
];
const notations = Notation.all.map(n => n.name);
const current = player.options.notation;
const next = shiftDown ? notations.previousSibling(current) : notations.nextSibling(current);
Notation.set(next);
Notation.find(next).setCurrent();
}
static toggleNews() {

View File

@ -20,6 +20,9 @@ Vue.mixin({
shorten: function(value, places, placesUnder1000) {
return shorten(value, places, placesUnder1000);
},
shortenPostBreak: function(value, places, placesUnder1000) {
return shortenPostBreak(value, places, placesUnder1000);
},
shortenRateOfChange: function(value) {
return shortenRateOfChange(value);
},

View File

@ -32,7 +32,7 @@ dev.spin4d = function() {
dev.cancerize = function() {
Theme.tryUnlock("Cancer");
Notation.set("Cancer");
Notation.cancer.setCurrent();
};
dev.fixSave = function() {

View File

@ -1,164 +1,3 @@
var FormatList = ['', 'K', 'M', 'B', 'T', 'Qa', 'Qt', 'Sx', 'Sp', 'Oc', 'No', 'Dc', 'UDc', 'DDc', 'TDc', 'QaDc', 'QtDc', 'SxDc', 'SpDc', 'ODc', 'NDc', 'Vg', 'UVg', 'DVg', 'TVg', 'QaVg', 'QtVg', 'SxVg', 'SpVg', 'OVg', 'NVg', 'Tg', 'UTg', 'DTg', 'TTg', 'QaTg', 'QtTg', 'SxTg', 'SpTg', 'OTg', 'NTg', 'Qd', 'UQd', 'DQd', 'TQd', 'QaQd', 'QtQd', 'SxQd', 'SpQd', 'OQd', 'NQd', 'Qi', 'UQi', 'DQi', 'TQi', 'QaQi', 'QtQi', 'SxQi', 'SpQi', 'OQi', 'NQi', 'Se', 'USe', 'DSe', 'TSe', 'QaSe', 'QtSe', 'SxSe', 'SpSe', 'OSe', 'NSe', 'St', 'USt', 'DSt', 'TSt', 'QaSt', 'QtSt', 'SxSt', 'SpSt', 'OSt', 'NSt', 'Og', 'UOg', 'DOg', 'TOg', 'QaOg', 'QtOg', 'SxOg', 'SpOg', 'OOg', 'NOg', 'Nn', 'UNn', 'DNn', 'TNn', 'QaNn', 'QtNn', 'SxNn', 'SpNn', 'ONn', 'NNn', 'Ce',];
const commaRegexp = /\B(?=(\d{3})+(?!\d))/g;
function letter(power,str) {
const len = str.length;
function lN(n) {
let result = 1;
for (var j = 0; j < n; ++j) result = len*result+1;
return result;
}
if (power <= 5) return str[0];
power = Math.floor(power / 3);
let i=0;
while (power >= lN(++i));
if (i==1) return str[power-1];
power -= lN(i-1);
let ret = '';
while (i>0) ret += str[Math.floor(power/Math.pow(len,--i))%len]
return ret;
}
function getAbbreviation(e) {
const prefixes = [
['', 'U', 'D', 'T', 'Qa', 'Qt', 'Sx', 'Sp', 'O', 'N'],
['', 'Dc', 'Vg', 'Tg', 'Qd', 'Qi', 'Se', 'St', 'Og', 'Nn'],
['', 'Ce', 'Dn', 'Tc', 'Qe', 'Qu', 'Sc', 'Si', 'Oe', 'Ne']]
const prefixes2 = ['', 'MI-', 'MC-', 'NA-', 'PC-', 'FM-']
e = Math.floor(e/3)-1;
let index2 = 0;
let prefix = [prefixes[0][e%10]];
while (e >= 10) {
e = Math.floor(e/10);
prefix.push(prefixes[(++index2)%3][e%10])
}
index2 = Math.floor(index2/3)
while (prefix.length%3 != 0) prefix.push("");
let ret = "";
while (index2 >= 0) ret += prefix[index2*3] + prefix[index2*3+1] + prefix[index2*3+2] + prefixes2[index2--];
if (ret.endsWith("-")) ret = ret.slice(0,ret.length-1)
return ret.replace("UM","M").replace("UNA","NA").replace("UPC","PC").replace("UFM","FM")
}
let forcePostBreakFormat = false;
const inflog10 = Math.log10(Number.MAX_VALUE);
const infDecimal = new Decimal(Number.MAX_VALUE);
function formatValue(notation, value, places, placesUnder1000) {
const decimal = new Decimal(value);
if (decimal.exponent < 3) {
return decimal.toNumber().toFixed(placesUnder1000);
}
const notFinite = typeof value === "number" && !Number.isFinite(value);
const isPreBreak = !player.break || Challenge.isRunning();
if (notFinite || !forcePostBreakFormat && isPreBreak && decimal.gte(infDecimal)) {
return "Infinite";
}
let power = decimal.exponent;
let mantissa = decimal.mantissa;
// If commas is false, exponent will be formatted with current notation
let commas = player.options.commas && power < 1000000000;
function formatPower(power) {
if (power < 100000) return power.toString();
if (commas) return formatWithCommas(power);
return formatValue(notation, power, 3, 3);
}
function isOverflowing(mantissa, threshold) {
const pow10 = Math.pow(10, places);
return Math.round(mantissa * pow10) >= threshold * pow10;
}
if (notation === "Scientific" || (notation === "Mixed scientific" && power >= 33)) {
if (isOverflowing(mantissa, 10)) {
mantissa = 1;
power++;
}
return `${mantissa.toFixed(places)}e${formatPower(power)}`;
}
if (notation === "Infinity") {
commas = player.options.commas;
const log10 = decimal.log10();
const infinities = log10 / inflog10;
const infPlaces = infinities < 1000 ? 4 : 3;
const formatted = infinities.toFixed(Math.max(infPlaces, places));
if (commas) {
const parts = formatted.split(".");
return `${formatWithCommas(parts[0])}.${parts[1]}`;
}
else {
return `${formatted}`;
}
}
if (notation === "Logarithm") {
const log10 = decimal.log10();
if (power < 100000) {
return "e" + log10.toFixed(Math.max(places, 1));
}
if (commas) {
return "e" + formatWithCommas(log10.toFixed(places));
}
return "ee" + Math.log10(log10).toFixed(3);
}
if (notation === "Brackets") {
let table = [")", "[", "{", "]", "(", "}"];
let log6 = Math.LN10 / Math.log(6) * decimal.log10();
let wholePartOfLog = Math.floor(log6);
let decimalPartOfLog = log6 - wholePartOfLog;
//Easier to convert a number between 0-35 to base 6 than messing with fractions and shit
let decimalPartTimes36 = Math.floor(decimalPartOfLog * 36);
let string = "";
while (wholePartOfLog >= 6) {
let remainder = wholePartOfLog % 6;
wholePartOfLog -= remainder;
wholePartOfLog /= 6;
string = table[remainder] + string;
}
string = "e" + table[wholePartOfLog] + string + ".";
string += table[Math.floor(decimalPartTimes36 / 6)];
string += table[decimalPartTimes36 % 6];
return string;
}
// 3-digit mantissa notations below
const powerOffset = power % 3;
mantissa *= Math.pow(10, powerOffset);
if (isOverflowing(mantissa, 1000)) {
mantissa = 1;
power += 3;
}
function concatResult(powerFormat) {
return mantissa.toFixed(places) + powerFormat;
}
if (notation === "Engineering" || (notation === "Mixed engineering" && power >= 33)) {
return concatResult("e" + formatPower(power - powerOffset));
}
if (notation === "Standard" || notation === "Mixed scientific" || notation === "Mixed engineering") {
const abbreviation = power <= 303 ? FormatList[(power - powerOffset) / 3] : getAbbreviation(power);
return concatResult(" " + abbreviation);
}
if (notation === "Letters") {
return concatResult(letter(power, 'abcdefghijklmnopqrstuvwxyz'));
}
if (notation === "Cancer") {
return concatResult(letter(power, ['😠', '🎂', '🎄', '💀', '🍆', '👪', '🌈', '💯', '🍦', '🎃', '💋', '😂', '🌙', '⛔', '🐙', '💩', '❓', '☢', '🙈', '👍', '☂', '✌', '⚠', '❌', '😋', '⚡']));
}
return "1337 H4CK3R";
}
function shortenRateOfChange(money) {
return shorten(money, 2, 2);
}
@ -183,12 +22,21 @@ function shortenMultiplier(money) {
return shorten(money, 1, 1);
}
function shortenAutobuyerInput(money) {
return formatValue("Scientific", money, 2, 0);
function shortenAutobuyerInput(value) {
return Notation.scientific.format(value, 2, 0);
}
function shorten(value, places, placesUnder1000) {
return formatValue(Notation.current().name, value, places, placesUnder1000);
// TODO: this is needed for Vue reactivity to work
const notation = player.options.notation;
return Notation.current.format(value, places, placesUnder1000);
}
function shortenPostBreak(value, places, placesUnder1000) {
Notation.forcePostBreakFormat = true;
const shortened = this.shorten(value, places, placesUnder1000);
Notation.forcePostBreakFormat = false;
return shortened;
}
function formatX(value, places, placesUnder1000) {
@ -212,6 +60,7 @@ function timeDisplayShort(ms) {
return TimeSpan.fromMilliseconds(ms).toStringShort();
}
const commaRegexp = /\B(?=(\d{3})+(?!\d))/g;
function formatWithCommas(value) {
return value.toString().replace(commaRegexp, ",");
}

View File

@ -84,7 +84,7 @@ function galaxyReset() {
player.tickDecrease -= 0.03;
player.resets = 0;
softReset(0);
if (Notation.current().isCancer()) player.spreadingCancer += 1;
if (Notation.current === Notation.cancer) player.spreadingCancer += 1;
Galaxy.checkAchievements();
}
@ -107,7 +107,7 @@ function maxBuyGalaxies(manual) {
if (player.currentEternityChall === "eterc6" || Challenge(8).isRunning || player.currentChallenge === "postc7") return
if (Autobuyer.galaxy.limit > player.galaxies || manual) {
while (player.eightAmount >= Galaxy.requirement.amount && (Autobuyer.galaxy.limit > player.galaxies || manual)) {
if (Notation.current().isCancer()) player.spreadingCancer += 1;
if (Notation.current === Notation.cancer) player.spreadingCancer += 1;
player.galaxies++;
}
player.galaxies--;

View File

@ -203,8 +203,20 @@ function onLoad() {
updateWormholeUpgrades()
updateAutomatorRows()
drawPerkNetwork()
Notation.set(player.options.notation);
GameCache.invalidate();
const notation = player.options.notation;
if (notation === undefined) {
player.options.notation = "Standard";
}
const notationMigration = {
"Mixed": "Mixed scientific",
"Default": "Brackets",
"Emojis": "Cancer"
};
if (notationMigration[notation] !== undefined) {
player.options.notation = notationMigration[notation];
}
Notation.find(player.options.notation).setCurrent();
$(".wormhole-upgrades").hide()
if (player.wormhole[0].unlocked) {
@ -228,6 +240,8 @@ function onLoad() {
if (automatorOn) $("#automatorOn")[0].checked = true
automatorIdx = player.reality.automatorCurrentRow;
GameCache.invalidate();
let diff = new Date().getTime() - player.lastUpdate
if (diff > 1000*1000) {
simulateTime(diff/1000)

View File

@ -0,0 +1,407 @@
class Notation {
constructor(name) {
this.name = name;
this._infDecimal = new Decimal(Number.MAX_VALUE);
}
get isPainful() {
return false;
}
/**
* @param {Decimal | number | string | undefined | null} value
* @param {number} places
* @param {number} placesUnder1000
* @return {string}
*/
format(value, places, placesUnder1000) {
const decimal = new Decimal(value);
if (decimal.exponent < 3) {
return decimal.toNumber().toFixed(placesUnder1000);
}
if (typeof value === "number" && !Number.isFinite(value) || this.isInfinite(decimal)) {
return "Infinite";
}
return this.formatDecimal(decimal, places);
}
/**
* @param {Decimal} decimal
* @protected
*/
isInfinite(decimal) {
const isPreBreak = !player.break || Challenge.isRunning();
return !Notation.forcePostBreakFormat && isPreBreak && decimal.gte(this._infDecimal);
}
/**
* @param {Decimal} value
* @param {number} places
* @return {string}
* @abstract
* @protected
*/
formatDecimal(value, places) {}
/**
* @param {number} power
* @return {string}
* @protected
*/
formatExponent(power) {
if (power < 100000) return power.toString();
if (Notation.commasOnExponent(power)) return formatWithCommas(power);
return this.formatDecimal(power.toDecimal(), 3);
}
/**
* @param {number} power
* @return {boolean}
* @protected
*/
static commasOnExponent(power) {
return player.options.commas && power < 1000000000;
}
/**
* Fixes cases like (9.6e3, 0), which results in "10e3" (but we need "1e4" instead)
* because toFixed rounds numbers to closest integer
* @param {Decimal} value
* @param {number} places
* @param {number} threshold
* @param powerOffset
* @return {Decimal}
* @protected
*/
fixMantissaOverflow(value, places, threshold, powerOffset) {
const pow10 = Math.pow(10, places);
const isOverflowing = Math.round(value.mantissa * pow10) >= threshold * pow10;
if (!isOverflowing) return value;
return Decimal.fromMantissaExponent_noNormalize(1, value.exponent + powerOffset);
}
setCurrent() {
player.options.notation = this.name;
Notation.current = this;
}
/**
* @param {string} name
* @return {Notation}
*/
static find(name) {
const notation = Notation.all.find(n => n.name === name);
return notation === undefined ? Notation.mixedScientific : notation;
}
}
Notation.forcePostBreakFormat = false;
Notation.scientific = new class ScientificNotation extends Notation {
formatDecimal(value, places) {
const fixedValue = this.fixMantissaOverflow(value, places, 10, 1);
const mantissa = fixedValue.mantissa.toFixed(places);
const exponent = this.formatExponent(fixedValue.exponent);
return `${mantissa}e${exponent}`;
}
}("Scientific");
class EngineeringNotation extends Notation {
formatDecimal(value, places) {
const engineering = this.makeFixedEngineering(value, places);
const mantissa = engineering.mantissa.toFixed(places);
const exponent = this.formatExponent(engineering.exponent);
return `${mantissa}e${exponent}`;
}
/**
* Transforms 1-digit mantissa decimal into 3-digits mantissa decimal
* For example: 1.5e5 => 150e3
* Note, that it does so in 3 exponent increments, so 1.5e3 is still 1.5e3
* @param {Decimal} value
* @returns {Decimal}
* @protected
*/
makeEngineering(value) {
const exponentOffset = value.exponent % 3;
return Decimal.fromMantissaExponent_noNormalize(
value.mantissa * Math.pow(10, exponentOffset),
value.exponent - exponentOffset
);
}
/**
* @param {Decimal} value
* @param {number} places
* @protected
*/
makeFixedEngineering(value, places) {
const result = this.makeEngineering(value);
return this.fixMantissaOverflow(result, places, 1000, 3);
}
}
Notation.engineering = new EngineeringNotation("Engineering");
Notation.standard = new class StandardNotation extends EngineeringNotation {
constructor() {
super("Standard");
this.abbreviations = [
'', 'K', 'M', 'B', 'T', 'Qa', 'Qt', 'Sx', 'Sp', 'Oc', 'No', 'Dc', 'UDc', 'DDc',
'TDc', 'QaDc', 'QtDc', 'SxDc', 'SpDc', 'ODc', 'NDc', 'Vg', 'UVg', 'DVg', 'TVg',
'QaVg', 'QtVg', 'SxVg', 'SpVg', 'OVg', 'NVg', 'Tg', 'UTg', 'DTg', 'TTg', 'QaTg',
'QtTg', 'SxTg', 'SpTg', 'OTg', 'NTg', 'Qd', 'UQd', 'DQd', 'TQd', 'QaQd', 'QtQd',
'SxQd', 'SpQd', 'OQd', 'NQd', 'Qi', 'UQi', 'DQi', 'TQi', 'QaQi', 'QtQi', 'SxQi',
'SpQi', 'OQi', 'NQi', 'Se', 'USe', 'DSe', 'TSe', 'QaSe', 'QtSe', 'SxSe', 'SpSe',
'OSe', 'NSe', 'St', 'USt', 'DSt', 'TSt', 'QaSt', 'QtSt', 'SxSt', 'SpSt', 'OSt',
'NSt', 'Og', 'UOg', 'DOg', 'TOg', 'QaOg', 'QtOg', 'SxOg', 'SpOg', 'OOg', 'NOg',
'Nn', 'UNn', 'DNn', 'TNn', 'QaNn', 'QtNn', 'SxNn', 'SpNn', 'ONn', 'NNn', 'Ce'
];
}
get isPainful() {
return true;
}
formatDecimal(value, places) {
const engineering = this.makeFixedEngineering(value, places);
const mantissa = engineering.mantissa.toFixed(places);
const abbreviation = value.exponent <= 303 ?
this.abbreviations[engineering.exponent / 3] :
StandardNotation.getAbbreviation(value.exponent);
return `${mantissa} ${abbreviation}`;
}
/**
* @param {number} e
* @return {string}
* @private
*/
static getAbbreviation(e) {
const prefixes = [
['', 'U', 'D', 'T', 'Qa', 'Qt', 'Sx', 'Sp', 'O', 'N'],
['', 'Dc', 'Vg', 'Tg', 'Qd', 'Qi', 'Se', 'St', 'Og', 'Nn'],
['', 'Ce', 'Dn', 'Tc', 'Qe', 'Qu', 'Sc', 'Si', 'Oe', 'Ne']];
const prefixes2 = ['', 'MI-', 'MC-', 'NA-', 'PC-', 'FM-'];
e = Math.floor(e / 3) - 1;
let index2 = 0;
let prefix = [prefixes[0][e % 10]];
while (e >= 10) {
e = Math.floor(e / 10);
prefix.push(prefixes[(++index2) % 3][e % 10]);
}
index2 = Math.floor(index2 / 3);
while (prefix.length % 3 !== 0) prefix.push("");
let ret = "";
while (index2 >= 0) ret += prefix[index2 * 3] + prefix[index2 * 3 + 1] + prefix[index2 * 3 + 2] + prefixes2[index2--];
if (ret.endsWith("-")) ret = ret.slice(0, ret.length - 1)
return ret.replace("UM", "M").replace("UNA", "NA").replace("UPC", "PC").replace("UFM", "FM");
}
}();
Notation.mixedScientific = new class MixedScientificNotation extends Notation {
formatDecimal(value, places) {
const notation = value.exponent >= 33 ? Notation.scientific : Notation.standard;
return notation.format(value, places);
}
}("Mixed scientific");
Notation.mixedEngineering = new class MixedEngineeringNotation extends Notation {
formatDecimal(value, places) {
const notation = value.exponent >= 33 ? Notation.engineering : Notation.standard;
return notation.format(value, places);
}
}("Mixed engineering");
Notation.infinity = new class InfinityNotation extends Notation {
constructor() {
super("Infinity");
this._infLog10 = Math.log10(Number.MAX_VALUE);
}
formatDecimal(value, places) {
const log10 = value.log10();
const infinities = log10 / this._infLog10;
const infPlaces = infinities < 1000 ? 4 : 3;
const formatted = infinities.toFixed(Math.max(infPlaces, places));
if (player.options.commas) {
const parts = formatted.split(".");
return `${formatWithCommas(parts[0])}.${parts[1]}`;
}
else {
return `${formatted}`;
}
}
}("Infinity");
Notation.logarithm = new class LogarithmNotation extends Notation {
formatDecimal(value, places) {
const log10 = value.log10();
if (value.exponent < 100000) {
return "e" + log10.toFixed(Math.max(places, 1));
}
if (Notation.commasOnExponent(value.exponent)) {
return "e" + formatWithCommas(log10.toFixed(places));
}
return "ee" + Math.log10(log10).toFixed(3);
}
}("Logarithm");
Notation.brackets = new class BracketsNotation extends Notation {
get isPainful() {
return true;
}
formatDecimal(value, places) {
let table = [")", "[", "{", "]", "(", "}"];
let log6 = Math.LN10 / Math.log(6) * value.log10();
let wholePartOfLog = Math.floor(log6);
let decimalPartOfLog = log6 - wholePartOfLog;
//Easier to convert a number between 0-35 to base 6 than messing with fractions and shit
let decimalPartTimes36 = Math.floor(decimalPartOfLog * 36);
let string = "";
while (wholePartOfLog >= 6) {
let remainder = wholePartOfLog % 6;
wholePartOfLog -= remainder;
wholePartOfLog /= 6;
string = table[remainder] + string;
}
string = "e" + table[wholePartOfLog] + string + ".";
string += table[Math.floor(decimalPartTimes36 / 6)];
string += table[decimalPartTimes36 % 6];
return string;
}
}("Brackets");
class LettersNotation extends EngineeringNotation {
constructor(name, letters) {
super(name);
this._letters = letters;
}
/**
* @private
*/
letter(power, str) {
const len = str.length;
function lN(n) {
let result = 1;
for (let j = 0; j < n; ++j) result = len * result + 1;
return result;
}
if (power <= 5) return str[0];
power = Math.floor(power / 3);
let i = 0;
while (power >= lN(++i)) ;
if (i === 1) return str[power - 1];
power -= lN(i - 1);
let ret = '';
while (i > 0) ret += str[Math.floor(power / Math.pow(len, --i)) % len];
return ret;
}
formatDecimal(value, places) {
const engineering = this.makeEngineering(value);
const mantissa = engineering.mantissa.toFixed(places);
const letters = this.letter(value.exponent, this._letters);
return mantissa + letters;
}
}
Notation.letters = new LettersNotation("Letters", "abcdefghijklmnopqrstuvwxyz");
Notation.cancer = new class CancerNotation extends LettersNotation{
get isPainful() {
return true;
}
setCurrent() {
super.setCurrent();
ui.notify.success("😂😂😂");
}
}("Cancer", ['😠', '🎂', '🎄', '💀', '🍆', '👪', '🌈', '💯', '🍦', '🎃', '💋', '😂', '🌙', '⛔', '🐙', '💩', '❓', '☢', '🙈', '👍', '☂', '✌', '⚠', '❌', '😋', '⚡']);
Notation.roman = new class RomanNotation extends Notation {
constructor() {
super("Roman");
this._decimalValue = [ 1000000, 900000, 500000, 400000, 100000, 90000, 50000, 40000, 10000, 9000, 5000, 4000, 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ];
this._romanNumeral = [ "M̄", "C̄M̄", "D̄", "C̄D̄", "C̄", "X̄C̄", "L̄", "X̄L̄", "X̄", "X̄", "V̄", "V̄", "", "", "", "", "", "", "", "", "", "","", "", "" ];
this._romanFractions = ["", "·", ":", "∴", "∷", "⁙"];
this.maximum = 4000000;
this._maxLog10 = Math.log10(this.maximum);
}
get isPainful() {
return true;
}
// We need to format all values (even below 1000), so override format instead of formatDecimal
format(value, places, placesUnder1000) {
const decimal = new Decimal(value);
if (typeof value === "number" && !Number.isFinite(value) || this.isInfinite(decimal)) {
return "Infinitus";
}
const decimalValue = this._decimalValue;
const romanNumeral = this._romanNumeral;
const romanFractions = this._romanFractions;
function romanize(value) {
let roman = String.empty;
for (let i = 0; i < decimalValue.length; i++) {
while (decimalValue[i] <= value) {
roman += romanNumeral[i];
value -= decimalValue[i];
}
}
let duodecimal = Math.round(Math.floor(value * 10) * 1.2);
if (duodecimal === 0) {
return roman === String.empty ? "nulla" : roman;
}
if (duodecimal > 5) {
duodecimal -= 6;
roman += "";
}
roman += romanFractions[duodecimal];
return roman;
}
if (decimal.lt(this.maximum)) {
return romanize(decimal.toNumber());
}
const log10 = decimal.log10();
const maximums = log10 / this._maxLog10;
const current = Math.pow(this.maximum, maximums - Math.floor(maximums));
return `${romanize(current)}${this.format(maximums)}`;
}
formatDecimal(value, places) {}
}("Roman");
/**
* Explicit array declaration instead of Object.values for sorting purposes
* (Object.values doesn't guarantee any order)
* @type {Notation[]}
*/
Notation.all = [
Notation.scientific,
Notation.engineering,
Notation.letters,
Notation.standard,
Notation.cancer,
Notation.mixedScientific,
Notation.mixedEngineering,
Notation.logarithm,
Notation.brackets,
Notation.infinity,
Notation.roman
];
Notation.current = Notation.mixedScientific;

View File

@ -329,7 +329,7 @@ function fromValue(value) {
let m,k,l;
if (value.split(" ")[1].length < 5) {
for (l=101;l>0;l--) {
if (value.includes(FormatList[l])) {
if (value.includes(Notation.standard.abbreviations[l])) {
e += l*3
console.log("caught!"+l)
@ -1138,7 +1138,7 @@ function gameLoop(diff, options = {}) {
} else {
Marathon2 = 0;
}
if (player.eternities >= 1 && Notation.current().isPain()) {
if (player.eternities >= 1 && Notation.current.isPainful) {
player.secretUnlocks.painTimer += player.options.updateRate/1000;
if (player.secretUnlocks.painTimer >= 600) giveAchievement("Do you enjoy pain?");
}

View File

@ -126,7 +126,7 @@
<script type="text/javascript" src="javascripts/core/app/player-progress.js"></script>
<script type="text/javascript" src="javascripts/core/app/modal.js"></script>
<script type="text/javascript" src="javascripts/core/app/themes.js"></script>
<script type="text/javascript" src="javascripts/core/app/notations.js"></script>
<script type="text/javascript" src="javascripts/core/notations.js"></script>
<script type="text/javascript" src="javascripts/core/app/options.js"></script>
<script type="text/javascript" src="javascripts/core/app/event-hub.js"></script>
<script type="text/javascript" src="javascripts/core/app/ui.js"></script>