Skip to content

Instantly share code, notes, and snippets.

@uqmessias
Created July 26, 2024 15:49
Show Gist options
  • Save uqmessias/15b40f8fc7a466680cf6246b4eced735 to your computer and use it in GitHub Desktop.
Save uqmessias/15b40f8fc7a466680cf6246b4eced735 to your computer and use it in GitHub Desktop.
Função para calcular a quantidade de meses que alguém poderia gastar um determinado dinheiro considerando o rendimento desse dinheiro e também para calcular quanto de dinheiro se consegue juntar com o rendimento mensal.
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const stream = require("stream/promises");
const readline = require("readline");
const { totalmem } = require("os");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
/**
* @param {...string} messages
* @returns {Promise<string>}
*/
async function ask(...messages) {
return new Promise((resolve) => {
for (let i = 0; i < messages.length - 1; i++) {
rl.write(`${messages[i]}\n`);
}
rl.question(`${messages[messages.length - 1]}\n`, resolve);
});
}
/**
* @param {RegExp} regex
* @param {string} regexFormat
* @param {(rawValue: string): number} parser
* @param {...string} messages
* @returns {Promise<number>}
*/
async function askNumberFormat(regex, regexFormat, parser, ...messages) {
const answer = await ask(...messages);
if (!regex.test(answer)) {
writeLine(`Formato inválido "${answer}", o correto é "${regexFormat}"`);
writeLine(`Tente novamente!\n`);
return askNumberFormat(regex, regexFormat, ...messages);
}
return parser(answer);
}
/**
* @returns {Promise<'d'|'t'>}
*/
async function askEnumFormat() {
const message =
'Digite "d" para inserir depósito mensal ou "t" para calcular a partir do valor total:';
const answer = await ask(message);
if (!/^[dt]{1}$/.test(answer)) {
writeLine(`Formato inválido "${answer}"`);
writeLine(`Tente novamente!\n`);
return askEnumFormat(message);
}
return answer;
}
/**
* @param {...string} messages
* @returns {Promise<number>}
*/
function askMoneyFormat(...messages) {
return askNumberFormat(
new RegExp("^[\\d]+([\\.|,]{1}[\\d]{1,2})?$"),
"12345.67",
(rawValue) =>
Number.parseFloat(rawValue.replace("%", "").replace(",", ".")),
...messages
);
}
/**
* @param {...string} messages
* @returns {Promise<number>}
*/
function askSimpleNumberFormat(...messages) {
return askNumberFormat(
new RegExp("^[\\d]+$"),
"12345",
Number.parseFloat,
...messages
);
}
/**
* @param {...string} messages
* @returns {Promise<number>}
*/
function askPercentageFormat(...messages) {
return askNumberFormat(
new RegExp("^[\\d]+([\\.|,]{1}[\\d]+)?$"),
"12.3456789%",
(rawValue) =>
Number.parseFloat(rawValue.replace("%", "").replace(",", ".")) / 100,
...messages
);
}
/**
* @param {number} num
* @returns {string}
*/
function formatMoney(num) {
return `R$ ${num
.toFixed(2)
.replace(".", ",")
.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1.")}`;
}
/**
* @param {string} message
*/
function writeLine(message) {
rl.write(`${message}\n`);
}
/**
* @param {number} totalAmount
* @param {number} interestPercentagePerMonth
* @param {number} withdrawAmountPerMonth
* @returns {number}
*/
function getMonths(
totalAmount,
interestPercentagePerMonth,
withdrawAmountPerMonth
) {
let monthInterestAmount = totalAmount * interestPercentagePerMonth;
if (monthInterestAmount >= withdrawAmountPerMonth) {
return Infinity;
}
let totalAmountRest = totalAmount;
let months = 0;
while (withdrawAmountPerMonth < totalAmountRest) {
totalAmountRest += monthInterestAmount;
totalAmountRest -= withdrawAmountPerMonth;
monthInterestAmount = totalAmountRest * interestPercentagePerMonth;
months++;
}
return months;
}
/**
* @param {number} monthlyDepositAmount
* @param {number} monthlyInterestPercentage
* @param {number} totalMonths
* @returns {number}
*/
function getTotalAmount(
monthlyDepositAmount,
monthlyInterestPercentage,
totalMonths
) {
if (totalMonths <= 0) {
return 0;
}
let totalAmount = 0;
for (let i = 1; i <= totalMonths; i++) {
totalAmount +=
monthlyDepositAmount + totalAmount * monthlyInterestPercentage;
}
return totalAmount;
}
async function aposentadoria() {
const enumType = await askEnumFormat();
/** @type {number} */
let totalAmount;
/** @type {number} */
let monthlyWithdrawAmount;
/** @type {number} */
let monthlyInterestPercentage;
async function askForMonthlyWithdrawAmountAndPercentage() {
monthlyWithdrawAmount = await askMoneyFormat(
"Digite o valor que você deseja sacar por mês:"
);
monthlyInterestPercentage = await askPercentageFormat(
"Digite o percentual que rende por mês:"
); // percentual de juros que o valor da conta rende por mês
}
if (enumType === "t") {
totalAmount = await askMoneyFormat(
"Digite o valor total que você tem ou deseja ter:"
);
await askForMonthlyWithdrawAmountAndPercentage();
} else {
const monthlyDepositAmount = await askMoneyFormat(
"Digite o valor que você deseja depositar por mês:"
);
const months = await askSimpleNumberFormat(
"Digite a quantidade de meses que você gostaria de depositar:"
);
await askForMonthlyWithdrawAmountAndPercentage();
totalAmount = getTotalAmount(
monthlyDepositAmount,
monthlyInterestPercentage,
months
); // valor total que alguém tem na conta ou quer ter
writeLine(
`Com ${formatMoney(
monthlyDepositAmount
)} depositado todo mês por ${months} meses e rendendo ${(
monthlyInterestPercentage * 100
).toFixed(2)}% ao mês, você junta ${formatMoney(
months * monthlyDepositAmount
)}, mas tem o valor final de ${formatMoney(totalAmount)}`
);
}
const result = getMonths(
totalAmount,
monthlyInterestPercentage,
monthlyWithdrawAmount
);
writeLine(
`Com o valor total de ${formatMoney(
totalAmount
)} você consegue tirar ${formatMoney(
monthlyWithdrawAmount
)} por ${result} meses`
);
}
aposentadoria();
@uqmessias
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment