Capture values in a code similar to JSON - javascript

I'm trying to make a tool for one game (Victoria II), the save game (the entire save game hasn't this format, only the part which i intend to use, the rest of save game hasn't any importance now) of Victoria II has this format:
AAA = {
B = {
random_text = 1000.00
another_one = 400.00
}
C= {
no_importance = 222
}
D = {
random_text = 5.00
another_one = 10.00
}
}
How the tool will work? The tool will calculate the GDP of the country AAA (there are 100 countries, firstly i want to calculate the GDP of AAA, but i will want to calculate of every one. The code of every country is three letters in uppercase), the B parameter is the domestic production of some goods (random_text and another_one), the C parameter has no importance, so, the tool will ignore it. The D parameter is the price of some goods (in this case, random_text and another_one, if not mistaken there are 20 goods). So, the tool (in JavaScript) must multiply the production of goods in the country with the price that each goods has, and then make a table with the GDP of every country. The question is: How i can do this with JavaScript? I'm trying to use regexp, but I'm always failing, the code captures the parameter C and makes the tool fails. For every country, i want to insert its name in the table and its respective GDP.
Note: In the link above, there are more comments about the working of the tool.

Assuming the format you show above is reliable, you could do a quick-and-dirty conversion to JSON via a few calls to .replace(), then parse that JSON and process the resulting object as required.
Not sure I understood what you were saying about the GDP calculation, but I think you mean that the GDP for AAA would be the sum of each B value multiplied by its corresponding D value, i.e., 1000.00 * 5.00 + 400.00 * 10.00 = 9000.
var input = ' /* your input here */ ';
var json = '{'
+ input.replace(/([^\s]+)\s*=/g,'"$1":')
.replace(/([^{\s])\n(\s*[^{}])/g,'$1,\n$2')
.replace(/,(\s*})/g,'$1')
+ '}';
var obj = JSON.parse(json);
var output = Object.keys(obj).map(function(v) {
return {
country: v,
gdp: Object.keys(obj[v].B).reduce(function(p, c) {
return p + obj[v].B[c] * obj[v].D[c];
}, 0)
};
});
After running the above, the output variable will be an array of objects with details in this format:
[ { "country": "AAA", "gdp": 9000 }, //etc. ]
Expand the following and run it to see it working with three countries:
var input = `AAA = {
B = {
random_text = 1000.00
another_one = 400.00
}
C= {
no_importance = 222
}
D = {
random_text = 5.00
another_one = 10.00
}
}
BBB = {
B = {
random_text = 111.00
another_one = 222.00
}
C= {
no_importance = 222
}
D = {
random_text = 3.00
another_one = 4.00
}
}
CCC = {
B = {
x = 10.0
y = 20.0
z = 30.0
}
C= {
no_importance = 222
}
D = {
x = 1.00
y = 2.00
z = 3.00
}
}`;
var json = '{'
+ input.replace(/([^\s]+)\s*=/g,'"$1":')
.replace(/([^{\s])\n(\s*[^{}])/g,'$1,\n$2')
.replace(/,(\s*})/g,'$1')
+ '}';
var obj = JSON.parse(json);
var output = Object.keys(obj).map(function(v) {
return {
country: v,
gdp: Object.keys(obj[v].B).reduce(function(p, c) {
return p + obj[v].B[c] * obj[v].D[c];
}, 0)
};
});
console.log(output);

Related

How do I iterate the price in parentheses and add it to the total price, My code doesn't seem to work

I've found this on google and gave it a go. But it seems as if its not doing anything. it isn't updating the price total area at all, nor is it adding or subtracting.
<script type="text/javascript">
function doMath() {
// Capture the entered values of two input boxes
var my_input1 = document.getElementsByName("case").value;
var my_input2 = document.getElementsByName("cpu").value;
var my_input3 = document.getElementsByName("cooling").value;
var my_input4 = document.getElementsByName("ram").value;
var my_input5 = document.getElementsByName("gpuchoice").value;
var my_input6 = document.getElementsByName("storage").value;
var my_input7 = document.getElementsByName("storage1").value;
var my_input8 = document.getElementsByName("storage2").value;
var my_input9 = document.getElementsByName("powersupchoice").value;
var my_input10 = document.getElementsByName("fans").value;
var my_input11 = document.getElementsByName("lighting").value;
var my_input12 = document.getElementsByName("sleeving").value;
var my_input13 = document.getElementsByName("peripherals").value;
var my_input14 = document.getElementsByName("headsets").value;
var my_input15 = document.getElementsByName("controllers").value;
var my_input16 = document.getElementsByName("wirelessadapter").value;
// Add them together and display
var sum = parseInt(my_input1) + parseInt(my_input2) + parseInt(my_input3) + parseInt(my_input4) + parseInt(my_input5) + parseInt(my_input6) + parseInt(my_input7) + parseInt(my_input8) + parseInt(my_input9) + parseInt(my_input10) + parseInt(my_input11) + parseInt(my_input12) + parseInt(my_input13) + parseInt(my_input14) + parseInt(my_input15) + parseInt(my_input16);
document.getElementsByName("text2").value = sum;
document.getElementsByName("text2").innerHTML = sum;
}
</script>
Any advice, or a better way of handling this perhaps?
The code works, but it wont get the data price of storage 1 or storage 2, with those two removed from the sum function it adds the totals of everything else perfect. just not these two inputs.
<select name="storage1" id="storage1">
<option data-productprice="45.00" value="None" selected>None</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 500 GB (+$0.00)">Crucial MX500 500 GB (+$0.00)</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 1 TB (+$0.00)">Crucial MX500 1 TB (+$0.00)</option>
<option data-productprice="45.00" value="Crucial MX500 SSD 2 TB (+$0.00)">Crucial MX500 2 TB (+$0.00)</option>
</select>
here is the JS that is broken with the storage options in sum function, remove the parseFloat(my_input7) everything works great. put it back in and NAN haha
function doMath() {
//var regExp = /\(([^)]+)\)/;
//var matches = regExp.exec("I expect five hundred dollars ($500).");
// Capture the entered values of two input boxes
var my_input1 = document.querySelector('[name=case]:checked').dataset.productprice;
var my_input2 = document.querySelector('[name=cpu]:checked').dataset.productprice;
var my_input3 = document.querySelector('[name=cooling]:checked').dataset.productprice;
var my_input4 = document.querySelector('[name=ram]:checked').dataset.productprice;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').dataset.productprice;
var my_input6 = document.querySelector('[name=storage]:checked').dataset.productprice;
var my_input7 = document.querySelector('[name=storage1]').dataset.productprice;
var my_input8 = document.querySelector('[name=storage2]').dataset.productprice;
var my_input9 = document.querySelector('[name=powersupchoice]:checked').dataset.productprice;
var my_input10 = document.querySelector('[name=fans]:checked').dataset.productprice;
var my_input11 = document.querySelector('[name=lighting]:checked').dataset.productprice;
var my_input12 = document.querySelector('[name=sleeving]').dataset.productprice;
var my_input13 = document.querySelector('[name=peripherals]').dataset.productprice;
var my_input14 = document.querySelector('[name=headsets]').dataset.productprice;
var my_input15 = document.querySelector('[name=controllers]').dataset.productprice;
var my_input16 = document.querySelector('[name=wirelessadapter]').dataset.productprice;
// Add them together and display
var sum = parseFloat(55.00) + parseFloat(50.25) + parseFloat(20.55) + parseFloat(my_input1) + parseFloat(my_input2) + parseFloat(my_input3) + parseFloat(my_input4) + parseFloat(my_input4) + parseFloat(my_input6) + parseFloat(my_input7);
document.getElementById('pricetotal').value = sum;
document.getElementById('text2').innerHTML = sum;
}
I have solved it due to the two wonderful people that posted there answers! I read up on what you guys recommended and ended up using this to fix it due to the select option field.
Code is below :D
function doMath() {
var my_input1 = document.querySelector('[name=case]:checked').dataset.productprice;
var my_input2 = document.querySelector('[name=cpu]:checked').dataset.productprice;
var my_input3 = document.querySelector('[name=cooling]:checked').dataset.productprice;
var my_input4 = document.querySelector('[name=ram]:checked').dataset.productprice;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').dataset.productprice;
var my_input6 = document.querySelector('[name=storage]:checked').dataset.productprice;
var my_input7 = document.querySelector('[name=storage1]');
var my_input8 = document.querySelector('[name=storage2]');
var my_input9 = document.querySelector('[name=powersupchoice]:checked').dataset.productprice;
var my_input10 = document.querySelector('[name=fans]:checked').dataset.productprice;
var my_input11 = document.querySelector('[name=lighting]:checked').dataset.productprice;
var my_input12 = document.querySelector('[name=sleeving]');
var my_input13 = document.querySelector('[name=peripherals]:checked').dataset.productprice;
var my_input14 = document.querySelector('[name=headsets]');
var my_input15 = document.querySelector('[name=controllers]');
var my_input16 = document.querySelector('[name=wirelessadapter]');
var valueofssd1 = my_input7.options[my_input7.selectedIndex].dataset.productprice;
var valueofssd2 = my_input8.options[my_input8.selectedIndex].dataset.productprice;
var valueofsleeving = my_input12.options[my_input12.selectedIndex].dataset.productprice;
var valueofheadset = my_input14.options[my_input14.selectedIndex].dataset.productprice;
var valueofcontroller = my_input15.options[my_input15.selectedIndex].dataset.productprice;
var valueofadapter = my_input16.options[my_input16.selectedIndex].dataset.productprice;
// Add them together and display
var sum = parseFloat(my_input1) + parseFloat(my_input2) + parseFloat(my_input3) + parseFloat(my_input4) + parseFloat(my_input5) + parseFloat(my_input6) + parseFloat(my_input9) + parseFloat(my_input10) + parseFloat(my_input11) + parseFloat(my_input13) + parseFloat(valueofssd1) + parseFloat(valueofssd2) + parseFloat(valueofsleeving) + parseFloat(valueofheadset) + parseFloat(valueofcontroller) + parseFloat(valueofadapter);
document.getElementById('pricetotal').value = "$" + sum + ".00";
document.getElementById('text2').innerHTML = "$" + sum + ".00";
}
I write an answer as it's a bit too long for a comment.
There's a lot of mess both in your HTML code and in the way you try to select elements. You have a mix of <input> and <select> elements in your page, whose values you try to select and sum.
When you select <input> elements via getElementsByName, you select indeed a NodeList of elements (there are also some <h1> inside!), so you have to narrow them to the ones you really need to get their value.
The right selections for your elements would be:
var my_input1 = document.querySelector('[name=case]:checked').value;
var my_input2 = document.querySelector('[name=cpu]:checked').value;
var my_input3 = document.querySelector('[name=cooling]:checked').value;
var my_input4 = document.querySelector('[name=ram]:checked').value;
var my_input5 = document.querySelector('[name=gpuchoice]:checked').value;
var my_input6 = document.querySelector('[name=storage]:checked').value;
var my_input7 = document.querySelector('[name=storage1]').value;
var my_input8 = document.querySelector('[name=storage2]').value;
var my_input9 = document.querySelector('[name=powersupchoice]:checked').value;
var my_input10 = document.querySelector('[name=fans]:checked').value;
var my_input11 = document.querySelector('[name=lighting]:checked').value;
var my_input12 = document.querySelector('[name=sleeving]').value;
var my_input13 = document.querySelector('[name=peripherals]').value;
var my_input14 = document.querySelector('[name=headsets]').value;
var my_input15 = document.querySelector('[name=controllers]').value;
var my_input16 = document.querySelector('[name=wirelessadapter]').value;
Still too much cumbersome to be honest, but at least it selects the right elements.
But, also this way it won't work for your purposes. That's because sometimes your <input>/<select> elements have a value like value="45", some other times they have a value like value="Moroval Diamond Mesh Case"; this way, they are not summable:
"45" + "Moroval Diamond Mesh Case" // will yield the string "45Moroval Diamond Mesh Case"
That's the exact list of values you would get from my code above:
"45" // parseInt() -> 45
"Ryzen 5 3600 (+$0.00)" // parseInt() -> NaN
"Thermaltake TH120 RGB (+$0.00)" // parseInt() -> NaN
"Corsair Vengeance LPX 16 GB (2 x 8 GB) DDR4-3200 Memory (+$0.00)" // parseInt() -> NaN
"XFX Radeon RX 6500 XT 4 GB Speedster QICK 210" // parseInt() -> NaN
"Samsung 970 Evo Plus M2 NVME SSD 500 GB (+$0.00)" // parseInt() =-> NaN
"None" // parseInt() -> NaN
"None" // parseInt() -> NaN
"Corsair CX 650M 650 WATT BRONZE Power Supply (+$0.00)" // parseInt() -> NaN
"Artic P12 Non-RGB Case Fans x3 (+$0)" // parseInt() -> NaN
"No Lighting Selected" // parseInt() -> NaN
"None" // parseInt() -> NaN
undefined // parseInt() -> NaN
"None" // parseInt() -> NaN
"None" // parseInt() -> NaN
"No Wireless Adapter" // parseInt() -> NaN
The only number comes from the first selection. Others are strings or undefined, so parseInt() won't be a number but NaN (Not a Number).
Edit (based on #MikeT comment):
It's better to always use numbers for value attribute in this case. Something like (random numbers):
Consider that in your <select> elements, each <option> tag should always have a unique identifier as value (to be sure to uniquely identify each option):
// select HTML element
<select name="headsets" id="headsets">
<option value="1">None</option>
<option value="2">Razer BlackShark V2 Pro 7.1 Wireless (+$100.00)</option>
<option value="3">HyperX Cloud II 7.1 Wireless (+$95.00)</option>
<option value="4">Corsair Void RGB Elite 7.1 Wireless (+$87.60)</option>
<option value="5">Logitech G935 DTS:X 7.1 Wireless (+$156.99)</option>
</select>
// hard-coded array of products to link selected value and price. probably a database-based solution is a better choice
const headsets = [
{ id: 1, description: 'None', price: 0 },
{ id: 2, description: 'Razer BlackShark V2 Pro 7.1 Wireless', price: 100 },
{ id: 3, description: 'HyperX Cloud II 7.1 Wireless', price: 95 },
{ id: 4, description: 'Corsair Void RGB Elite 7.1 Wireless', price: 87.6 },
{ id: 5, description: 'Logitech G935 DTS:X 7.1 Wireless', price: 156.99 },
];
// this is the price to sum
const selectedHeadsetPrice = headsets.find(item => item.id === +document.getElementById('headsets').value).price;
as #cheesyMan says your html is a mess and you are trying to brute for something that is better handled by finesse
i would aim for something more like this
const headsetData = { // preferably this would be read form a database or other not on page source
"none":{
display:"None",
price:0
},
"rzp7":{
display:"Razer BlackShark V2 Pro 7.1 Wireless (+$100.00)",
price:100
},
"hxc7":{
display:"HyperX Cloud II 7.1 Wireless (+$95.00)",
price:95
},
}
you could then populate from this list
const headsetselect = document.querySelector('select[name=headsets]')
for(const [key, {display} of Object.entries(headsetData)){
const opt = document.createElement("option");
opt.value = key;
opt.innerHTML = display;
headsetselect .appendChild(opt );
}
and then at the calculation stage you would do
const headsetselect = document.querySelector('select[name=headsets]')
total += headsetData[headsetselect.value].price
though if you follow best practice and ids are unique per element then
document.getElementById("headset")
would be be better than a query selector
edit:
you mention that you also wanted the text for an email
which can also be easilty accompliched like this
const product = headsetData[headsetselect.value]
text += `${product.display} ( ${product.price})`

How to store 256 bit Hex in javascript

how can i handle a 64 character hexadecimal (256 bit) in Javascript.
> b = 0x1936c240636390dc823e3a728e94b208eb53c6756d81da57ec3425e05d43ac10
// 1.1404571630774433e+76
> b.toString(16)
// '1936c24063639100000000000000000000000000000000000000000000000000'
When i do that, i loose accuracy.
Edited:
Unfortunately i in the following scenario js transforms the input paramter
function uint256(hexNumber){
let bigNumber = BigInt(hexNumber);
logger.info('Hex:'+ bigNumber.toString(16)+' to bigInt '+bigNumber);
return bigNumber.toString(16);
}
so that the call gives me:
uint256(0x1936c240636390dc823e3a728e94b208eb53c6756d81da57ec3425e05d43ac10)
//Hex:1936c24063639100000000000000000000000000000000000000000000000000 to bigInt 11404571630774432649143590157348217225799776391499391730068078364228824596480
For the context, I'm trying to transcript a large Solidity function which looks like this only with 520 array allocation instead of six.
vk.a = Pairing.G1Point(uint256(0x1936c240636390dc823e3a728e94b208eb53c6756d81da57ec3425e05d43ac10), uint256(0x2d70ff78e8216bf29d58923a686d9738278b8ce2fd822e197c85b09286d15566));
vk.b = Pairing.G2Point([uint256(0x2b4daf047abe2e7f0b311118c1b963b63695dc0d769cea78849604434de055bf), uint256(0x29c13ecb6f33dbc4b3b8a02e2e255511ce4c26a8a2f299efcc94caf2de4fce00)], [uint256(0x1da9020008df7f549751f8a251af3b2dc4a2ad3e0870de54acaedd9fc1b47e17), uint256(0x25ea0d7e2b29de431b86a943db30dbf4d98f68df9ca8a9628d14d1591e817d90)]);
vk.gamma = Pairing.G2Point([uint256(0x011016e22ae045444f50fb80f246ec486c7e02af09132cd38c4fcf484983e4f2), uint256(0x00e83c788c2878d1d5eba3ed49b0d81e4c0487dedc3e4d1c2baab5833785b62f)], [uint256(0x05eb89e741ed5b5d611cebf92d1ed02cd6f3311089f0d400df7d9ced5a48fd41), uint256(0x132a90a3b0d369ccd66e2a5ba04a935e44d8ad5dca93a76bba592a578130a911)]);
vk.delta = Pairing.G2Point([uint256(0x065f6a3323a2abffd621fc263f348eb914904b68d5897729ae34a6b9d33f0852), uint256(0x0c3b60f59d3bd50328a04c0ff6d979199685d0526f89f6ac29d6174ce24707a2)], [uint256(0x26e7ebce2b44efef6b6315938e33f0a8ecc82dbad635c9efa681ed85bbb59982), uint256(0x12e0f3721230a0f38f6c9913048d5230fd2615ef3ff7f6ee4b20dfe0bdea1a86)]);
//vk.gamma_abc = new Pairing.G1Point[](520);
vk.gamma_abc[0] = Pairing.G1Point(uint256(0x196af2b7293f4166f93674ac9a094d1d280285ee936d12c0f009d8c0ceb7275c), uint256(0x2d536bc8c9d330f9e10ab4db1210b14c5caa794064a34aeeb92d35a2142e1003));
vk.gamma_abc[1] = Pairing.G1Point(uint256(0x17519a69d3ab06c7376e8b441eaf8abf240bfba37fa92d203a57ee4e7ebcc09a), uint256(0x0afafa533a58968132a300d25f3e2e31efb50713c60dd5e62093eb9ac68947cd));
vk.gamma_abc[2] = Pairing.G1Point(uint256(0x09c5badd7ac47ceadcdc87260b470e1bc173a2e281d0ee2bbe1e998761906a1c), uint256(0x10225903a96deb54a81d5b2fa1f0e19c080ae66e219038c421e61b55abc6e8c2));
vk.gamma_abc[3] = Pairing.G1Point(uint256(0x0d1cb6242e59537351ba89b729849ccf46909b6f4de62d661541dcee62d4ab91), uint256(0x086240d4e29a207011e2ef99d35db84fcc0d85f805e0102ddbbee0d1ca5c814a));
vk.gamma_abc[4] = Pairing.G1Point(uint256(0x004b8d16937ab63656090b905a085f8b4209c1122d12173ed1d8681b4e2e9c2f), uint256(0x194925508ed037169cf95c94716551dbce6aad6c65a44fcccd44280461816e95));
vk.gamma_abc[5] = Pairing.G1Point(uint256(0x0e8d97d12590c0c3854e5a4ba14c802d4a66e6cfda02b950584014341ec261dc), uint256(0x2e8d13c1c8ee7a46f50ad7b74de98eaf4cae13360a537ef3f55998a914255045));
vk.gamma_abc[6] = Pairing.G1Point(uint256(0x16f625a3746225f60ae1d9891196b2baa06f8be90dd738ea1dbeefffb4c62d0c), uint256(0x2de7e064393312d12c372c87ade6b533e2c01ae7e45c0b94b892cf608e52f910));
I'm hoping to find an easy way to get this key into a JSON format, so i was thinking to add the following to the upper part:
let Pairing = {
G1Point : (a,b) => {
return {x:a, y: b};
},
G2Point : (a,b) => {
return {x : a, y : b}
}
}
let vk = {
a : {},
b : {},
gamma_abc : [],
delta : {},
};
function uint256(hexNumber){
let bigNumber = BigInt(hexNumber);
logger.info('Hex:'+ bigNumber.toString(16)+' to bigInt '+bigNumber);
return bigNumber.toString(16);
}
You need to convert it too BigInt. If you want to store that value in a database for example, then you need to store it as an string.
var b = "0x1936c240636390dc823e3a728e94b208eb53c6756d81da57ec3425e05d43ac10";
var bigNumb = BigInt(b);
console.log(bigNumb.toString(16));
console.log(bigNumb.toString(10));

How to solve equation using javascript/nodejs?

I have an equation : 100 + (y * 5) = 200
I have to find the value of y = (200 -100)/5, but the main thing is operators sign may changes ( for eg: 100 * (y -5) = 200 ),
So How to write a program such that if the equation is passed, it solve and gives the value of x, irrespective of whatever operators are used.
Any help is appreciated.
I have tried below in node js and have to solve equation :
var fs = require('fs');
fs.readFile('equation.json',
// callback function that is called when reading file is done
function(err, data) {
// json data
var jsonData = data;
// parse json
var jsonParsed = JSON.parse(jsonData);
//operators array
var operators = {
"add":"+",
"subtract":"-",
"multiply":"*",
"divide":"/",
"equal":"="
};
var eq,op1,op2,equation;
for(opt in operators){
if(jsonParsed.op == opt){
eq = operators.equal;
}
//looking for first operator
if(jsonParsed.lhs.op == opt){
if(opt=="add"){
op1 = operators.add;
}
else if(opt=="subtract"){
op1 = operators.subtract;
}
else if(opt=="multiply"){
op1 = operators.multiply;
}
else if(opt=="divide"){
op1 = operators.divide;
}
}
//looking for second operator
if(jsonParsed.lhs.rhs.op == opt){
if(opt=="add"){
op2 = operators.add;
}
else if(opt=="subtract"){
op2 = operators.subtract;
}
else if(opt=="multiply"){
op2 = operators.multiply;
}
else if(opt=="divide"){
op2 = operators.divide;
}
}
}
//console.log(eq);
//console.log(op1);
//console.log(op2)
//parsing expression
equation = jsonParsed.lhs.lhs + op1 +"(" + jsonParsed.lhs.rhs.lhs + op2 + jsonParsed.lhs.rhs.rhs + ")" + eq + jsonParsed.rhs;
console.log(equation);
});
JSON
{
"op": "equal",
"lhs": {
"op": "add",
"lhs": 1,
"rhs": {
"op": "multiply",
"lhs": "x",
"rhs": 10
}
},
"rhs": 21
}
Systems of linear equations are most easily and generally solved on computers using matrices.
There is a webpage here that goes into how this works:
https://www.aplustopper.com/solving-systems-linear-equations-using-matrices/
There are also matrix packages for JavaScript available on the internet, like this one
https://mathjs.org/docs/datatypes/matrices.html
Disclosure: I have no association with either of these websites. This is how I did it in Java (using NASA's matrix package for Java) back in the day.

How to get the exact percentage in a JavaScript formula

I'm trying to figure out what will be the JavaScript formula if I have a data in my database and this is i want to be the output:
if the data = 10 I want to be output that in a 100% in which I will be going to use in an div element height
if the data = 65 I want to be output that in a 0% in which I will be going to use in an div element height
and this is my code right now but I can't figure it out:
var datas = JSON.parse(data);
var ID, Bio, Non_Bio, Recy, Extra;
var div = 10;
ID = datas[0].ID;
Bio = datas[0].Bio;
Non_Bio = datas[0].Non_Bio;
Recy = datas[0].Recy;
Extra = datas[0]. Extra;
var obtained = Bio;
var obtained2 = Non_Bio;
var obtained3 = Recy;
var obt = obtained*100/div;
var obt2 = obtained2*100/div;
var obt3 = obtained3*100/div;
var water1 = $("#water1").height() + obt;
var water2 = $("#water2").height() + obt2;
var water3 = $("#water3").height() + obt3;
If the math can't be solved in one's head, doing it on paper can help, particularly when solving a pair of simultaneous equations using high school maths.
Assuming the ultrasound value to height relationship is linear you can write it as the equation of a line:
h = a * u + b ... 1)
where h is height, u is the ultrasound sensor reading, and a and b are constants.
Now take two calibration values of sensor readings taken for an empty and a full bin and call them c0 and c100 respectively.
From 1)
0 = a * c0 + b ... 2) using the c0 value , and
100 = a * c100 + b ... 3) using c100
Solving this pair of simultaneous equations proceeds along the lines of
b = 0 -a*c0 ... from 2)
b = 100 -a*c100 ... 4) from 3)
Hence
0 -a*c0 = 100 -a*c100
a*c100 - a*c0 = 100
a = 100/(c100-c0) ... 5)
and now substituting 4) back into 2) gives
b = 100 - a*c100 ... 6)
In this test example, the equations are converted into a factory function that returns an object with calibrate and height functions calibrate(c0, c100) and height( sensor). The height returned is rounded to the nearest quarter due to an overall lack of precision in the data.
function createBin() {
var a, b;
function calibrate( c0, c100) {
a = 100/(c100-c0);
b = 100 - a*c100;
}
function height( sensor) {
let h = a * sensor + b;
return Math.round( 4*h)/4;
}
return {calibrate, height};
}
const bin = createBin();
bin.calibrate (65, 10);
var readings = [67, 65, 37, 10, 5];
readings.forEach(
reading => console.log( "height( %s) = %s%", reading, bin.height(reading))
);
Note that when dealing with real world sensors, calibration data can vary between sensors and installations - hard coding equations that need to be calibrated against hardware variability is something to be avoided.
var datas=[{
ID :10,
Bio :7,
Non_Bio: 65,
Recy :75,
Extra :20
}]
var obt=[];
datas.map((data,index)=>{
console.log(data)
Object.values(data).map(item=>{
console.log(item)
if(item===10){
obt.push("100%");
}
else{
obt.push("0%");
}
})})
console.log("required output:");
console.log(obt);
Assumed: ID = datas[0].ID; since you are fetching from array 0th index and then its key.It mus be array of object (you have not given the proper inputs.) and the if logic can be changed accordingly as you mentioned if its 10 it must be 100%.
Logic: Just iterating each object of the array and then getting the object values (of each key i.e. id,bio etc..) and checking the value if divisible by 10 then pushing that data into empty array so you can use it further. You can also insert the output data into map.

