Using exponents in Gravity Forms calculations - javascript

Firstly, I am by no means versed in JavaScript or jQuery. That being said, I'm using Gravity Forms to create a savings calculator that contains exponents. I found THIS thread, but am confused as to how it actually works in calculating an exponential value.
Here's my setup:
I have 3 user-defined fields:
Principal amount
Interest rate
Number of monthly payments
The actual calculations are hidden from the user. There are two formulas calculating at once here. The first is the 'User calculations' working to find a 'Total Interest'. The second is a 'Fixed calculations' with a fixed interest rate of 1.95%, instead of the user-defined field, working towards the same goal. The fixed rate aside, both formulas are identical, and the results of which are incorporated into a final formula free of exponents. Thankfully. Here are the first three 'Number' fields (name & formula) after the user input:
'CALC'<br>
( {Interest rate::2} / 12 ) / 100
'MP exponent'
( 1 + {CALC:8} ) <---This is the formula that requires an exponent equal to the user-defined "Number of monthly payments" field.
'MP numerator'
{CALC:8} * {Principal amount::1} * {MP exponent:10}
The formula goes on and incorporates the MP exponent field multiple times. Given my case here, can I even use the aforementioned script (unedited from its source post):
<script>
gform.addFilter( 'gform_calculation_result', function(result, formulaField, formId, calcObj ){
if ( formulaField.field_id == "2" ) {
var field_five = jQuery('#input_2_5').val();
result = field_five * 12;
}
return result;
});
</script>
...for my calculation? I'm not at all sure how to specify something like this in 4 separate fields... I understand this may not be possible with Gravity Forms - or certainly not simple - so I greatly appreciate any help the community may offer me.

The javascript snippet you used above will change what the user sees, but it will not change the saved form data, per say. You instead need to add a PHP filter to the functions.php file of your theme.
add_filter( 'gform_calculation_result', function ( $result, $formula, $field, $form, $entry ) {
if ( $form['id'] == 1 && $field['id'] == 10 ) {
$base = 1 + (float) rgar( $entry, '8' ); // '8' should be field ID of Calc
$exponent = (float) rgar( $entry, '1' ); // '1' should be field ID of Number of monthly payments
$result = pow( $base, $exponent );
}
return $result;
}, 10, 5 );
One warning: this will not change anything that the user "sees" when filling out the form. It will only change the final calculation after the user hits the submit button.
It would also be cleaner to do all of your calculations in a filter like this rather than using hidden form data.

Related

How to create a quantity discount formula using Math JavaScript?

I am learning JavaScript for WordPress Websites, but I am only asked for the formula without including HTML or CSS fields, I just need the JS.
I need to create a formula to take a quantity [quantity] multiply it by the base price [base price] and then subtract the [discount] based on the following list they give me.
If you buy:
1 = 4
2 to 10 = 3.4
11 to 50 = 3.0
From 51 to 100 = 2.75
From 101 to 1000 = 2.50
This is the code I have been able to create but it only gives me the price until it reaches 10.
It is an exercise or an example, because I am learning how to create the code... the goal is to make the list above.
(function(){
if([field id="quantity"]<=10)
{
return 4;
}
else if(10>[field id="quantity"] && [field id="quantity"]<=20)
{
return 3.5;
}
else
{
return 0;
}
})() * [field id="quantity"]
Here is an example I made to give you an idea of the structure:
Loan Calculator Form | Monthly Payment:
[field id="amount"]*([field id="annual_interest"]/1200)/(1-(Math.pow(1/(1+([field id="annual_interest"]/1200)),([field id="repayment_period"]*12))))
List of available static mathematical methods I was given to use
Url of this list: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math?retiredLocale=vi#static_methods
I would like you to show me some examples of quantity discounts to learn how to handle the tools involved in performing this equation.

Javascript Taxi fare

