How to merge iCalendar events - php

I'm trying to merge multiple iCalendars together. I wanna be able to merge overlapping events. So for example, if I have an event Monday at 12pm - 2pm and another event at 1pm - 3pm, I want to end up with an event that runs from 12pm until 3pm.
I'm looking for a simple open-source script that does that in PHP, or just help with the algorithm itself.
Any kind of help is appreciated!

Right -- sadly, I cannot help you with the PHP coding, as i know nothing of PHP (this also means my algorithmic help might just be waay off). However, I know quite my way around algorithms, so I'm going to come up with as many as possible. I'll give each it's reasons for and against, you can take your pick, and hopefully we'll both learn something.
First off, a simplification -- note that when merging more than two ICalendars together, we can merge two, then merge our result with the next etc; meaning our algorithm can just merge two to work.
With that in mind, the conceptually simplest merge I can muster:
Given ICalendars A and B, we will merge them into a new ICalendar C
Initialize C
Pick & remove the earliest event from either A or B, adding it to C.
Do the same, this time "merging the events" if they overlap.
lather, rinse, repeat until both A and B are empty -- C should now contain the merger of A and B.
Actually, this would be close to the best algorithm -- O(n) time, where n is the average number of events per ICalendar; meaning no other methods will be forthcoming...sadly.

This is what I ended up doing if anyone's interested. It may not be the most efficient, but it's good enough for what I'm doing.
Parse the calendars into Event objects (each object has a start time and end time unix timestamps), the class Event should also have a toString() method for exporting.
Store all objects in an array then sort it by start time (ascendingly)
Initialize an array for the final result, let's call it "final_array"
Take the first Event in the array as "A"
Start iterating through the array starting with the next Event, let's name it "B"
If B starts after A ends: Add A to final_array and make B the new A
If B starts before A ends:
If B ends before A ends: Do nothing
If B ends after A ends: Change A's end time to B's end time.
Go back to 5 if you haven't reached the end of the array
For each event in final_array, write event to the new calendar file

Related

Overlapping intervals and the amount of overlaps

