Convert numbers to degrees in Angular 8 - javascript

I'm getting 25 from the API which must be converted to -45 and the end result must be:
<div style="transform: rotate(-45deg);">
My current code looks like this:
<div style="transform: rotate({{data.angle}}deg);">
Basically, I need to convert
0 to -90
25 to -45
50 to 0
75 to 45
100 is 90
FYI, I'm creating a speedometer. You may see the HTML demo: https://jsfiddle.net/bcgzrdfL/

This is more of a mathematics problem than programming one. Linear equation y = a*x + b satisfies your transformation conditions. After solving it, given your inputs you'll get the following function:
toDegrees(input: number): number {
return 1.8 * input - 90;
}
And the usage in the template:
<div style="transform: rotate({{toDegrees(data.angle)}}deg);">

Related

Need help extracting numbers from string in JavaScript

I need a rock solid RegExp to try and solve some issue with Raphael.js parseStringPath processing regarding Arc path commands and possible others (SnapSVG also inherits the problem). You see, arcTo path command accepts 7 coordinates and settings, but some strings might be malformed due to extreme optimization and the browser doesn't flag them, rather renders them properly. Check Raphael.js demo here.
Have a look at this example, I'm using the RegExp from Raphael.js and a very simplistic example with my own RegExp called incorrectReg, trying to break strings like 000 into [0,0,0] or 011 into [0,1,1].
let spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029",
pathValues = new RegExp(`(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[${spaces}]*,?[${spaces}]*`, `ig`),
incorectReg = new RegExp(`([${spaces}]*0(?=[a-z0-9])|([${spaces}]\\0)*0(?=[a-z0-9]*))`, `ig`); // THIS ONE
function action(){
let input = document.getElementById('input'),
output = document.getElementById('output'),
pathValue = input.getAttribute('d'),
segments = pathValue.replace(/([a-z])/gi,'|$1').split('|').filter(x=>x.trim()),
pathArray = []
segments.map(x=>{
let pathCommand = x[0],
pathParams = x.replace(pathCommand,'').trim()
pathArray.push( [pathCommand].concat(
pathParams.replace(',',' ')
.replace(pathValues,' $1 ')
.replace(incorectReg,'$1 ')
.split(' '))
.filter(x=>x)
);
})
output.setAttribute('d',pathArray.map(x=>x.join(' ')).join(''))
console.table(pathArray)
}
svg {max-width:49%}
<button onclick="action()">Extract</button>
<hr>
<svg viewBox="0 0 16 16">
<path id="input" d="M2,0a2 2 0 00,-2 2a2 2 0 002 2a.5.5 0 011 0z" stroke="red" stroke-width="1px" fill="none"></path>
</svg>
<svg viewBox="0 0 16 16">
<path id="output" d="M0 0" stroke="green" stroke-width="1" fill="none"></path>
</svg>
As you can see in your browser console, we already solve the 000 group (which is obviously not a valid number, boolean, or anything specific), we just have to solve 011 and 11, where all these groups are in fact a string of booleans.
So again, the arcTo path command works with
arcTo -> ['A', rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y]
// str, float, float, float, boolean (0|1), boolean (0|1), float, float
I need a better incorrectReg RegExp and a combination of solutions to properly handle mainly arcTo, and other similar cases. Open to any suggestion.
Thank you
According to the discussion below OP, I propose not to use regexp, but rather a proper parser (or lexer or tokenizer or how to correctly call it).
You can
write your own parser (nice excercise)
use something existing, e.g. I have successfully tried
svg-path-parser.
I am not even sure if such "super"regexp is possible to create.. Anyway you can use "sub"regexp in the parsing process :-)
Just for clarity and serving the community, I will post a working solution, it might help somebody in the future.
Unfortunately the incorrectReg RegExp, good or bad cannot work because it can also change other values as well (EG: M0,11 returns ["M",0,1,1] with the RegExp provided by TheFourthBird), so yea Jan, you were right!
Here's a working solution, please feel free to edit or add more clarity if you like. Once we all agree on a rock solid solution, I will submit a PR to Raphael right after.
let spaces = "\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029",
pathValues = new RegExp(`(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[${spaces}]*,?[${spaces}]*`, `ig`),
incorrectReg = new RegExp(`(?<=[01${spaces}]+)([01])[${spaces}]*`, `g`); // FIXED ONE
function action(){
let input = document.getElementById('input'),
output = document.getElementById('output'),
pathValue = input.getAttribute('d'),
segments = pathValue.replace(/([a-z])/gi,'|$1').split('|').filter(x=>x.trim()),
pathArray = []
segments.map(x=>{
let pathCommand = x[0],
pathParams = x.replace(pathCommand,'').trim();
pathParams = pathParams.replace(',',' ')
.replace(pathValues,' $1 ')
/* .replace(incorrectReg,' $& ') */
.split(' ').filter(x=>x);
if ( pathCommand.toLowerCase() === 'a' && pathParams.length < 7){
for (let i=0, ln = pathParams.length; i<ln; i++){
if ( (i === 3 || i === 4) && pathParams[i].length > 1 ) {
pathParams = pathParams.slice(0,i) // first part of array
.concat(pathParams[i][0]) // extract largeArcFlag OR sweepFlag
.concat(
pathParams[i].slice(1).replace(/(\-\d|\-\.\d|\.\d*(?=\.))/g,'|$1').split('|'), // get sweepFlag
pathParams.slice(i+1)) // continue after flags
.filter(x=>x) // remove added empty "space" items
ln = pathParams.length // update length
}
}
if (pathParams.length === 7) {
pathArray.push([pathCommand].concat(pathParams.splice(0, 7)));
} else {
throw Error(`arcTo requires 7 coordinates, only ${pathParams.length + ' given: ['+pathParams.join(',')}]`)
}
} else {
pathArray.push( [pathCommand].concat(pathParams) );
}
})
output.setAttribute('d',pathArray.map(x=>x.join(' ')).join(''))
// console.log(pathArray)
}
svg {max-width:49%}
<button onclick="action()">Extract</button>
<hr>
<svg viewBox="0 0 16 16">
<path id="input" d="M2 0a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V2a2 2 0 00-2-2H2zm7.5 11h-4a.5.5 0 01-.5-.5v-4a.5.5 0 011 0v2.793l4.146-4.147a.5.5 0 01.708.708L6.707 10H9.5a.5.5 0 010 1z" fill="red"></path>
</svg>
<svg viewBox="0 0 16 16">
<path id="output" d="M0 0" fill="green"></path>
</svg>