I got the function setup and variables taken care. I am trying to calculate taxi fare per start zone, end zone and elapsed time.
Here what I have so far but it is not calculating well.
It keeps giving me $5
if( startZone == 1 && endZone == 1 ){
totalTaxiFare = baseCharge;
if( timeCovered > 0 && timeCovered <= 4 ){
baseCharge = 5.00;
charge = (0.75/timeCovered)*timeCovered;
totalTaxiFare = baseCharge + charge;
}
}
if( startZone == 1 && endZone == 2 ){
totalTaxiFare = baseCharge;
if( timeCovered > 4 && timeCovered <= 10 ){
baseCharge = 7.00;
charge =( 3.00 + (0.50 * ( timeCovered - 4 ) * ( 0.75 / timeCovered ) * timeCovered ) );
totalTaxiFare = baseCharge + charge;
}
}
document.writeln("<p> The total taxi fare is $" + totalTaxiFare + "</p>");
Ok, I don't know if I got the math correctly since I had to guess what the rates were by looking at the pattern. There's that zone thing I'm not sure what that's about, but by looking in the original code, I think it's a conditional to change the calculations for working 2 shifts?
Anyways, you should always use var for your variables, otherwise all of that data is floating around in globalspace. You had this expression: totalTaxiFare = baseCharge; floating around being exposed. So it looks as if ultimately your totalTaxiFare was constantly being changed to baseCharge which is at a constant value of 5.00. If you used var and kept the majority of your variables local, you'd probably get different results, but with the expressions you had those results wouldn't be accurate.
I'm definitely not a math wizard (lazy in high school), but is this an expression that would yield an appropriate result for cab fare?: `
(0.75/timeCovered)*timeCovered;
Ok, parenthesis first and we'll say 3 minutes? 3 hours? 3 time units I guess.
(.75/3)*3 which is (.25)*3 which is .75 so that was changed into a more appropriate expression:
(.75)*timeCovered;
So that would be
(.75)*3 = 2.25
Sorry if I sound harsh, I think that if you want to program, you should pay special attention to your math. Even if your syntax is flawless, it won't help if the math is even a little off.
Here's a DEMO, like I said before, I guessed as to how the expressions are done because you didn't provide the complete rates or given any details on time. It looks like it's working like it should give it a try. Good luck, sir ;-)

Is there a way to measure string similarity in Google BigQuery

