I am writing an application which needs a bar plot, whose binning, in the x axis, is relative to the order of magnitude of the average time-distance between the events that are displayed.
For example, the average time distance in the events that I want to display might be 73 seconds. This means that the size of the bins relative to the bars that are displayed should be a minute.
Other examples of duration in seconds of the input interval and inferred order of magnitude are:
3 seconds: one second
327 seconds: one minute (or, possibly, 5 minutes)
5298 seconds: one hour
7625 seconds: (possibly) two hours
10234 seconds: one day
4023860 seconds: one month
and so on. I tried to look into the moment.js library and I found out that they implemented something very interesting: the fromNow method.
Please note that I am also interested in the number of seconds of each order of magnitude that has been previously illustrated.
I know that I could implement it myself with a cascade of tests (divisions with rest), but I would like to reinvent the (possibly buggy) wheel.
Finally, I implemented a solution in the following simple function:
function compute_magnitude_interval(average_interval) {
var minute = 60;
var hour = minute*60;
var day = hour*24;
var possible_intervals = [
1, 2, 5, 10, 20, 30,
minute, minute*2, minute*5, minute*10, minute*20, minute*30,
hour, hour*2, hour*5, hour*10, hour*12,
day, day*2, day*5, day*10, day*15
].reverse();
for(var i in possible_intervals){
var seconds = possible_intervals[i];
if (Math.floor(average_interval/seconds) > 0) {
return seconds;
}
};
}
Related
I am a bit new to spreadsheet scripting and I have a project that I am trying to accomplish.
Overview:
I am making spreadsheet that records reading progress.
The first column (A) is the date.
Second Column (B) is the required time to be spent reading.
Third column (C) is the amount on minutes spent reading.
Fourth column (D)is the bonus minutes which are described below.
Fifth column (E) is the result of (Effort+Bonus-Requirement)
If you spend over 30 minutes (let's say 30+x minutes) , the extra is used to add 1 minute for the next x days. So if you spent 37 minutes reading the next 7 days you will get a bonus of 1 minute so you need to spend 29 minutes instead of the usual 30 for the next 7 days.
However the bonus can accumulate and stack. if you spend 37 minutes on the first day, the next day you are required to do 29 minutes but if instead you did a total of 35 minutes then the next 5 days (after the 2nd day) will get another 1 bonus minute so the 3rd day would have a total of 2 minutes bonus. So the bigger picture in this example will be that the 2nd day gets +1, 3rd to 7th will get 2 minutes and the 8th day will get 1 min (from the first day not the 2nd).
Other criteria to address:
The maximum bonus to calculate is uncapped, so if the user was required to spend 30 minutes reading and they spent 150 minutes the bonus of 120 minutes would be added as 1 minute each day for the next 120 days.
The bonus is stackable with no limit, if the total exceeds the required daily limits it would be treated normally, you can reach and exceed the required 30 minutes through bonus alone and it would be treated normally. If you have a stacked bonus of 35 minutes at one day it would be treated as "goal achieved + 5 minutes bonus" even before such day arrives. yet there is nothing to prevent over achieving on that day to increase the bonus.
My effort
I have done some scripting using google sheets javascript but the issue is that I had to create a function that I need to use in every cell since from what I've understood scripts can not use setValue() on cells other than the ones its called in.
Also the way functions work is that they are only called at the moment you set the cell to "=myFunction()" and do not change once set even if you change the cells used as inputs.
Some Code
This is the function that I created, it works fine however I need it to be persistent and do the calculation in real time.
function c() {
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var thisCell = activeSheet.getCurrentCell();
var thisColumn = thisCell.getColumn();
var thisRow = thisCell.getRow();
var finalValue = 0;
for (var i = 2; i< thisRow; i++) {
//if the value in cell Ei is greater than the difference between (thisRow-i) then increment cell
if (activeSheet.getRange("E"+i).getValue() >= (thisRow-i)){
Logger.log(activeSheet.getRange("E"+i).getValue());
finalValue++;
}
}
return (finalValue);
Logger.log("final "+finalValue);
}
I hope my problem is clear enough for you.
I’m trying to make one of my variable an initial starting time and have the output be an addition to that time based on a number of parameters.
For instance;
I start subtract x from y and get z. Then I take z and divide it from x getting the % of that difference to the original number. Then based on that percentage every 5% represents 5mins. So if i start at 10:00am and the price of hotdog is $10 and if drops to $8 (20% drop) I want to show a 20min addition to 10:00am.
My issue is that when I get to the addition to the original time it goes past 60 min. So instead of it going from 900 to 1010 it goes to 970.
How do I make it count from 60’s like time. Please help. Thanks!
Store everything as minutes (or seconds, days - whatever is most suitable) and convert the values whenever needed:
function convertToHourString (minutes) {
return Math.floor( minutes / 60 ) + ':' + minutes % 60
}
convertToHourString(10); // 0:10
convertToHourString(70); // 1:10
I'm making a web based code generator which gives doctor's approval to prescribe certain antibiotics, it works by adding the number of the day of the week (i.e. 0 for Sunday, 1 for Monday) with the getDay() function) and a counter which increases with each day (i.e. 232 today, then 233 tomorrow etc...)(using the Math.floor(now/8.64e7) to make a numerical code (like 2232 which looks meaningless to a person, but which a validator can tell is a code generated on Tuesday day 232 (2232 would be OK, but 2231 or 2233 would not be accepted).
Here is the script:
<script>
var getcode = function () {
var now = new Date();
var fullDaysSinceEpoch = Math.floor(now / 8.64e7) - 16550;
return '' + now.getDay() + fullDaysSinceEpoch;
}
</script>
I want to do it this way rather than make a link between the two programs (because the approval for that would be a nightmare).
My problem is that once the second counter reaches 999 it will continue to become 1000 then 1001 etc... which will go above the max characters allowed in the validator.
I can keep updating the program and subtracting from the counter, but It is a bit dodgy.
Is there an easier way to construct this counter so it increments every day but only takes the right most 3 numbers from "Math.floor(now / 8.64e7) - 16550" after is reaches 1000? Something like the RIGHT function in excel?
I have thought about using %10, but I will just run into the same problem when the counter reaches 1000 again.
How do I calculate the difference in minutes given two strings. For example say I have
11:00
11:30
But of course the second string could be 12:11 so I can't subtract just the minutes.
first use javascript to convert the strings to time, then subtract, then convert back to strings
like this:
x = new Date("1/1/01 11:00")
y = new Date("1/1/01 11:30")
// now y-x has difference in milliseconds
// (y-x)/1000 is difference in seconds, etc
The data 1/1/01 is just being used as a dummy value, but the one thing you might have to worry about is are the times on different days, if so you will have to use 1/2/01 for the second time. Unless of course you always know the times are in the same day, but if they can cross "midnight" then you have to adjust for that.
You may want to use http://momentjs.com/ which will take care of the details for you.
When looking for getting metrics such as date , hour , minutes, seconds from the date difference, it's a lot easier to use basic notations as listed here
var x = new Date(new Date().getTime() + 11.5*60*60000); // adds 11 hours - 30 minutes
var y = new Date(new Date().getTime() + 11*60*60000); // adds 11 hours
alert(x.getMinutes() - y.getMinutes()); // gives the difference = 30
Here's an example : https://jsfiddle.net/DinoMyte/157knmgn/
I am trying to create a count up timer based on an object's modified time (formatted like: 2014-02-19T18:49:15) and comparing it to the current time using Moment.js. But when it reaches 60 minutes, it restarts back to 0. I think this is because I am comparing just the minutes here or at least using math to change the milliseconds to a whole number format? I am not quite sure, I got excited when I got the minutes to format correctly. The difference in minutes is all I want to return. So for example after an hour and a half I want a returned value of '90'.
function() {
return function(entry) {
var elpTime = Math.floor(((Date.parse(moment()) - Date.parse(entry.arrival_time)) / (1000*60)) % 60);
return elpTime;
}
};
Here is an example of the object.
{
patient_id: 198,
arrival_time: "2014-02-19T18:49:15",
last_modified: "2014-02-19T18:49:15"
}
I know I am missing something probably obvious. But any help is appreciated. Thanks!
(Should be noted that I am using this as apart of a filter function in Angular.js. But I stripped it out since I didn't think it was nessacary)
Since you are using Moment.js you can use the built in diff function to return the time period between two moments.
function() {
return function(entry) {
var elpTime = moment(entry.arrival_time).diff(moment(),'minutes');
return elpTime;
}
};
From the documentation:
The supported measurements are years, months, weeks, days, hours, minutes, and seconds.
By default, moment#diff will return number rounded down. If you want the floating point number, pass true as the third argument. Before 2.0.0, moment#diff returned rounded number, not a rounded down number.
Example from documentation:
var a = moment([2008, 6]);
var b = moment([2007, 0]);
a.diff(b, 'years'); // 1
a.diff(b, 'years', true); // 1.5