Address PR feedback

This commit is contained in:
SpectralFlame 2021-12-31 11:14:51 -06:00 committed by cyip92
parent 7439052dab
commit b837ee79b8
8 changed files with 95 additions and 72 deletions

View File

@ -93,14 +93,14 @@ export const AutobuyerInputFunctions = {
if (!input) return undefined;
try {
let decimal;
if (/^e\d*[.]?\d+$/u.test(input.replace(",", ""))) {
if (/^e\d*[.]?\d+$/u.test(input.replace(/,/gu, ""))) {
// Logarithm Notation
decimal = Decimal.pow10(parseFloat(input.replace(",", "").slice(1)));
} else if (/^\d*[.]?\d+(e\d*[.]?\d+)?$/u.test(input.replace(",", ""))) {
decimal = Decimal.pow10(parseFloat(input.replace(/,/gu, "").slice(1)));
} else if (/^\d*[.]?\d+(e\d*[.]?\d+)?$/u.test(input.replace(/,/gu, ""))) {
// Scientific notation; internals of break-infinity will gladly strip extraneous letters before parsing, but
// since this is largely uncommunicated to the user, we instead explicitly check for formatting and reject
// anything that doesn't fit as invalid
decimal = Decimal.fromString(input.replace(",", ""));
decimal = Decimal.fromString(input.replace(/,/gu, ""));
} else {
return undefined;
}
@ -127,7 +127,7 @@ export const AutobuyerInputFunctions = {
if (!input) return undefined;
// We explicitly check formatting here instead of letting parseInt handle the whole thing because otherwise the
// fact that parseInt removes extraneous letters means junk like "361ebqv3" registers as valid and parses as 361
if (!/^\d+$/u.test(input.replace(",", ""))) return undefined;
if (!/^\d+$/u.test(input.replace(/,/gu, ""))) return undefined;
const int = parseInt(input, 10);
return isNaN(int) || !Number.isInteger(int) ? undefined : int;
}

View File

@ -56,8 +56,8 @@ Vue.component("automator-docs-main-page", {
documentation pages. This will be similarly formatted to reference pages for programming.
<br>
<br>
If you have minimal or no prior coding experience, you can instead use some premade templates which generate
text that can put directly into the Automator text field.
If you have minimal or no prior coding experience, or do not feel like writing your own code, you can
instead use some premade templates which generate text that can put directly into the Automator text field.
</div>
<div v-else-if="listState === 1">
<automator-man-page

View File

@ -163,7 +163,7 @@ export class AutomatorScript {
}
export const AutomatorData = {
// -1 is the ID for the documentation page
// 1 is the ID for the documentation page
currentInfoPane: 1,
// Used for getting the correct EC count in event log
lastECCompletionCount: 0,

View File

@ -33,17 +33,17 @@ export class ScriptTemplate {
this.templateUnlockDilation(params);
break;
default:
throw new Error("Unrecognized template name in ScriptTemplate");
throw new Error(`Unrecognized template name ${tempalateName} in ScriptTemplate`);
}
}
/**
* Special formatting for numbers in templates; we can't use format() here because that will change based on the
* player's cuttent notation. This is generally desirable in the rest of the game, but in most notations will
* player's current notation. This is generally desirable in the rest of the game, but in most notations will
* result in unparseable garbage here. Numbers are formatted assuming they're integers, and Decimals are formatted
* with 2 decimal places (in scientific notation if above 1000)
* @param {Number | Decimal} num Number to format, disregarding current notation settings
* @returns String representation of the properly-formatted number
* @returns {String} The properly-formatted number, in a reasonable-looking format valid for the automator
*/
format(num) {
if (typeof num === "number") return Math.round(num);
@ -75,7 +75,7 @@ export class ScriptTemplate {
* sets the autobuyer to those settings. Relevant props of object passed in:
* @param {String} mode "mult" or "time" for times highest and time modes, respectively
* @param {Decimal} value Numerical value for autobuyer settings (assumed to be seconds in time)
* @returns String suffix to feed into an automator script, should be prefixed by "auto [prestige] "
* @returns {String} String suffix to feed into an automator script, should be prefixed by "auto [prestige] "
*/
parseAutobuyerProp(mode, value) {
switch (mode) {
@ -84,7 +84,7 @@ export class ScriptTemplate {
case "time":
return `${this.format(value)} seconds`;
default:
throw new Error("Unrecognized autobuyer mode in automator script templates");
throw new Error(`Unrecognized autobuyer mode ${mode} in automator script templates`);
}
}
@ -155,9 +155,9 @@ export class ScriptTemplate {
this.lines.push("auto eternity off");
this.lines.push(`auto infinity 5s`);
if (params.isBanked) {
const has191 = new TimeStudyTree(params.tree).purchasedStudies.includes(TimeStudy(191));
if (!has191) this.warnings.push(`Tree does not contain TS191; banking anything will require
Achievement "${Achievement(131).name}"`);
const has191 = this.storedTreeObj.purchasedStudies.includes(TimeStudy(191));
if (!has191) this.warnings.push(`TS191 is not reachable from an empty tree; banking anything in this template
will require Achievement "${Achievement(131).name}"`);
const bankRate = has191 ? 0.1 : 0.05;
this.lines.push("// Note: This template attempts to get all the Banked Infinities within a single Eternity");
this.lines.push(`wait infinities > ${this.format(params.infinities.dividedBy(bankRate), 2)}`);
@ -194,7 +194,7 @@ export class ScriptTemplate {
if (!tree.hasRequirements(TimeStudy.eternityChallenge(params.ec), false, true)) {
this.warnings.push("Specified Study Tree cannot reach specified EC");
}
} else this.warnings.push("Specified Study Tree already has a different EC unlocked");
} else if (tree.ec !== params.ec) this.warnings.push("Specified Study Tree already has a different EC unlocked");
// Apply autobuyer settings; we specifically want to turn auto-eternity off so that we can manually trigger the
// prestige - otherwise, the autobuyer may end up preempting multiple completions

View File

@ -26,7 +26,7 @@ GameDatabase.reality.automator.templates = {
{
name: "decimal",
isValidString: str => AutobuyerInputFunctions.decimal.tryParse(str),
map: x => new Decimal(x),
map: x => AutobuyerInputFunctions.decimal.tryParse(x),
},
{
name: "boolean",
@ -124,8 +124,8 @@ GameDatabase.reality.automator.templates = {
warnings: () => {
const list = [];
if (!Perk.achievementGroup5.isBought) {
list.push(`You will not start this Reality with Achievement "${Achievement(131).name}" and thus grinding
Infinities may be less useful than expected since they cannot be banked until later on`);
list.push(`You will not start this Reality with Achievement "${Achievement(131).name}" - grinding
Infinities may be less useful than expected since they cannot be banked until later`);
}
// Boundless flow (infinity generation)
if (RealityUpgrade(11).isBought) {
@ -166,7 +166,7 @@ GameDatabase.reality.automator.templates = {
name: "Unlock Dilation",
description: `This script performs repeated Eternities, attempting to re-purchase a Time Study Tree every
Eternity. Autobuyer settings must be supplied for the Infinity and Eternity Autobuyers. The script acts
similarly to the "Climb EP" script, except that it instead loops until you have the total Time Theorem
similarly to the "Climb EP" script, except it loops until you have the total Time Theorem
requirement to unlock Dilation instead of until a target EP amount. After reaching the target, it will
unlock Dilation.`,
inputs: [

View File

@ -167,7 +167,9 @@ export class TimeStudyTree {
const maxTT = Currency.timeTheorems.value.add(GameCache.currentStudyTree.value.spentTheorems[0])
.clampMax(Number.MAX_VALUE).toNumber();
const maxST = V.spaceTheorems;
if (this.spentTheorems[0] + config.cost > maxTT || this.spentTheorems[1] + stNeeded > maxST) return;
const hasTT = this.spentTheorems[0] + config.cost <= maxTT;
const hasST = this.spentTheorems[1] + stNeeded <= maxST;
if (!hasTT || !hasST) return;
}
this.spentTheorems[0] += config.cost;
this.spentTheorems[1] += stNeeded;

View File

@ -8483,10 +8483,22 @@ input.o-automator-block-input {
flex-direction: column;
justify-content: space-between;
margin: 1rem;
height: 50rem;
height: 60rem;
width: 70rem;
}
.c-automator-template-description {
height: 13rem;
}
.c-automator-template-inputs {
height: 22rem;
}
.c-automator-template-warnings {
height: 22rem;
}
.c-automator-template-entry {
padding: 0.2rem;
}

View File

@ -17,17 +17,20 @@ export default {
templateInputs: [],
buttonTextStrings: [],
invalidInputCount: 0,
templateScript: null,
templateProps: null,
};
},
computed: {
params: () => GameDatabase.reality.automator.templates.paramTypes,
templates: () => GameDatabase.reality.automator.templates.scripts,
warnings() {
return this.invalidInputCount === 0
? this.modalConfig.warnings().concat(this.templateScript.warnings)
? this.modalConfig.warnings().concat(this.templateScript?.warnings)
: this.modalConfig.warnings();
},
templateScript() {
if (this.invalidInputCount !== 0) return null;
return new ScriptTemplate(this.templateProps, this.modalConfig.name);
}
},
// Many props in this component are generated dynamically from a GameDB entry, but Vue can only give reactive
// behavior to props that exist on declaration. We need all the dynamically generated inputs to be reactive, so we
@ -35,20 +38,17 @@ export default {
// calls don't error out from undefined inputs.
created() {
for (const input of this.modalConfig.inputs) {
if (this.paramTypeObject(input.type).boolDisplay) this.$set(this.templateInputs, input.name, false);
else this.$set(this.templateInputs, input.name, "");
const boolProp = this.paramTypeObject(input.type).boolDisplay;
if (boolProp) {
this.$set(this.templateInputs, input.name, false);
this.buttonTextStrings[input.name] = boolProp[1];
} else {
this.$set(this.templateInputs, input.name, "");
this.invalidInputCount++;
}
}
},
methods: {
update() {
this.invalidInputCount = 0;
for (const input of this.modalConfig.inputs) {
const boolProp = this.paramTypeObject(input.type).boolDisplay;
if (boolProp) this.buttonTextStrings[input.name] = boolProp[this.templateInputs[input.name] ? 0 : 1];
if (!this.isValid(input)) this.invalidInputCount++;
}
if (this.invalidInputCount === 0) this.makeTemplate();
},
paramTypeObject(name) {
return this.params.find(p => p.name === name);
},
@ -61,14 +61,21 @@ export default {
? undefined
: "c-automator-template-textbox--invalid";
},
makeTemplate() {
const templateProps = {};
updateTemplateProps() {
this.templateProps = {};
this.invalidInputCount = 0;
for (const input of this.modalConfig.inputs) {
const typeObj = this.paramTypeObject(input.type);
const mapFn = x => (typeObj.map ? typeObj.map(x) : x);
templateProps[input.name] = mapFn(this.templateInputs[input.name]);
this.templateProps[input.name] = mapFn(this.templateInputs[input.name]);
if (!this.isValid(input)) this.invalidInputCount++;
}
this.templateScript = new ScriptTemplate(templateProps, this.modalConfig.name);
},
updateButton(input) {
this.templateInputs[input.name] = !this.templateInputs[input.name];
const boolProp = this.paramTypeObject(input.type).boolDisplay;
this.buttonTextStrings[input.name] = boolProp[this.templateInputs[input.name] ? 0 : 1];
this.updateTemplateProps();
},
copyAndClose() {
copyToClipboard(this.templateScript.script);
@ -82,38 +89,40 @@ export default {
<template>
<div class="c-automator-template-container">
<ModalCloseButton @click="emitClose" />
<b>Template "{{ modalConfig.name }}"</b>
{{ modalConfig.description }}
<br>
<br>
<b>Required Information:</b>
<div
v-for="input in modalConfig.inputs"
:key="input.name"
class="c-automator-template-entry"
>
{{ input.prompt }}:
<span v-if="paramTypeObject(input.type).boolDisplay">
<button
class="o-primary-btn"
@click="templateInputs[input.name] = !templateInputs[input.name]"
>
{{ buttonTextStrings[input.name] }}
</button>
</span>
<span v-else>
<input
ref="templateInputs[input.name]"
v-model="templateInputs[input.name]"
type="text"
class="c-automator-template-textbox"
:class="validityClass(input)"
>
</span>
<div class="c-automator-template-description">
<b>"{{ modalConfig.name }}" Template</b>
<br>
{{ modalConfig.description }}
</div>
<br>
<br>
<div>
<div class="c-automator-template-inputs">
<b>Required Information:</b>
<div
v-for="input in modalConfig.inputs"
:key="input.name"
class="c-automator-template-entry"
>
{{ input.prompt }}:
<span v-if="paramTypeObject(input.type).boolDisplay">
<button
class="o-primary-btn"
@click="updateButton(input)"
>
{{ buttonTextStrings[input.name] }}
</button>
</span>
<span v-else>
<input
ref="templateInputs[input.name]"
v-model="templateInputs[input.name]"
type="text"
class="c-automator-template-textbox"
:class="validityClass(input)"
@input="updateTemplateProps"
>
</span>
</div>
</div>
<div class="c-automator-template-warnings">
<b>Possible things to consider:</b>
<div v-if="warnings.length !== 0">
<div