I'm wondering if anyone knows of a way to measure string similarity in BigQuery.
Seems like would be a neat function to have.
My case is i need to compare the similarity of two urls as want to be fairly sure they refer to the same article.
I can find examples using javascript so maybe a UDF is the way to go but i've not used UDF's at all (or javascript for that matter :) )
Just wondering if there may be a way using existing regex functions or if anyone might be able to get me started with porting the javascript example into a UDF.
Any help much appreciated, thanks
EDIT: Adding some example code
So if i have a UDF defined as:
// distance function
function levenshteinDistance (row, emit) {
//if (row.inputA.length <= 0 ) {var myresult = row.inputB.length};
if (typeof row.inputA === 'undefined') {var myresult = 1};
if (typeof row.inputB === 'undefined') {var myresult = 1};
//if (row.inputB.length <= 0 ) {var myresult = row.inputA.length};
var myresult = Math.min(
levenshteinDistance(row.inputA.substr(1), row.inputB) + 1,
levenshteinDistance(row.inputB.substr(1), row.inputA) + 1,
levenshteinDistance(row.inputA.substr(1), row.inputB.substr(1)) + (row.inputA[0] !== row.inputB[0] ? 1 : 0)
) + 1;
emit({outputA: myresult})
}
bigquery.defineFunction(
'levenshteinDistance', // Name of the function exported to SQL
['inputA', 'inputB'], // Names of input columns
[{'name': 'outputA', 'type': 'integer'}], // Output schema
levenshteinDistance // Reference to JavaScript UDF
);
// make a test function to test individual parts
function test(row, emit) {
if (row.inputA.length <= 0) { var x = row.inputB.length} else { var x = row.inputA.length};
emit({outputA: x});
}
bigquery.defineFunction(
'test', // Name of the function exported to SQL
['inputA', 'inputB'], // Names of input columns
[{'name': 'outputA', 'type': 'integer'}], // Output schema
test // Reference to JavaScript UDF
);
Any i try test with a query such as:
SELECT outputA FROM (levenshteinDistance(SELECT "abc" AS inputA, "abd" AS inputB))
I get error:
Error: TypeError: Cannot read property 'substr' of undefined at line 11, columns 38-39
Error Location: User-defined function
It seems like maybe row.inputA is not a string perhaps or for some reason string functions not able to work on it. Not sure if this is a type issue or something funny about what utils the UDF is able to use by default.
Again any help much appreciated, thanks.
Ready to use shared UDFs - Levenshtein distance:
SELECT fhoffa.x.levenshtein('felipe', 'hoffa')
, fhoffa.x.levenshtein('googgle', 'goggles')
, fhoffa.x.levenshtein('is this the', 'Is This The')
6 2 0
Soundex:
SELECT fhoffa.x.soundex('felipe')
, fhoffa.x.soundex('googgle')
, fhoffa.x.soundex('guugle')
F410 G240 G240
Fuzzy choose one:
SELECT fhoffa.x.fuzzy_extract_one('jony'
, (SELECT ARRAY_AGG(name)
FROM `fh-bigquery.popular_names.gender_probabilities`)
#, ['john', 'johnny', 'jonathan', 'jonas']
)
johnny
How-to:
https://medium.com/#hoffa/new-in-bigquery-persistent-udfs-c9ea4100fd83
If you're familiar with Python, you can use the functions defined by fuzzywuzzy in BigQuery using external libraries loaded from GCS.
Steps:
Download the javascript version of fuzzywuzzy (fuzzball)
Take the compiled file of the library: dist/fuzzball.umd.min.js and rename it to a clearer name (like fuzzball)
Upload it to a google cloud storage bucket
Create a temp function to use the lib in your query (set the path in OPTIONS to the relevant path)
CREATE TEMP FUNCTION token_set_ratio(a STRING, b STRING)
RETURNS FLOAT64
LANGUAGE js AS """
return fuzzball.token_set_ratio(a, b);
"""
OPTIONS (
library="gs://my-bucket/fuzzball.js");
with data as (select "my_test_string" as a, "my_other_string" as b)
SELECT a, b, token_set_ratio(a, b) from data
Levenshtein via JS would be the way to go. You can use the algorithm to get absolute string distance, or convert it to a percentage similarity by simply calculating abs(strlen - distance / strlen).
The easiest way to implement this would be to define a Levenshtein UDF that takes two inputs, a and b, and calculates the distance between them. The function could return a, b, and the distance.
To invoke it, you'd then pass in the two URLs as columns aliased to 'a' and 'b':
SELECT a, b, distance
FROM
Levenshtein(
SELECT
some_url AS a, other_url AS b
FROM
your_table
)
Below is quite simpler version for Hamming Distance by using WITH OFFSET instead of ROW_NUMBER() OVER()
#standardSQL
WITH Input AS (
SELECT 'abcdef' AS strings UNION ALL
SELECT 'defdef' UNION ALL
SELECT '1bcdef' UNION ALL
SELECT '1bcde4' UNION ALL
SELECT '123de4' UNION ALL
SELECT 'abc123'
)
SELECT 'abcdef' AS target, strings,
(SELECT COUNT(1)
FROM UNNEST(SPLIT('abcdef', '')) a WITH OFFSET x
JOIN UNNEST(SPLIT(strings, '')) b WITH OFFSET y
ON x = y AND a != b) hamming_distance
FROM Input
I did it like this:
CREATE TEMP FUNCTION trigram_similarity(a STRING, b STRING) AS (
(
WITH a_trigrams AS (
SELECT
DISTINCT tri_a
FROM
unnest(ML.NGRAMS(SPLIT(LOWER(a), ''), [3,3])) AS tri_a
),
b_trigrams AS (
SELECT
DISTINCT tri_b
FROM
unnest(ML.NGRAMS(SPLIT(LOWER(b), ''), [3,3])) AS tri_b
)
SELECT
COUNTIF(tri_b IS NOT NULL) / COUNT(*)
FROM
a_trigrams
LEFT JOIN b_trigrams ON tri_a = tri_b
)
);
Here is a comparison to Postgres's pg_trgm:
select trigram_similarity('saemus', 'seamus');
-- 0.25 vs. pg_trgm 0.272727
select trigram_similarity('shamus', 'seamus');
-- 0.5 vs. pg_trgm 0.4
I gave the same answer on How to perform trigram operations in Google BigQuery?
I couldn't find a direct answer to this, so I propose this solution, in standard SQL
#standardSQL
CREATE TEMP FUNCTION HammingDistance(a STRING, b STRING) AS (
(
SELECT
SUM(counter) AS diff
FROM (
SELECT
CASE
WHEN X.value != Y.value THEN 1
ELSE 0
END AS counter
FROM (
SELECT
value,
ROW_NUMBER() OVER() AS row
FROM
UNNEST(SPLIT(a, "")) AS value ) X
JOIN (
SELECT
value,
ROW_NUMBER() OVER() AS row
FROM
UNNEST(SPLIT(b, "")) AS value ) Y
ON
X.row = Y.row )
)
);
WITH Input AS (
SELECT 'abcdef' AS strings UNION ALL
SELECT 'defdef' UNION ALL
SELECT '1bcdef' UNION ALL
SELECT '1bcde4' UNION ALL
SELECT '123de4' UNION ALL
SELECT 'abc123'
)
SELECT strings, 'abcdef' as target, HammingDistance('abcdef', strings) as hamming_distance
FROM Input;
Compared to other solutions (like this one), it takes two strings (of the same length, following the definition for hamming distance) and outputs the expected distance.
bigquery similarity standardsql hammingdistance
While I was looking for the answer Felipe above, I worked on my own query and ended up with two versions, one which I called string approximation and another string resemblance.
The first is looking at the shortest distance between letters of source string and test string and returns a score between 0 and 1 where 1 is a complete match. It will always score based on the longest string of the two. It turns out to return similar results to the Levensthein distance.
#standardSql
CREATE OR REPLACE FUNCTION `myproject.func.stringApproximation`(sourceString STRING, testString STRING) AS (
(select avg(best_result) from (
select if(length(testString)<length(sourceString), sourceoffset, testoffset) as ref,
case
when min(result) is null then 0
else 1 / (min(result) + 1)
end as best_result,
from (
select *,
if(source = test, abs(sourceoffset - (testoffset)),
greatest(length(testString),length(sourceString))) as result
from unnest(split(lower(sourceString),'')) as source with offset sourceoffset
cross join
(select *
from unnest(split(lower(testString),'')) as test with offset as testoffset)
) as results
group by ref
)
)
);
The second is a variation of the first, where it will look at sequences of matching distances, so that a character matching at equal distance from the character preceding or following it will count as one point. This works quite well, better than string approximation but not quite as well as I would like to (see example output below).
#standarSql
CREATE OR REPLACE FUNCTION `myproject.func.stringResemblance`(sourceString STRING, testString STRING) AS (
(
select avg(sequence)
from (
select ref,
if(array_length(array(select * from comparison.collection intersect distinct
(select * from comparison.before))) > 0
or array_length(array(select * from comparison.collection intersect distinct
(select * from comparison.after))) > 0
, 1, 0) as sequence
from (
select ref,
collection,
lag(collection) over (order by ref) as before,
lead(collection) over (order by ref) as after
from (
select if(length(testString) < length(sourceString), sourceoffset, testoffset) as ref,
array_agg(result ignore nulls) as collection
from (
select *,
if(source = test, abs(sourceoffset - (testoffset)), null) as result
from unnest(split(lower(sourceString),'')) as source with offset sourceoffset
cross join
(select *
from unnest(split(lower(testString),'')) as test with offset as testoffset)
) as results
group by ref
)
) as comparison
)
)
);
Now here is a sample of result:
#standardSQL
with test_subjects as (
select 'benji' as name union all
select 'benjamin' union all
select 'benjamin alan artis' union all
select 'ben artis' union all
select 'artis benjamin'
)
select name, quick.stringApproximation('benjamin artis', name) as approxiamtion, quick.stringResemblance('benjamin artis', name) as resemblance
from test_subjects
order by resemblance desc
This returns
+---------------------+--------------------+--------------------+
| name | approximation | resemblance |
+---------------------+--------------------+--------------------+
| artis benjamin | 0.2653061224489796 | 0.8947368421052629 |
+---------------------+--------------------+--------------------+
| benjamin alan artis | 0.6078947368421053 | 0.8947368421052629 |
+---------------------+--------------------+--------------------+
| ben artis | 0.4142857142857142 | 0.7142857142857143 |
+---------------------+--------------------+--------------------+
| benjamin | 0.6125850340136053 | 0.5714285714285714 |
+---------------------+--------------------+--------------------+
| benji | 0.36269841269841263| 0.28571428571428575|
+----------------------------------------------------------------
Edited: updated the resemblance algorithm to improve results.
Try Flookup for Google Sheets... it's definitely faster than Levenshtein distance and it calculates percentage similarities right out of the box.
One Flookup function you might find useful is this:
FUZZYMATCH (string1, string2)
Parameter Details
string1: compares to string2.
string2: compares to string1.
The percentage similarity is then calculated based on these comparisons. Both parameters can be ranges.
I'm currently trying to optimise it for large data sets so you feedback would be very welcome.
Edit: I'm the creator of Flookup.