Add decimal point to the last character

I'm writing something that pulls some data from the internet; the thing is that one of the keys from the object that I get has weight and height and well, they're not formatted; they're like a whole integer; now, for example; if I get a weight key with a value of 1000 that means that it is 100.0kg; not just 1000, same with the height but sometimes I can get something like 10 on height which is 0.99m or 1m; 100 is 10.0m and so on, so, my question is; what can I do here to format these values properly adding a .0 to the final if the value doesn't have it and if it does have it just add the decimal point before the last character? I tried doing some ifs but they were hard coded and I looking very bad, plus it didn't work.
Output that I'm getting
Example:
Weight: 1000
Height: 20
Weight: 69
Height: 7
Weight: 432
Height: 12
Expected output:
Weight: 100.0
Height: 2,0
Weight: 6.9
Height: 0.7
Weight: 43.2
Height: 1.2
You could divide by 10 and use Number#toFixed for formatting a number.
The toFixed() method formats a number using fixed-point notation.
var values = [1000, 20, 69, 7, 432, 12];
values = values.map(function (v) {
return (v / 10).toFixed(1);
});
console.log(values);

Javascript Math: Geometric Series

I want to create a Roth IRA value calculator. The end result would accept values for annual contribution amount, interest rate, and total number of contribution years.
The calculation—a geometric series—that I need is:
Balance(Y) = P(1 + r)Y + c[ ((1 + r)Y + 1 - (1 + r)) / r ]
FWIW, I'm getting my math information here: http://www.moneychimp.com/articles/finworks/fmbasinv.htm
How would one go about writing this in Javascript? I've been reading about the math functions, but I can't seem to wrap my head around it...
I would definitely read up on JavaScripts operator precedence
A few things to note...
Grouping holds the highest precedence (), NOT with square brakets []
square brackets are for accessing object members and array literals.
There is no operator for exponents in JavaScript use Math.pow(x, n)
For mathematical operations, you MUST use operators 4(x + 1) with throw an
error telling you 4 is not a function. 4 * (x + 1) works.
The following operators are evaluated left-right * / % + - with * / %
holding equal precedence over + -. So mathematical operations are going to behave similar to pemdas.
Another note JavaScript is a dynamic loosely typed language. All numbers are 64-bit floating points, which can yield odd results in some math equations, e.g.
> .1 + .2 = 0.30000000000000004
Another good read
For solving any mathematics series below algorithm can be used. Even for some cases it will not satisfy your expected answer, but it will be correct in some other way.
Steps are as below:
1) Get the difference between the numbers as shown below:
2) Keep making difference until it seems same(difference get 0).
3) Put the same last number which is coming same in that sequence and by adding that difference complete the series by coming up.
<pre>
Examples are as below:
1 2 3 4 5 6 **7**
1 1 1 1 1 **1**
1 4 9 16 25 **36**
3 5 7 9 **11**
2 2 2 **2**
1 8 27 64 125 **216**
7 19 37 61 **91**
12 18 24 **30**
6 6 **6**
0 **0**
</pre>
The same above algorithm is implemented in below js code.
<pre>
//the input
var arr=[1,4,9,16];
var pa6inoArrayMelvo = function(arrr){
var nxtArr=[];
for(i=0;i<arrr.length;i++){
if(arrr[i+1] != undefined){
nxtArr.push(arrr[i+1] -arrr[i]);
}
}
return nxtArr;
}
var keepArray=[];
var keepAlltheArray= function(ar){
var tempArr=[];
keepArray.push(ar);
if(ar.length>1){
tempArr=pa6inoArrayMelvo(ar);
keepAlltheArray(tempArr);
}else{
generateArray(keepArray.length-1);
console.log("ans is:"+keepArray[0]);
}
}
var generateArray=function(idx){
if(keepArray[idx+1]){
var a=keepArray[idx+1];
var b=keepArray[idx];
var ans=a[a.length-1]+b[a.length-1];
keepArray[idx].push(ans);
}else{
var ans=keepArray[idx][keepArray[idx].length-1];
keepArray[idx].push(ans);
}
if(idx>0){
generateArray(idx-1);
}
}
keepAlltheArray(arr);
</pre>
As Yann Chabot said
P*(1 + r)*Y + c(((1 + r)*Y + 1 - (1 + r)) / r)
is the right answer but just as a side note, if you dont have P initialy you should set it to 1 by default.