I think I'm having a scope issue with a custom sort method

I've been working on a javascript class to simplify the sorting and comparing of library of congress call numbers. For the most part, the majority of it is working, except for one of the the main methods to return a sorted list. I can do the sort outside of the class given other methods of the class, so I'm not sure why I'm losing the scope when I enter the sort() function.
I'm not sure if there's a way I can pass the scope into the sort() or what I need to do to have access to that method.
I've created a github gist of the javascript and a quick html test of the class (including the error) that should demonstrate things:
https://gist.github.com/rayvoelker/accaa95c6b5db28f7f84429f8a3d8cdf
Here's the class methods that I'm having trouble with. Maybe I'm just not seeing something that should be simple.
locCallClass.prototype.localeCompare = function (a, b) {
try {
var a_norm = this.returnNormLcCall(a),
b_norm = this.returnNormLcCall(b);
return ( a_norm < b_norm ? -1 : (a_norm > b_norm ? 1 : 0) );
}
catch (err) {
// console.log("error")
}
}
locCallClass.prototype.sortCallNumbers = function (callnumbers) {
var sorted = callnumbers.sort(function (a,b) {
return this.localeCompare(a,b);
});
return sorted;
}
And here is the way that I'm calling it:
var loc = new locCallClass();
var set1 = ["LC 346 .65 .B29","LC 346 .M634","HX 754 .5 .C15","HX 754 .C7723"];
var sorted = loc.sortCallNumbers(set1);
And here's a snippet of the same demonstration code from the gist:
// js-loc-callnumbers
// A javascript class to normalize and perform various sorting options on
// Library of Congress Call Numbers within a library institution.
function locCallClass() {
// the regular expression that defines the Library of
// Congress call number. Thanks to Bill Dueber's post on the subject for the regex
// http://robotlibrarian.billdueber.com/2008/11/normalizing-loc-call-numbers-for-sorting/
this.lc = /^\s*([A-Z]{1,3})\s*(\d+(?:\s*\.\s*\d+)?)?\s*(?:\.?\s*([A-Z]+)\s*(\d+)?)?(?:\.?\s*([A-Z]+)\s*(\d+)?)?\s*(.*?)\s*$/;
//local storage for an array of call numbers
this.callNumberArray = [];
//a mostly sorted array of call numbers for testing
this.testCallNumbers = ["Z10.1 A", "Z5.1 A", "CB3 .C55", "CS418 .J82", "CS425 .B95", "D21 .W93", "D21.1.D58 1981", "D761 .W54", "D761.9.F7 G8", "DA86 .P884", "DA86 .R52", "DA506.A2 A4", "DA506.A2 B75", "DA784.5 .M23 1989", "DA785 .S12", "DC129 .W6", "DC130.A2 H3", "DF623 .C46", "DF631 .B313", "DK 267 .W78", "DK268.A1D56213 1999", "DS 70.7 .O6", "DS 70.7 .S27", "DS557.C28S6", "DS 557 .F3", "DS 917 .W47", "DS 917.35 .P33", "DT 636 .S5 A3", "DT636.2.F65 1996", "E 160 .F72", "E 160 .F73", "E184.A1I444 1992", "E184.A1I445 1996", "E 302 .J442 1984", "E302.J442 2004B", "E 487 .C746", "E 487 .C746 1966", "E 876 .U84 1986", "E 876 .V53", "F548.9.N4R437 2005", "F548.9.N4S77 2007", "F 1656 .C7 1968", "F 1659 .B55 F4", "GN 51 .A58", "GN 51 .A58 1988B", "GV 741 .B56", "GV741 .I58", "Q183.9.I34 2002", "Q183.9.L45 1993", "QA 29 .P775 A3 1987", "QA29.R3A4 1995", "QA 76.758 .H86 1989", "QA76.758.K365 2008", "QA 164 .C63 1969", "QA 164 .C63 1969", "QA274.73.R84 2004", "QA274.73.S2813 1999", "QA 353 .E5 Z4313 1993", "QA 353 .G44 W55 1990", "QA 640.7 .B55 1970", "QA641.A587 1996", "QC 173.98 .M44 V.1", "QC 173.98 .M44 V.1", "QD 21 .C51", "QD 21 .C51", "QD501 .B242 V.37", "QD501.B242 V.38", "QH 81 .B73", "QH 81 .B754", "QH540.I5", "QH540.I5", "QK 314 .F54", "QK 321 .A3613", "QL951 .C8", "QL951 .C8", "QP 601 .C733 V.171", "QP 601 .C733 V.172", "RA 410.7 .C5", "RA 410.7 .E73", "RC455.S8 1961", "RC 455 .S928", "RD 98 .G38", "RD 99 .E42 1955", "S 942 .C6 1974", "S 942 .K63 1972", "TA166.W68 1980", "TA167.A965 1998", "TA1520.S87 2007", "TA1520.W35 1998", "TD 741 .I33", "TD 741 .I33 1956", "TJ163.2 .A55", "TJ163.2 .A55", "TK5105.875.I57G723 2005", "TK5105.875.I57H338 1996", "TL215.J58L35 2005", "TL215.M18D53 2005", "TP155.C69 V.5 1997", "TP 155 .C74 1986", "TS156 .I838 2003", "TS 156 .J324"];
}
// locCallClass.returnNormLcCall(call_number)
// returns a "normalized" call number
locCallClass.prototype.returnNormLcCall = function(call_number) {
var result = this.lc.exec(call_number);
if (!result) {
throw new Error(call_number + " Not a Call Number");
}
// track the position of what we're looking at in the callnumber
var before_first_cutter = true;
var return_string = "";
// work through the results starting at 1 (the 0 value in the array is the original input)
for(var i=1; i<=(result.length-1); i++) {
if (i>1) {
return_string = return_string + "."
}
if (i>2) {
before_first_cutter = false;
}
return_string = return_string + this.padZed(result[i], before_first_cutter);
}
// TODO: consider adding further checks to see if the return string
// consists of 8 segments 9 characters and throw an error if not
return return_string;
}
// locCallClass.localeCompare(b,a)
// replicates functionality of the normal compare function
// so that it may be used in external sorting operations:
//
// A negative number if the reference string (a) occurs before the
// given string (b);
// positive if the reference string (a) occurs after
// the compare string (b);
// 0 if they are equivalent.
locCallClass.prototype.localeCompare = function (a, b) {
try {
var a_norm = this.returnNormLcCall(a),
b_norm = this.returnNormLcCall(b);
return ( a_norm < b_norm ? -1 : (a_norm > b_norm ? 1 : 0) );
}
catch (err) {
// console.log("error")
}
}
// locCallClass.sortCallNumbers()
// takes a variable list of call numbers as arguments, and returns
// a sorted array of call numbers in their original format/
// You can also use this method with an array like the following:
// loc.sortCallNumbers.call(loc_instance,input)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
//
// TODO: Consider removing this method, instead using something like the
// following:
// var loc = new locCallClass();
// loc.testCallNumbers.sort(function(a,b) {return loc.localeCompare(a,b)});
locCallClass.prototype.sortCallNumbers = function (callnumbers) {
var sorted = callnumbers.sort(function (a,b) {
return this.localeCompare(a,b);
});
return sorted;
}
// locCallClass.isBetween(a,b,c)
// returns true if a <= c <= b
locCallClass.prototype.isBetween = function (a,b,c) {
//this.localeCompare(a, b) <= 0 if in sort order
return ( (this.localeCompare(a,c) <= 0 && this.localeCompare(c,b) <=0) ? true : false );
}
// locCallClass.padZed()
// returns portion of the call number padded out to enable sorting.
locCallClass.prototype.padZed = function (value, before_first_cutter) {
//pad value with zeros - return value will have a length of 9
// The exceptions here are going to be if the number is before the
// cutter, then we should treat it as two different parts: whole
// number, and decimal portion.
if(value) {
if(before_first_cutter && !isNaN(value) ) {
//this is a number before the first cutter, split it, and then
// pad each of the parts
var int_portion = Math.floor(value).toString();
var dec_portion = (value % 1).toFixed(3).toString().substr(2,3);
var pad_zeros = "";
for (var i=0; i<(9 - int_portion.length); i++) {
pad_zeros = pad_zeros + "0";
}
return_value = pad_zeros + int_portion;
var pad_zeros = "";
for (var i=0; i<(9 - dec_portion.length); i++) {
pad_zeros = pad_zeros + "0";
}
return_value += "." + dec_portion + pad_zeros;
return return_value;
} // end if
else {
//pad the value to the right
var pad_zeros = "";
for (var i=0; i<(9 - value.length); i++) {
pad_zeros = pad_zeros + "0";
}
return value + pad_zeros;
}
}
else {
return "000000000";
}
}
/* test script */
var loc = new locCallClass();
var output1 = document.getElementById("output1");
// define, show and then sort the first set
var set1 = ["LC 346 .65 .B29",
"LC 346 .M634",
"HX 754 .5 .C15",
"HX 754 .C7723"
];
output1.innerHTML = "<b>pre-sort</b><br>";
for(var i=0; i<set1.length; i++) {
output1.innerHTML += set1[i] + "<br>";
}
//sort with the specialized sort method from our class, "loc"
var sorted1 = set1.sort(function(a,b) {
return loc.localeCompare(a,b);
});
output1.innerHTML += "<hr><b>sorted</b><br>";
for(var i=0; i<sorted1.length; i++) {
output1.innerHTML += sorted1[i] + "<br>";
}
// now test the built in method to sort call numbers
// which doesn't work for some reason
var alt_sorted = loc.sortCallNumbers(set1);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>locCallClass test sorting of call numbers</title>
</head>
<body style="font-family:monospace;">
<h3>test sorting of call numbers</h3>
<div id="output1"></div>
</body>
Thanks in advance to anyone who could help me out!
Cache this:
locCallClass.prototype.sortCallNumbers = function(callnumbers) {
var self = this;
var sorted = callnumbers.sort(function(a, b) {
return self.localeCompare(a, b);
});
return sorted;
}
Or hard bind the sort's callback function to this:
locCallClass.prototype.sortCallNumbers = function(callnumbers) {
var sorted = callnumbers.sort(function(a, b) {
return this.localeCompare(a, b);
}.bind(this));
return sorted;
}

Categories

Resources