Skip to content

Instantly share code, notes, and snippets.

@alaninnovates
Last active June 20, 2022 21:47
Show Gist options
  • Save alaninnovates/513a605eb2d69ae92193a55ea852261f to your computer and use it in GitHub Desktop.
Save alaninnovates/513a605eb2d69ae92193a55ea852261f to your computer and use it in GitHub Desktop.
Islands Totem Calculator
const { MessageEmbed } = require('discord.js');
const columnify = require('columnify');
const { itemData, totemData, lmcPrice, priceData } = require('../data');
const { getUserPrices } = require('../util');
const INVALID_INPUT_MESSAGE =
'One or more of your inputs are not valid. Input must be in the format of `utility/efficiency/quality` and all values must be between 0 and 53.';
const parseInteger = (str) => {
if (!/^(0|[1-9]\d*)$/.test(str)) return;
return parseInt(str);
};
const validateInteger = (int) => {
const parsed = parseInteger(int);
// console.log(parsed, int, parsed > 53, parsed < 0);
if (parsed === undefined || parsed > 53 || parsed < 0) {
// console.log('returning false');
return false;
}
return true;
};
const getRange = (arr, start, end) => {
return arr.slice(start, end);
};
/**
* @param {number} num
*/
const roundLmc = (num) => {
// const roundedNumber = Math.floor(num);
// if (roundedNumber === 0) return 1;
// return roundedNumber;
return Math.floor(num);
};
/**
* @typedef {Object} InputData
* @property {number} beginUtility
* @property {number} targetUtility
* @property {number} beginEfficiency
* @property {number} targetEfficiency
* @property {number} beginQuality
* @property {number} targetQuality
*/
/**
* @param {InputData} inputData
* @param {import('discord.js').CommandInteraction} interaction
*/
const calculatePrices = async (
{
beginUtility,
targetUtility,
beginEfficiency,
targetEfficiency,
beginQuality,
targetQuality,
},
interaction,
) => {
/*
NEVERMIND
The table is formatted as follows:
if mode is ITEM:
| Item Name | Utility | Efficiency | Quality | Total Amount Required | Price |
| Wood | 10 | 30 | 39 | 79 | 47400 |
| Iron | 10 | 30 | 39 | 79 | 330 |
| ----------- | ------- | ---------- | ------- | --------------------- | ----- |
| Total | - | - | - | - | 47730 |
| Total (LMC) | - | - | - | - | ~2 |
if mode is COIN:
| Item Name | Utility | Efficiency | Quality | Total Amount Required |
| Wood | 6000 | 5000 | 10000 | 21000 |
| Iron | 310 | 3430 | 300 | 4040 |
| ----------- | ------- | ---------- | ------- | --------------------- |
| Total | - | - | - | 25040 |
| Total (LMC) | - | - | - | ~1 |
if mode is LMC:
todo
*/
const userPrices = await getUserPrices(
interaction.client.db,
interaction.user.id,
);
const prices = Object.assign(priceData, userPrices);
const itemRequirements = {};
for (const item of itemData) {
const utilityReq = getRange(
totemData.utility[item],
beginUtility,
targetUtility,
);
const efficiencyReq = getRange(
totemData.efficiency[item],
beginEfficiency,
targetEfficiency,
);
const qualityReq = getRange(
totemData.quality[item],
beginQuality,
targetQuality,
);
itemRequirements[item] = {
utility: utilityReq.reduce((acc, cur) => acc + cur, 0),
efficiency: efficiencyReq.reduce((acc, cur) => acc + cur, 0),
quality: qualityReq.reduce((acc, cur) => acc + cur, 0),
};
}
const getPrice = (amount, item) => {
return amount * prices[item];
};
const coinRequirements = {};
for (const requirement of Object.keys(itemRequirements)) {
const reqData = itemRequirements[requirement];
coinRequirements[requirement] = {
utility: getPrice(reqData.utility, requirement),
efficiency: getPrice(reqData.efficiency, requirement),
quality: getPrice(reqData.quality, requirement),
};
}
const lmcRequirements = {};
for (const requirement of Object.keys(coinRequirements)) {
const reqData = coinRequirements[requirement];
lmcRequirements[requirement] = {
utility: roundLmc(reqData.utility / lmcPrice),
efficiency: roundLmc(reqData.efficiency / lmcPrice),
quality: roundLmc(reqData.quality / lmcPrice),
};
}
return {
itemRequirements,
coinRequirements,
lmcRequirements,
};
};
const generatePriceEmbed = (itemRequirements, requirementType) => {
// console.log(itemRequirements);
const itemRequirementTransformed = Object.keys(itemRequirements).map(
(itemName) => ({
item: itemName,
utility: itemRequirements[itemName].utility,
efficiency: itemRequirements[itemName].efficiency,
quality: itemRequirements[itemName].quality,
total:
itemRequirements[itemName].utility +
itemRequirements[itemName].efficiency +
itemRequirements[itemName].quality,
}),
);
itemRequirementTransformed.push(
{
item: '-',
utility: '-',
efficiency: '-',
quality: '-',
total: '-',
},
{
item: 'Total',
utility: itemRequirementTransformed.reduce(
(acc, cur) => acc + cur.utility,
0,
),
efficiency: itemRequirementTransformed.reduce(
(acc, cur) => acc + cur.efficiency,
0,
),
quality: itemRequirementTransformed.reduce(
(acc, cur) => acc + cur.quality,
0,
),
total: itemRequirementTransformed.reduce(
(acc, cur) => acc + cur.total,
0,
),
},
);
for (const item of itemRequirementTransformed) {
item.utility = item.utility.toLocaleString();
item.efficiency = item.efficiency.toLocaleString();
item.quality = item.quality.toLocaleString();
item.total = item.total.toLocaleString();
}
return new MessageEmbed()
.setTitle(requirementType)
.setDescription(
'```\n' + columnify(itemRequirementTransformed) + '\n```',
)
.setColor('GREEN');
};
/**
* @param {import('discord.js').CommandInteraction} interaction
* @param {InputData} inputData
* @param {number} totemAmount
*/
const showResultEmbed = async (interaction, inputData, totemAmount) => {
const priceData = await calculatePrices(inputData, interaction);
const priceMessage = await interaction.user.send({
embeds: [
new MessageEmbed()
.setTitle('Calculator Result')
.setDescription(
`These are the prices for ${totemAmount} totems upgraded by\n- ${
inputData.targetUtility - inputData.beginUtility
} utility levels\n- ${
inputData.targetEfficiency - inputData.beginEfficiency
} efficiency levels\n- ${
inputData.targetQuality - inputData.beginQuality
} quality levels`,
)
.setColor('GREEN'),
generatePriceEmbed(priceData.itemRequirements, 'Item requirements'),
generatePriceEmbed(priceData.coinRequirements, 'Coin requirements'),
generatePriceEmbed(priceData.lmcRequirements, 'LMC requirements'),
new MessageEmbed()
.setTitle('Return')
.setDescription(
`Click [here](https://discord.com/channels/${interaction.guildId}/${interaction.channelId}) to return to the channel you were in.`,
)
.setFooter({
text: 'Calculator made by alaninnovates#0123',
}),
],
});
await interaction.followUp({
embeds: [
new MessageEmbed()
.setTitle("I have DM'd you the prices.")
.setDescription(
`Click [here](${priceMessage.url}) to view them.`,
)
.setColor('GREEN'),
],
});
};
module.exports = {
name: 'calculate',
/**
* @param {import('discord.js').CommandInteraction} interaction
*/
execute: async (interaction) => {
const totemAmount = interaction.options.getNumber('amount');
const inputData = {
beginUtility: 0,
targetUtility: 0,
beginEfficiency: 0,
targetEfficiency: 0,
beginQuality: 0,
targetQuality: 0,
};
await interaction.reply({
embeds: [
new MessageEmbed()
.setTitle('Inputs')
.setDescription(
'Please input your desired upgrades in the format of `utility/efficiency/quality` when prompted to do so.\n**Example:** `0/0/0` means your totem is upgraded at 0 utility, 0 efficiency, and 0 quality.\n\n**Please input your begining upgrade values.** These values are what your totems are currently upgraded to.\n\nSay "cancel" at any time to cancel.',
),
],
});
let currentInput = 0;
const inputsCollector = interaction.channel
.createMessageCollector({
filter: (m) => m.author.id === interaction.user.id,
})
.on('collect', async (message) => {
if (message.content.toLowerCase() === 'cancel') {
inputsCollector.stop();
return await interaction.followUp('Alright, cancelled!');
}
const inputs = message.content.split('/');
// console.log(
// inputs.length,
// !inputs.every(validateInteger),
// inputs,
// );
if (inputs.length !== 3 || !inputs.every(validateInteger)) {
await message.channel.send(INVALID_INPUT_MESSAGE);
return;
}
const [utility, efficiency, quality] = inputs.map(parseInteger);
if (currentInput === 0) {
inputData.beginUtility = utility;
inputData.beginEfficiency = efficiency;
inputData.beginQuality = quality;
await message.channel.send({
embeds: [
new MessageEmbed()
.setTitle('Target upgrades')
.setDescription(
'**Please input your target upgrade values.** These values are what you want your totems to be upgraded to.',
),
],
});
currentInput = 1;
} else if (currentInput === 1) {
inputData.targetUtility = utility;
inputData.targetEfficiency = efficiency;
inputData.targetQuality = quality;
inputsCollector.stop();
if (
inputData.beginUtility > inputData.targetUtility ||
inputData.beginEfficiency >
inputData.targetEfficiency ||
inputData.beginQuality > inputData.targetQuality
) {
return await interaction.followUp(
'Your beginning upgrade values cannot be higher than your target upgrade values. **Please re-run the command** to try again.',
);
}
await showResultEmbed(interaction, inputData, totemAmount);
}
});
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment