I'm trying to solve an interval calendar problem.
Given busy slots as a data-set in a person's outlook calendar and
the time required for a meeting (eg: 45 mins) write a method to find
an open available slot for scheduling a meeting.
Input:
per1: (1,5) (10, 14) (19,20) (27,30)
per2: (3,5) (12,15) (18,21) (23,24)
Output: (6,9) (16,17) (22,22) (25,26)
I'm trying to see how I can solve this problem using:
A) Vanilla JavaScript (ES5 / ES6)
B) Using Data-structure like Interval trees etc.
I'm thinking maybe combine both of the calendar's and sort them in ascending order of start time and then start looking for a slot? Please correct me if I'm wrong.
Need your advice/suggestions on the same.
Given that it's a tuple of absolute hours and only two people involved, you could maintain a state array of length 24. Run a loop to mark all the hours where p1 and p2 are busy. You will be left with an array of hours where both of them will not be busy and then extract the absolute gaps between such intervals. Here is a fiddle (https://jsfiddle.net/r9nq63tk/1/) which handles the marking of the busy hours.
let freeHours = new Array(24);
// Mark the busy hours
let intervals = [];
for(let hours = 0; hours < 24; hours++) {
// Find the ranges where the hours have not been marked and push it to intervals
}
Related
I am (VERY) new to Apps Script and JS generally. I am trying to write a script that will automatically tally the difference between student entry time and start time of a course to deliver total minutes missed.
I have been able to get a function working that can do this for a single cell value, but am having trouble iterating it across a range. Doubtless this is due to a fundamental misunderstanding I have about the for loop I am using, but I am not sure where to look for more detailed information.
Any and all advice is appreciated. Please keep in mind my extreme "beginner status".
I have tried declaring a blank variable and adding multiple results of previously written single-cell functions to that total, but it is returning 0 regardless of given information.
I am including all three of the functions below, the idea is that each will do one part of the overall task.
function LATENESS (entry,start) {
return (entry-start)/60000
}
function MISSEDMINUTES(studenttime,starttime) {
const time = studenttime;
const begin = starttime;
if (time=="Present") {
return 0
} else if (time=="Absent") {
return 90
} else {
return LATENESS(time,begin)
}
}
function TOTALMISSED(range,begintime) {
var total = 0
for (let i = 0; i < range.length; i++) {
total = total + MISSEDMINUTES(i,begintime)
}
}```
If you slightly tweak your layout to have the 'missing minutes' column immediately adjacent to the column of names, you can have a single formula which will calculate the missing minutes for any number of students over any number of days:
Name
*
2/6
2/7
2/8
2/9
John Smith
-
Present
Present
Absent
10:06
Lucy Jenkins
-
Absent
Absent
Absent
Absent
Darren Polter
-
Present
Present
Present
10:01
With 'Name' present in A1, add the following to cell B1 (where I've marked an asterisk):
={"mins missed";
byrow(map(
C2:index(C2:ZZZ,counta(A2:A),counta(C1:1)),
lambda(x,switch(x,"Present",0,"Absent",90,,0,1440*(x-timevalue("10:00"))))),
lambda(row,sum(row)))}
We are MAPping a minute value onto each entry in the table (where 'Present'=0, 'Absent'=90 & a time entry = the number of minutes difference between then and 10am), then summing BYROW.
Updated
Based on the example, you could probably have a formula like the below one to conduct your summation:
=Sum(ARRAYFORMULA(if(B2:E2="Absent",90,if(isnumber(B2:E2),(B2:E2-$K$1)*60*24,0))))
Note that k1 has the start time of 10:00. Same sample sheet has working example.
Original Answer
I'm pretty sure you could do what you want with regular sheets formulas. Here'a sample sheet that shows how to get the difference in two times in minutes and seconds... Along with accounting for absent.
Here's the formula used that will update with new entries.
=Filter({if(B2:B="Absent",90*60,Round((C2:C-B2:B)*3600*24,0)),if(B2:B="Absent",90,Round((C2:C-B2:B)*3600*24/60,1))},(B2:B<>""))
This example might not solve all your issues, but from what I'm seeing, there's no need to be using an app script. If this doesn't cover it, post some sample data using Mark down table.
I am using a PIR sensor to detect motion within my environment. When there is motion the PIR sensor sends a value of 1 to the console. As soon as it detects no motion it goes to 0 numerous times via a setInterval() every second. Now at that point in time I want to detect how long 0 has been 0 and then at 10 minutes do something. I was thinking of doing a new Date().getMinutes(); once at start of motion and then another one when motion stopped and comparing those two. Am I on the right track?
I ended up adding a var i = 0; outside of the setInterval() and within the if (myDigitalValue === 0) loop I kept i++ until it hit the amount of seconds I was looking for and when it equaled that I ran a method.
(new Date()).getMinutes() will return the "minutes" part of the current time, i.e. where the minute hand would be pointing on a clock. What you probably want is the absolute time that has passed since a particular point. Fortunately there's an easy way to determine time difference with the a Date object (or two of them):
begin = new Date();
. . . time passes . . .
end = new Date();
timeDiffInMilliseconds = end - begin;
In other words, when you subtract one Date object from another, you get the time difference in milliseconds (hooray for polymorphic operators).
One advantage this would have is that if you wanted to change the frequency of your test or the length of time, you would just change the relevant one. With the loop as you describe, the two are tied together unnecessarily, which can be more error prone.
I am asking help for a problem which I am not able to solve despite every effort. I am trying to make a counter. This counter is to be placed in a div under the available items on a webpage. This counter should be able to change its value at predefined values and intervals, for example, the value starts at 5,000 at then decreases by 1 after 2 seconds and then by 4 after next 5 seconds and then by 3 after next 2 seconds and then the process repeats (decreases by 1 after 2 seconds...) three or four sets of variation will be enough.
The value shown by the counter must not be affected by the number of page loads or simultaneous users, also it should remain if the user sees the page in two different browsers, it must only be shown as described above.
This counter must be capable of changing its value without needing the user to refresh the page.
Most straightforward solution as it appears to me would be to make the timer relative to absolute time.
This means you take the time passed since an arbitrary point in time you define as the start, e.g. right now which is var start = Date("Thu Jun 04 2015 01:46:44 GMT+0200 (CEST)") here. You can now subtract start from the current time to learn how much time has passed:
var passedSeconds = (new Date() - start) / 1000;
We divide by 1000 since JS calculates with miliseconds by default.
To update the timer, do a simple
setInterval(function() {
var passedSeconds = (new Date() - start) / 1000;
var value = doCalculationForSeconds(passedSeconds);
document.getElementById('myDisplay)'.textContent = value;
}, 1000);
which calls this method every second.
Lastly, you need to figure out a good way to calculate the progress. You could either run your formula in a big loop for all of passedSeconds. Or you evaluate if you can reduce it to a single calculation step. Will depend on the exact changes in value you'll have in your final version.
I'm writing a system to handle messaging.
One of the options of a user is DND (Do Not Disturb) where a user can define a time range where he should not be alerted (such as 22:00 - 08:00).
When I perform a query on users, I wish to filter out the users which currently are on DND.
In each user's document, I define a field to hold the time in seconds:
{dnd: {start: 22*3600, end: 8*3600}}
I'm not sure how to perform the query itself (the following sample will not work due to overlapping midnight)
var current; // holds current time in seconds
db.user.find({$or:[{"dnd.start":{$gt:current}},{"dnd.end":{$lt:current}}]});
A different approach to this might be to store a "blacklist" of times as an array and query that the current time is not one of those elements. It depends on how granular you need this to be. Hours or half hours may be reasonable, as far out as per minute is not too bad.
So to generate the "blacklist" per minute you could do, as JavaScript code but the principles are easy to convert:
var start = 22 * 60;
var end = 8 * 60;
var dnd = [start];
do {
start++;
if ( start == 1440 )
start = 0;
dnd.push( start );
} while ( start != end );
db.user.update({},{ "$set": { "dnd": dnd } },true)
Essentially setting the "blacklist" against the user record.
Then when you query for say 1:30 in the morning, or the 90th minute you would do:
db.user.find({ "dnd": { "$ne": 90 })
And since the "blacklist" contains that value then you do not return the user records where that value would be in the list. But for a time beyond the "dnd" range it would return:
db.user.find({ "dnd": { "$ne": 481 })
Clearly you would generally want to exclude the array element when calling up details for the user record, but that is a simple matter of projection.
I am trying to figure out a formula to calculate the urgency of a set of arbitrary tasks, based on the number of days until a 'deadline' and the % completion of the task already completed.
So far I have a 'function' which gives the represents:
U = ((dd * 25) - (100 - cp))
Where:
dd = Day difference from deadline to current date (in an integer value)
cp = current completion % (in an integer value - in increments of 5 currently)
This gives me a linear function, and the 25 in the function indicates a 25% per day progression of the task.
So that at any given date:
Where U <0 task is urgent
Where U =0 task is on schedule
Where U >0 task is ahead of schedule
(The actual display on if a task is on schedule (within a range) would be handled separately)
Is there any other methods to calculate the urgency of a task, from the difference of two dates and weighted by a variable?
From current responses:
Using the start date,end date and current date differences along with completion % to calculate urgency
Possibly using a non-linear function to increase U when cp >75% and decrease U when cp < 75%. Are there any advantages for linear vs non-linear functions?
This will be used in MySQL & javascript, as I'd like a way to display how on track a task is using the U value. So finding a method to correctly (more so than my current method) calculate the value for U is what I'm attempting to do.
Solution
The solution I went with (based on marked solution):
((((((end_date - now) / (end_date - start_date)) * 100) * (100 - cp)) * 10) * -1)
Minor Changes made
Using the rule of three as a start, multiplied by 10 just to increase the values & create a wider range without needing to factor for float values too much.
Also multiplied by -1, this was so that completed tasks then give a negative number, while incomplete tasks show a higher number (makes sense: higher urgency of a task therefore a higher number)
I may in future add to this, adding a velocity for a task as suggested & also taking into account for the number of people assigned to a given task.
This function is only going to be used for a rough guide to show someone what tasks (in a given list) the might need to do first.
Also as I used this in MySQL the function needed to be wrapped in a IFNULL (due to existing data in my case)
IFNULL( *function* ,-200)
An initial arbitrary value of -200 if it was null value (as some tasks do not have an start/end date)
Thanks for the assistance & suggestions
Given that:
due is day difference from deadline to current date
estimated is the time needed for a task
done is the progress in percentage
This would be a simple rule of three:
var rest = estimated / 100 * (100 - done);
if(due < rest) {
state = 'behind';
}
if(due == rest) {
state = 'on';
}
if(due > rest) {
state = 'ahead';
}
Note that possibly very few tasks would be "on schedule" because they'd have to match exactly, you could also check in ranges like rest < due + 0.5 && rest > due - 0.5 or so, imitating a non-linear prioritizing.