Not getting the result I expected from this calculation

I'm using a form to help determine the strength for an action in a game I'm making a plugin for. The player fills in some form fields and selects 1 value from a drop down and then clicks calculate. The result if I use an actual calculator is what I expected but, the result from my javascript function is not. I've been wrestling with it for a while but, can't seem to work out why it's failing to calculate correctly. Below is the function:
function wgtcalc() {
document.wgtcalc.strDSAtk.value =
(document.wgtcalc.strBaseSpeed.value * document.wgtcalc.strAltitude1.value) +
(document.wgtcalc.strBaseSpeed.value * document.wgtcalc.strAltitude2.value) +
(document.wgtcalc.strDistance.value / document.wgtcalc.strFullSwing.value);
}
Try:
function wgtcalc() {
document.wgtcalc.strDSAtk.value =
( Number(document.wgtcalc.strBaseSpeed.value) *
Number (document.wgtcalc.strAltitude1.value)) +
( Number (document.wgtcalc.strBaseSpeed.value) *
Number (document.wgtcalc.strAltitude2.value)) +
( Number (document.wgtcalc.strDistance.value) /
Number (document.wgtcalc.strFullSwing.value) );
}
As pc-shooter pointed out you're doing a calculation on strings.

In an HTML table, can a numeric value be expressed with comma formatting?

In Visual FoxPro, a number can be formatted in a textbox or grid and still be seen by the program as just a number, even though it is shown with commas and period format.
Presently I'm inserting data into a DataTable Jquery as follows:
oTable.fnAddData( ["Bogus data","1,541,512.52","12.5%","0","0","0"]);
But I would like to be entering the data as follows and yet show it with the commas for clarity:
oTable.fnAddData( ["Bogus data",1541512.52,"12.5%","0","0","0"]);
The reason is that when you sort the rows on this column, the character string in the first example will produce a mess. the numbers, hopefully will produce a well ordered list.
If you have any other suggestions on how to fix the sorting of the character number column please suggest it...
TIA
Dennis
A sort plugin for formatted numbers is detailed here, by the author of DataTables:
http://www.datatables.net/plug-ins/sorting
See "formatted numbers":
This plug-in will provide numeric sorting for numeric columns which have extra formatting, such as thousands seperators, currency symobols or any other non-numeric data.
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"formatted-num-pre": function ( a ) {
a = (a==="-") ? 0 : a.replace( /[^\d\-\.]/g, "" );
return parseFloat( a );
},
"formatted-num-asc": function ( a, b ) {
return a - b;
},
"formatted-num-desc": function ( a, b ) {
return b - a;
}
} );
Here's a quick and dirty way to do it;
var number = 1541512.52;
var nicelyformattedNumber = number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
oTable.fnAddData( ["Bogus data", nicelyformattedNumber, "12.5%","0","0","0"]);
Source

Categories

Resources