Check if date range is filled in Javascript with Node.js - javascript

I am building a scheduling application with Express. I have a calendar view that displays a monthly calendar.
Each day must be completely covered; whether shifts overlap or not, there must be at least one person on a shift at all times.
Given an array of shifts for the day that look like this
{
start: [javascript Date],
end: [javascript Date],
name: "James Bond",
...
}
I want to conditionally add a CSS class to highlight the day if more shifts are needed to fill it.
What is the best way tell if the time between x and y is completely filled?

You need to show what you have tried, but I will give you pseudocode for two basic approaches for this problem.
With either approach, make sure that you are using half-opened intervals for your shifts. This is represented a few different ways:
// interval notation:
[start, end)
// algebraicly
start <= value < end
// javascript and other code
start <= value && end > value
Approach #1
Use Date.getTime() on each date to get a simple numeric representation of each date.
Find a library that implements an Interval Tree.
Map all your shifts onto the tree.
Flatten/merge the tree.
Look for gaps.
Approach #2
Initialize a counter i = 0.
Initialize a dictionary or list of key/value pairs.
For each shift in the list:
If your start date x is in the shift, then increment i.
See if the start time is in the dictionary.
If not, add it with the key being the start datetime and the value being 1.
If it is already in the dictionary, increment the value.
See if the end time is in the dictionary.
If not, add it with the key being the start datetime and the value being -1.
If it is already in the dictionary, decrement the value.
Sort the dictionary by the datetime keys.
Walk the dictionary, starting from x.
i should be starting with the number of people currently working.
Add the value of each dictionary item to your counter i.
If i == 0 then nobody is working. Return false or error.
If you've followed the logic, then i should never be negative. Error if it is.
Continue until your end date y is reached.

Related

Auto-increment dates in two cells if date has passed

Overview:
I'm not a programmer but I managed to get some serious coding into a Gsheets to track my teams project, so we have multiple-variable dropdown menus and integration with google calendar to track projects development and all that.
Why I'm at stackoverflow:
I kind of lack the knowledge to start the code from the scratch, I usually find spare parts of code through forums on the internet and clue them together and it usually works surprisingly well, but this time I couldn't find much informtation.
What I need:
I have 5 cells, and we can put as below,
Date start - Date end - date code* - number** - Priority***
*script to add the date range to gcalendar
** & *** The number is an array that's based on the word written on the priority cell, for example: If priority is written Weekly them
the number colunm will show 7 on the cell to the left and them it
goes. (monthly = 30 and blablabla...)
So I'd like to know if someone could give a hand with a script that would work (at least in my head) as following:
If I set the priority to weekly, it will show 7 on the number colunm and them, every time the "Date end" has passed, it will automatically add 7 days to the "Date start" and "Date end" again.
That way I could keep the projects on a loop where I'll be able to track them constatly.
Thanks in advance for any insights provided,
ps: I've seen some posts about this on sql, but I have no idea also on how to take advantage of the proposals that were presented there.
Edit:
Spreadsheet picture
eDIT2:
Spreadsheet with a increment colunm
Pertinent to the data set and description, you probably do not need any VBA as the increment could be achieved by adding +1 to the reference pointing to previous cell. For example, assuming cell A1 is formatted as Date, enter in cell B1: =A1+1 , then in cell C1: =B1+1 and so on. The result should be as shown below
A B C
9/1/2017 9/2/2017 9/3/2017
It could be further extended with simple logic allowing do display incremented value only if the previous cell is not empty, like : =IF(A1,A1+1,"")
In your case, it could be cell F1 containing =IF(E1,E1+1,"").
FYI, the underlying value of Date is just an Integer value (Time is represented as decimal part), so the arithmetic operations could be applied.
More generic solution would be based on the Excel DATE() Worksheet formula as shown in sample shown below (adding 1 mo. to the date entered in cell A1):
=DATE(YEAR(A1), MONTH(A1)+1, DAY(A1))
In order to implement additional logic, you may consider using Excel Worksheet IF() statement like for example, cell B1 containing:
=A1+IF(C1="week",7,1)
A B C
9/1/2017 9/8/2017 week
so based on the IF() condition it will add either 7 days if C1 contains the word "week" or 1 day otherwise. It could be further extended with nested IF().
Hope this will help.

Search with multiple range values on same item

I'm implementing a search filter via instantsearch.js with a range slider.
The slider filters a range of years based on the year data column of each item. In this DB tho there are some items with no precise year, but a "supposed" period, like "circa XVIII sec" or "End of 1910s". This means that for these items there is not a single year to filter but rather multiple years.
Let's say for ex. that I wish to filter results in a range of years from 1874 to 1930 and I have an item with "Second half 19th century" in the year field. As you can tell it should result in the match, since any year from 1851 to 1900 is correct for this item.
How should I treat this type of data to be part of this filter range?
How should I structure the data in the year column of this DB?
Should I use some script logic in the algolia javascript search rather than use a special way of structuring the data or indexing?
I was thinking of a logic like:
"If value of item is not just digits, convert it to a range of years.
Then check if the range of these years can match with the filter required in
the slider"
I can't really tell how to do this, and it looks a bit cumbersome and silly to me. I'm pretty sure this is no new issue to face in DB data design, so there has to be a proper way to address it.
I tried searching around but I don't even know how to proper word this thing I'm asking.. if you have suggestions to edit the title please do tell me!
I'm using a MySQL database along with PHP.
With Algolia, you'll need to convert this values to timestamp then you would be able to use numericFilter and add a range slider or numeric refinement list component to your UI.
Also the attribute must be defined as an attributesForFaceting in your index configuration.
https://community.algolia.com/instantsearch.js/documentation/#rangeslider
https://community.algolia.com/instantsearch.js/documentation/#numericrefinementlist
Considering your year as a range, you can either add a beggining and an end attribute to those fields. Example:
EventTimes
id SMALLINT NOT NULL PRIMARY,
yearEnd DATETIME,
yearStart DATETIME
In this case, the end and the start will be equal (I use null ends), when the event is an specific time, and becomes a range when the two fields are filled.
When SELECTing, you can always check for both fields, without a significant loss of speed or accuracy. Then check either for specific time, range of times, or if an event begins, ends, re-begins, re-ends and so on, you can check for different fields within the same table.

Regex for finding all the numbers between any two numeric values (range) in JavaScript [duplicate]

This question already has answers here:
How to match numbers between X and Y with regexp?
(7 answers)
Closed 7 years ago.
First of all, i know Regular expressions isn't the best tool to achieve what I want here. I have done enough research to know that bit. Still, The problem I am stuck in requires me to make up a regex to find the values between some lower and upper bound values.
So here is the problem, I have a large set of data, let's say ranging between 1 and 1000000. That data is not under my direct control, I cannot manipulate the data directly. Only way of finding out (searching) some values from that data is regex.. Now, the user can give two values, a minimum value and a maximum value and I need to construct a regex based on these two values and then query the large data set using the regex to get all the values lying between the set range. So, if my data contains [1,5,7,9,15,30,45,87] and user sets the range min:10, max:40. The regex should filter out values 15, 30.
From whatever I have searched, I know it is very much possible to build a regex for finding out values between fixed values (if we know them beforehand) for example, values between 1 to 100 can be found by:
^(100|[1-9][0-9]?)$
But what gets so tricky about my problem is that the input range can be anything from pretty much 1 digit values to up to 10 digit values. 10000-550000 can be an example user input for a large data set.
I know this will require some complex logic and loops involved on the basis of number of digits in the lower bound and number of digits in the upper bound of the range and then some recursive or other magical logic to build a regex that covers all the number lying in that range.
I've been filling up pages to come up with a logic but I'm afraid it surpasses my knowledge of regex. If anyone has ever done something like this before or try to point me in the right direction or attempt it him/herself - it'll be quite helpful. Thanks.
The language I will be using this in is JavaScript and I read somewhere that JS doesn't support conditional regex, keeping that in mind, solution doesn't have to be in specific to a language.
If your task is to get numbers between min and max value from the dataset, you can try filter method.
Var filteredResults = Dataset.filter(function(item){
If(item < max && item > min)
Return item
}
)

