How can I get the level by given experience? - javascript

I have a formula that calculates the experience based on a certain level and another that calculates the level based on the given experience.
But the second function does not return the expected value.
const levels = 40;
const xp_for_first_level = 1000;
const xp_for_last_level = 1000000;
const getExperience = level => {
const B = Math.log(xp_for_last_level / xp_for_first_level) / (levels - 1);
const A = xp_for_first_level / (Math.exp(B) - 1.0);
const old_xp = Math.round(A * Math.exp(B * (level - 1)));
const new_xp = Math.round(A * Math.exp(B * level));
return new_xp - old_xp;
};
const getLevel = experience => {
const B = Math.log(xp_for_last_level / xp_for_first_level) / (levels - 1);
const A = xp_for_first_level / (Math.exp(B) - 1.0);
return Math.ceil(Math.log(experience / A) / B);
};
console.log(getLevel(xp_for_first_level)); // -9
console.log(getLevel(xp_for_last_level)); // 30
Expected result 1 and 40, but returns -9 and 30.
Can anyone help?
Anyone enlighten me, please?

I think the formula should change, i tried with this and it given correct return.
const getLevel = experience => {
const B = Math.log(xp_for_last_level / xp_for_first_level) / (levels + 1);
const A = xp_for_first_level - 1;
return Math.ceil(Math.log(experience / A) / B);
};

Related

Is there any problem with converting this excel formula to javascript?

Here is the excel formula:
=E2-(J2*2*G2)-(K2*E2*2)/30+IF((L2+M2)>60,((L2+M2)-60)*H2+60*G2,(L2+M2)*G2)+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here what I tried (Javascript):
var E2 = $("#sentence").val();
var J2 = $("#deduction").val();
var G2 = 55145;
var K2 = $("#absence").val();
var L2 = $("#overtime").val();
var M2 = 0;
var H2 = 50050;
var N2 = $("#transportation").val();
var sixty;
if ((L2 + M2) > 60) {
sixty = ((L2 + M2) - 60) * H2 + 60 * G2;
} else {
sixty = (L2 + M2) * G2;
};
var result = E2 - (J2 * 2 * G2) - (K2 * E2 * 2) / 30 + sixty;
I couldn't find the way to conver this part of formula:
+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here I found the problem:
Even if one of the variables sets to null, then the formula does not work properly.
It looks like some pretty basic math.
let total = (N2 / AE1) * AE2 + (Q2 * AE5 + P2 * AE4 + O2 * AE3 )
This is basically impossible to translate without seeing the actual spreadsheet but that should get you started. Also, make sure to take into consideration order of operations because the computer is going to evaluate it from left to right unless there are parenthesis (where it will evaluate those first).

Re-selecting another value and clac but old result displays in JS

I'm studying calc. I'm having problem with re-selecting value and calc.
Here is my whole program
https://jsfiddle.net/diessses/c9ykmsf2/6/
When user select value then press submit. it works perfectly. However when user change such as 'cb_amount' , s_month and 's_year' Then click submit below code part displays OLD result. Other part result works fine. Could you teach me write code please?
// PAY_START_END_MONTH_FMT message
const PAY_START_END_MONTH_FMT = "If loan start Month is :start ,<br> Final loan paying will be :end ";
let s_month = document.getElementById(elementId.s_month).value;
if (s_month) {
let s_year = document.getElementById(elementId.s_year).value;
let date = new Date();
date.setMonth(s_month - 1);
date.setFullYear(s_year);
let startMonth = DateManager.formatDate(date, DateManager.getFormatString().YYYY_MM);
DateManager.addMonth(date, (years * 12) - 1);
let endMonth = DateManager.formatDate(date, DateManager.getFormatString().YYYY_MM);
document.getElementById("pay_start_end_month").innerHTML = PAY_START_END_MONTH_FMT.replace(":start", startMonth).replace(":end", endMonth);
}
// CB_SENTENCE_FMT message
const CB_SENTENCE_FMT = "Combined bonus amount will be :j_actual_cb_ttl. Paying times is :j_cbTimes . mothly paying is :j_monthly_bns_payment";
if (bSecondToLastTtl > 1) {
let j_actual_cb_ttl = ValueUtils.comma(bSecondToLastTtl);
let j_cbTimes = cbTimes;
let j_monthly_bns_payment = ValueUtils.comma(monthly_b);
document.getElementById("j_cb_sentence").innerHTML = CB_SENTENCE_FMT.replace(":j_actual_cb_ttl", j_actual_cb_ttl).replace(":j_cbTimes", j_cbTimes).replace(":j_monthly_bns_payment", j_monthly_bns_payment);
}
There are a lot of variables which you are have declaration as "const". Try changing those to "let". Read about it here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let. I have forked your code and tried, seems to be updating the data based on the new values.
Forked fiddle https://jsfiddle.net/b5g73x02/. Below is what I changed.
let cbTimes = years * 2; //
let diff = amount - downpayment;
let justDevideCbAmount = cb_amount / cbTimes;
let monthly_b = (Math.floor(justDevideCbAmount / 100) * 100);
let bSecondToLastTtl = monthly_b * cbTimes;
let paymentTimes = years * 12;
let interestMod = 10000 + (interest * 100);
let ttlWInterest = parseInt(((amount - downpayment) * interestMod )/ 10000);
let ttlWInterestNegativeCb = ttlWInterest - bSecondToLastTtl;
let jstDevideMonthly = ttlWInterestNegativeCb / paymentTimes;
let secondToLastMonthlyPayment = (Math.floor(jstDevideMonthly / 100) * 100);
let firstMonthlyPayment = ttlWInterestNegativeCb - (secondToLastMonthlyPayment * (paymentTimes - 1));
let jKinri = (interest / 100).toFixed(5);
let kinriFinal = ValueUtils.comma(parseInt(ttlWInterest - (amount - downpayment)));