This question might be similar to others but is a bit different. Let's say we have a set of intervals that goes like this let's say A-9 are numbers but for the sake of formatting I used letters):
<-a---> <------c--->
<------------MAIN>
ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
<--d-> <--b------->
So we have the Main interval which goes from I to Z, the interval a that goes from M to S and so on.
Now I want to have the intervals where I have the most overlaps WITHIN the main one (which is essentially the basic constraint) that would be M-O with (a and d) and Q-S (a and b) and U-Z (b and c) with 2 overlaps each (everything beyond Z is out of the question because it is outside the main interval
I essentially want a list (aka array) of the intervals and the number of overlaps inside the Main, while not counting the main into that number (sorting not needed there are enough ways to do this) in PHP.
I thought of making a picture of the intervals and then counting the colors for each pixel column but that's
averting the problem
inefficient
probably pretty slow
so, TLDR, I need a solution that
works in PHP
is relatively fast
is reliable
gives you the overlapping intervals with their overlap count
has a main interval used as base constraint which is not counted to the overlap.
I know it's a very specific question but I am not that well versed in Math and algorithms.
Build 2 vectors. One contains the start points and one contains the end points of each interval.
Sort the 2 vectors.
While you have something in any of the two vectors:
pick the minimum between the 2.
If you picked it from the vector with start points increment the number of overlapping intervals by 1, else decrease it by 1.
If your point is also the starting point of the main interval set a flag that you results are valid now.
If your point is the end point of the main interval you can stop.
If the flag is set then you can compare the current number of overlapping intervals with the max so far and update accordingly.
You can decrease 1 from the max to ignore the main interval. You can keep a list of sections where you have the max count (Just make sure you clear it when you getter a better result).
This is O(NlogN) with the number of intervals you have.
The basic algorithm for this is go over the whole length with a counter that increases when you meet a start point and decreases when you meet an end point.
Keep track of the maximum this counter gets to.
Go over the whole length again, this time add locations to your result array when:
1. You are within the MAIN part borders.
2. Your counter (which is maintained the same way) is equal to the maximum you calculated before.

someone knows the algorithm to avoid that two or more datetimes collide between them in php

I want to find the correct algorithm to avoid collision between datetime variables.
I mean for example we don't want the one wedding collide with other one in the same hour.
You have to make two checks because, from what you've stated, you don't know which of the two events starts first. So, this is what you do in mysql, assuming that you've joined two rows and one is called a and one is called b and they each have a datetime field for start and end:
select ...your query...
where (
a.end<=b.start or b.end<=a.start
) ... continue your query here if you want...
I changed this. You don't want ANY overlap. So, all you need to do is ensure one ends before the other one starts. Simplifies the query.
The same logic us used if you have some sort of PHP variables. I'll use $a_start, $a_end, $b_start, and $b_end as an example:
if($a_end<=$b_start || $b_end<=$a_start) // You are good!
I used <=, so one can end at the exact time another starts. Use just < if you don't want that microsecond of overlap.

Searchable date/time durations in SMW

I'm using Mediawiki, with the SMW extension, in a private setting to organize a fictional universe my group is creating. I have some functionality I'd like, and I'd like to know if there is an extension out there, or the possibility of making my own, that would let me do what I want to do.
Basically, in plain english... I want to know what's going on in the universe at a specific point (or duration) in time.
I'd like to give the user an ability to give a date (as simple as a year, or as precise as necessary), or duration, and return every event which has a duration that overlaps.
For example.
Event 1 starts ~ 3200 BCE, and ends ~ 198 BCE
Event 2 starts ~509 BCE and ends ~ 405 CE
Event 3 starts 1/15/419 CE and ends 1/17/419 CE
Event 4 starts ~409 BCE and ends on 2/14/2021 CE
User inputs a date (partial, in this instance) 309 BCE.
Wiki returns Event 1, and Event 4, as the given date is within the duration of both.
This would allow my creators to query a specific date (and hopefully a duration) and discover what events are already taking place, so they can adjust their works according to what is already established. It's a simple conflict checker.
If there's no extension available that can handle this, is there anything like this anywhere I can research? I've never dealt with dates in PHP. I'm a general business coder, I've never done complex applications.
There is no built in “duration” data type in SMW, so the easiest approach would probably be to use one date property for the starting date, and one for the ending date (note that it must be BC/AD, not BCE/CE or similar):
[[Event starts at::3200 BC]]
[[Event ends at::198 BC]]
then you can query for each event that has a starting date before, and an ending date after a certain date:
{{#ask:[[Event starts at::<1000 BC]] [[Event ends at::>1000 BC]]}}
Note that > actually means “greater or equal to” in SMW query syntax.

clever way to increment a value in a large array

Hep hey!
I am building an statistic overview of how many people is supposed to be at work at any given 5 minuts interval on a given day.
Say, we have 6 people working at 10.50, same at 10.55, then one go home and we got 5 people working at 11.00
Now, the way i imagined to keep track of this was to have an array with 5x12x24 elements (1 element per 5 minuts for an 24 hour interval), where i run through each employees shift time and increment the elements for the given 5 min intervals their shift takes them over.
(say a person works from 9.00 to 10.00, then i will increment the values from 9.00, 9.05, 9.10 up to 10.00 by one)
I need the data to make a diagram later, that is why i store it in an array.
Now my question is, which way is the fastest to do this?
Should i start out with an array which contains all the time elements and then increment it as i run through the shift hours of the employees ($arr['9.05']++) or should i start out by making an empty array and just check if the value of the time exsists, if not, create that element and if it does, increment it?
Or is there in general a smarter way to do this?
I ask as i can see this becomming a pretty heavy operation if you have 50+ employees which have to run through this function, so the smarter it can be made, the better :)
PS. the shift times comes from a database that i do not have access to, so i only have the timestamps of the start of the shit and the finish.

Searching for matrix way finding algorithm

i am developing a board game in php and now i have problems in writing an algorithm...
the game board is a multidimensional array ($board[10][10]) to define rows and columns of the board matrix or vector...
now i have to loop through the complete board but with a dynamic start point. for example the user selects cell [5,6] this is the start point for the loop. goal is to find all available board cells around the selected cell to find the target cells for a move method. i think i need a performant and efficient way to do this. does anyone know an algorithm to loop through a matrix/vector, only ones every field to find the available and used cells?
extra rule...
in the picture appended is a blue field selected (is a little bigger than the other). the available fields are only on the right side. the left side are available but not reachable from the current selected position... i think this is a extra information which makes the algorithm a little bit complicated....
big thx so far!
kind regards
not completely sure that I got the requirements right, so let me restate them:
You want an efficient algorithm to loop through all elements of an nxn matrix with n approximately 10, which starts at a given element (i,j) and is ordered by distance from (i,j)!?
I'd loop through a distance variable d from 0 to n/2
then for each value of d loop for l through -(2*d) to +(2*d)-1
pick the the cells (i+d, j+l), if i>=0 also pick (i+l,j-d),(i+l, j+d)
for each cell you have to apply a modulo n, to map negativ indexes back to the matrix.
This considers the matrix basically a torus, glueing upper and lower edge as well as left and right edge together.
If you don't like that you can let run d up to n and instead of a modulo operation just ignore values outside the matrix.
These aproaches give you the fields directly in the correct order. For small fields I do doubt any kind of optimization on this level has much of an effect in most situations, Nicholas approach might be just as good.
Update
I slightly modified the cells to pick in order to honor the rule 'only consider fields that are right from the current column or on the same column'
If your map is only 10x10, I'd loop through from [0][0], collecting all the possible spaces for the player to move, then grade the spaces by distance to current player position. N is small, so the fact that the algorithm has O(N^2) shouldn't affect your performance much.
Maybe someone with more background in algorithms has something up their sleeve.

Categories