Creating a Profit Calculator

I'm trying to create a basic profit calculator but I am struggling with one issue.
I've written some basic javascript and the formula almost works. However my issue is that the decimal point doesn't seem to want to work properly. For example:
What is the case cost: 2.80
How may units per case: 2
What is the sell price: 3.15
Total Profit = 1.75 Profit should of course be, 0.175
I'm a complete newbie to JavaScript so your help would be much appreciated.
<form id="profitCalculator">
<p><label>What is the case cost? <input type="text" name="casecost"></label></p>
<p><label>How many packs / units per case? <input type="text" name="packs"></label></p>
<p><label>What is the sell price? <input type="text" name="sell_price"></label></p>
<p>Total profit £: <input type="text" name="profit"></p>
document.getElementById('profitCalculator').onclick = function () {
var casecost = this.elements['casecost'].value || 0;
var packs = this.elements['packs'].value || 0;
var sell_price = this.elements['sell_price'].value || 0;
var profit = sell_price - casecost / packs;
this.elements['profit'].value = profit.toFixed(2); }
Thanks
It should be
var profit = (sell_price - casecost) / packs;
BUT - Never calculate currency with decimals in Javascript!
Javascript will truncate decimal values when they become to long, possibly resulting in nasty rounding errors. Always multiply your values by 100, then calculate everything, and at last, divide by 100 again.
Look at order of operations, you may know this as 'BODMAS'
Supporting Link: http://www.mathsisfun.com/operation-order-bodmas.html
Change to (sell_price - casecost) / packs;
your problem occurs because operators procedence.
var profit = sell_price - casecost / packs;
/ (division) occurs first than - (minus).
As your example.
2.80 / 2 = 1.4
3.15 - 1.4 = 1.75
You should put some parenthesis covering what has to priority, in your case, to get the value 0.175, you should put the like this.
(3.15 - 2.80) / 2 = 0.175
in code
var profit = (sell_price - casecost) / packs;
See MDN's reference on Operator Precedence and you'll see that division (and multiplication) is done before addition or subtraction. So you have essentially:
3.15 - (2.80 / 2) = 1.75
Instead of:
(3.15 - 2.80) / 2 = 0.175
Also note, as #Adrian Schmidt pointed out, using floating point numbers for math is a bad idea. If you do that above calculation in javascript you actually get:
0.17500000000000004
Because computers don't have infinite precision when representing floating point numbers. See, for example: Is floating point math broken?
So your formula should be:
(sell_price - casecost) / packs
Another thing to consider is that the values you get from your text boxes are strings, not numbers. Your formula works because there is no - operator for strings, so javascript automatically converts your values to numbers. But this is a dangerous thing to rely on. For example, if you did this:
sell_price + casecost
With your example inputs, the result would be:
"3.152.80"
Because it's doing string concatenation, not addition.
So it's worth using parseFloat to convert your strings. (and parseInt for packs as it is, presumably, an integer)
So a complete example might look like this:
var casecost = parseFloat(this.elements['casecost'].value) * 100 || 0;
var packs = parseInt(this.elements['packs'].value, 10) || 0;
var sell_price = parseFloat(this.elements['sell_price'].value) * 100 || 0;
var profit = ((sell_price - casecost) / packs) / 100;
this.elements['profit'].value = profit.toFixed(2);
Also note that if packs is 0, then you'll have a divide by zero error. You'll want to add logic to check the value of packs and do something when it's zero (not calculate the profit).

javascript (200-200)/100 = 9009

So I am working on a formula with javascript.
and this is the formula. The data for the tank variables is gathered from inputfields.
y = ((tank1 + tank2 + (tank 3 /25)) - (tank4 + tank4))/100;
alert(y);
so for tank1 = 100 tank2 = 100 and tank3 = 0 tank4 = 100 and tank5 =100
according to javascript the answer to this is 9009 while it is supposed to be 0.
for tank1 = 90 tank2 = 90 tank3 = 0 tank4 = 90 and tank5 = 90 answer = 818.6
I tried changing the divisions to multiplications /25 to 0.04 and /100 to 0.01 but the results were the same.
I also tried renaming the tanks in case they were referring to the wrong tanks.
I have also tried alerting the tanks and they gave the right inserted numbers back.
I am running Jquery.
Does anyone Know what is causing this?
Just use parseInt(tankX) for every tank variable and it will work as expected.
This is because your values come from input fields as strings not integers.
Reference: parseInt

Categories