Is it possible to access d3-shape's algorithm for curveMonotoneX?

I am drawing a line in d3 using curveMonotoneX
import React from 'react';
import { line, curveMonotoneX } from 'd3-shape';
export default function GradientLine(props) {
const { points } = props;
const lineGenerator = line()
.curve(curveMonotoneX)
.x(d => d.x)
.y(d => d.y);
const lineDefinition = lineGenerator(points);
return <path d={lineDefinition} />
For the purposes of creating a tooltip that updates based on the current mouse position, I would like to derive the value of curveMonotoneX at a certain X position. Is this possible? I can supply X in terms of pixels or chart units, and would be happy with an answer in pixels or chart units.
The d3 documentation refers to this paper for the formula to calculate curveMonotoneX for a given set of points. Writing the algorithm myself is an option, but I think it's more of a last resort as it introduces potential bugs from the algorithms not matching up exactly, or d3's algorithm changing in the future.
At this time I do not believe it is possible to access D3's algorithm. I wrote a solver which matches D3's path generator except near the first and last data points. For my needs I was able to mask this issue by adding two extra points to the data set, one before and one after (both offscreen).
export class curveMonotoneSolver {
/* Solver for the monotonic curve interpolation algorithm laid out in
http://adsbit.harvard.edu//full/1990A%26A...239..443S/0000443.000.html
Unfortunately I was not able to get the the curves do not match d3's path
generator around the boundary points, so I opted to implement the first
set of solutions for boundary conditions enumerated in the paper,
"define the unknown slope by the one-sided finite differences" (you can
CTRL-F that sentence). */
constructor(controlPoints) {
this.doPreCalculations(controlPoints);
}
update(controlPoints) {
this.doPreCalculations(controlPoints);
}
doPreCalculations(controlPoints) {
this.controlPoints = controlPoints.map((cp, i) => {
const nextCP = controlPoints[i + 1];
if (nextCP) {
return {
...cp,
h: nextCP.x - cp.x,
s: (nextCP.y - cp.y) / (nextCP.x - cp.x),
};
}
return cp;
});
this.controlPoints = this.controlPoints.map((cp, i) => ({
...cp,
dy: this.getDY(cp, i),
}));
}
getDY(cp, i) {
const lastCP = this.controlPoints[i - 1];
if (i === 0) return cp.s;
if (i === this.controlPoints.length - 1) return lastCP.s;
if (lastCP.s * cp.s <= 0) return 0;
const p = (lastCP.s * cp.h + cp.s * lastCP.h) / (cp.h + lastCP.h);
const comparitor = 2 * Math.min(Math.abs(cp.s), Math.abs(lastCP.s));
if (Math.abs(p) > comparitor) {
return 2 * Math.sign(cp.s) * Math.min(Math.abs(cp.s), Math.abs(lastCP.s));
}
return p;
}
solve(x) {
if (x === null) return null;
const startIndex = this.controlPoints.findIndex(cp => cp.x >= x) - 1;
const startCP = this.controlPoints[startIndex];
const endCP = this.controlPoints[startIndex + 1];
const a = (startCP.dy + endCP.dy - 2 * startCP.s) / Math.pow(startCP.h, 2);
const b = (3 * startCP.s - 2 * startCP.dy - endCP.dy) / startCP.h;
const cubicComponent = a * Math.pow(x - startCP.x, 3);
const squaredComponent = b * Math.pow(x - startCP.x, 2);
const linearComponent = startCP.dy * (x - startCP.x);
return cubicComponent + squaredComponent + linearComponent + startCP.y;
}
}

How can i transform my existing script to a "one-request-solution" (API)

Calculation of the actual RSI(Relative Strength Index) of the Bitcoin price via API:
My script currently makes 14 individual requests to the API to calculate the actual RSI for the Bitcoin. Now I have found a request with which I only have to make one request to the API.
https://min-api.cryptocompare.com/data/histoday?fsym=BTC&tsym=USD&limit=14
What do I need to do to integrate the new API into the existing script? I just want to make one request to the API.
// Create a url for currencies + date
const getURL = (currencyFrom, currencyTo, timestamp) =>
`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${currencyFrom}&tsyms=${currencyTo}&ts=${timestamp}`;
// Get a timestamp from exactly x days ago
const timeStampForDaysAgo =
nrOfDays => Date.now() - 1000 * 60 * 60 * 24 * nrOfDays;
const getBTCDollarValueForDays = nrOfDays => Promise
.all(Array.from(
Array(nrOfDays),
(_, i) =>
fetch(getURL("BTC", "USD", timeStampForDaysAgo(i)))
.then(r => r.json()))
);
const getDollarValueFromResponse = obj => obj.BTC.USD;
// Main:
getBTCDollarValueForDays(14)
.then(vals => vals.map(getDollarValueFromResponse))
.then(calcRSI)
.then(console.log.bind(console, "RSI is:"));
function calcRSI(xs) {
let sumGain = 0;
let sumLoss = 0;
const TOLERANCE = 50;
for (let i = 1;
i < xs.length;
i += 1) {
const curr = xs[i];
const prev = xs[i - 1]
const diff = curr - prev;
if (diff >= 0) {
sumGain += diff;
} else {
sumLoss -= diff;
}
}
if (sumGain === 0) return 0;
if (Math.abs(sumLoss) < TOLERANCE) return 100;
const relStrength = sumGain / sumLoss;
return 100 - (100 / (1 + relStrength));
};

is there a JavaScript implementation of the Inverse Error Function, akin to MATLAB erfinv()?

is there a JavaScript implementation of the Inverse Error Function?
This would implement the Gauss inverse error function. Approximations are ok.
Why yes. There is.
The following code uses built-in JavaScript functions and implments Abramowitz and Stegun's algorithm as described here:
function erfinv(x){
var z;
var a = 0.147;
var the_sign_of_x;
if(0==x) {
the_sign_of_x = 0;
} else if(x>0){
the_sign_of_x = 1;
} else {
the_sign_of_x = -1;
}
if(0 != x) {
var ln_1minus_x_sqrd = Math.log(1-x*x);
var ln_1minusxx_by_a = ln_1minus_x_sqrd / a;
var ln_1minusxx_by_2 = ln_1minus_x_sqrd / 2;
var ln_etc_by2_plus2 = ln_1minusxx_by_2 + (2/(Math.PI * a));
var first_sqrt = Math.sqrt((ln_etc_by2_plus2*ln_etc_by2_plus2)-ln_1minusxx_by_a);
var second_sqrt = Math.sqrt(first_sqrt - ln_etc_by2_plus2);
z = second_sqrt * the_sign_of_x;
} else { // x is zero
z = 0;
}
return z;
}
function provided earlier in this post did not work for me... NaN result on a 33meter circle with confidence 65% represented as 65.0 ... I wrote the following based on an equation listed here https://en.wikipedia.org/wiki/Error_function#Inverse_functions and it worked fine:
var _a = ((8*(Math.PI - 3)) / ((3*Math.PI)*(4 - Math.PI)));
function erfINV( inputX )
{
var _x = parseFloat(inputX);
var signX = ((_x < 0) ? -1.0 : 1.0 );
var oneMinusXsquared = 1.0 - (_x * _x);
var LNof1minusXsqrd = Math.log( oneMinusXsquared );
var PI_times_a = Math.PI * _a ;
var firstTerm = Math.pow(((2.0 / PI_times_a) + (LNof1minusXsqrd / 2.0)), 2);
var secondTerm = (LNof1minusXsqrd / _a);
var thirdTerm = ((2 / PI_times_a) + (LNof1minusXsqrd / 2.0));
var primaryComp = Math.sqrt( Math.sqrt( firstTerm - secondTerm ) - thirdTerm );
var scaled_R = signX * primaryComp ;
return scaled_R ;
}
Here's an alternative implementation of Abramowitz and Stegun's algorithm (equivalent to ptmalcolm's answer, but more succinct and twice as fast):
function erfinv(x) {
// maximum relative error = .00013
const a = 0.147
//if (0 == x) { return 0 }
const b = 2/(Math.PI * a) + Math.log(1-x**2)/2
const sqrt1 = Math.sqrt( b**2 - Math.log(1-x**2)/a )
const sqrt2 = Math.sqrt( sqrt1 - b )
return sqrt2 * Math.sign(x)
}
You can test the speed with console.time("erfinv"); for (let i=0; i<1000000000; i++) {erfinv(i/1000000000)}; console.timeEnd("erfinv")
The if statement optimization is commented out as it doesn't seem to make a difference - presumably the interpreter recognizes that this is all one equation.
If you need a more accurate approximation, check out Wikipedia.

Categories

Resources