Counting occurrences of a string in an array (javascript)

I have a code...
var userArray=userIn.match(/(?:[A-Z][a-z]*|\d+|[()])/g);
...that separates the user input of a chemical formula into its components.
For example, entering Cu(NO3)2N3 will yield
Cu , ( , N , O , 3 , ) , 2 , N , 3.
In finding the percentage of each element in the entire weight, I need to count how many times each element is entered.
So in the example above,
Cu : 1 ,
N : 5 ,
O : 6
Any suggestions of how I should go about doing this?
You need to build a parser
There is no simple way around that. You need nesting and memory, a regular expression can't handle that very well (well, a real CS regulular expression can't handle that at all).
First, you get the result regexp you have. This is called Tokenization.
Now, you have to actually parse that.
I suggest the following approach I will give you pseudo code because I think it will be better deductively. If you have any questions about it let me know:
method chemistryExpression(tokens): #Tokens is the result of your regex
Create an empty map called map
While the next token is a letter, consume it (remove it from the tokens)
2.1 Add the letter to the map with occurrence 1 or increment it by one if it's already inside the map
If the next token is (, consume it: # Deal with nesting
3.1 Add the occurrences from parseExpression(tokens) to the map (note, tokens changed)
3.2 Remove the extra ) you've just encountered
num = consume tokens while the next token is a number and convert to int
Multiply the occurances of all tokens in the map by num
Return the map
Implementation suggestion
The map can just be an object.
Adding to the map is checking if the key is there, if it is not, set it to 1, if it is there, increment its value by one.
Multiplying can be done using a for... in loop.
This solution is recursive this means you're using a function which calls itself (chemistryExpression) in this case. This parser is a very basic example of a recursive descent parser and handles nesting well.
Common sense and good practice necessitate two methods
peek - what is the next token in the tokens, this is tokens[0]
next - grab the next token from tokens, this is tokens.unshift()
For each value in userArray, check if there is a next element anf if that next element is a number, if so, add this number to the count of the current element type, else add 1. You can use an object as a map to store a count for each distinct element type :
var map = { }
map[userArray[/*an element*/] = ...
EDIT : if you have numbers longer than a digit, then in a loop while the next is a number, concatenate all numbers into a string and parseInt()

Optimization for matching End Date of an Event with Start Date of another Event

I have a data set of events (start date, end date, location). These events move in the country and I need to figure out which event should go where after it ends.
Exemple:
[1/7, 6/7, Toronto] (Starts the 1st of July, ends the 6th of July)
[2/7, 4/7, Montreal]
[4/7, 11/7, Ottawa]
[17/7, 22/7, Vancouver]
..etc (Data set will be around 100 entries, so performance is not really an issue)
In this exemple, Event 1 could move and do Event 4, since it ends on the 6th of July and Event 4 starts on the 17th. (Assuming transit in the same day)
All Events that couldn't find a suitable match will be stored in a report for someone to match manually.
This optimization code will be done in javascript.
My first thought was to have 2 arrays, with the same data. First array sorted by Start Date, 2nd array sorted by End Date. Then go through the list of End Dates and try to find an appropriate Start Date for it, then remove these entries from the array and continue like that until no more matching is possible.
Anybody has a better idea on how to approach this problem ? If you need more details let me know!
Your question isn't very clear. If I understand correctly, your goal is to choose a subset of events such that your selection maximizes the number of events (and there are not overlapping events). If so, your problem can be seen as an Activity Selection Problem. There is a simple greedy algorithm to solve that.
Let
event[1..n] the n events
start[i] the start time of the event number i
finish[i] the finish time of the event number i
and assume that you already sorted the events by end time.
The following greedy algorithm will find the largest subset S of non overlapping events:
(note that lse is the Last Selected Event)
S = {event[1]}
lse = 1
foreach event[i] do:
if start[i] > finish[lse]:
S = S + {event[i]}
lse = i
return S
Basically:
you sort the events by end time
you select the 1st event
you loop on the events, greedily choosing the 1st one that doesn't overlap with the last one you choose

Categories

Resources