Reputation: 437
I'm working on a timetabling piece of code. I am using a system of university modules and events associated to those modules, ie
Module CSC3039 Event1 - Lecture Event2 - Lecture Event3 - Practial etc
I need to check the times of each event in the module against each other and compare for clashes. The clashes do not need to be rectified, just highlighted. The table I will use is Events
containing Event_ID (PK), Module_code (FK), Start_Date_Time, End_Date_Time
plus other fields that don't matter here. I have figured out that I need to implement a For Each
statement, ultimately resulting in an if statement such as:
if (startTime1 <= endTime2 or endTime1 >= startTime2) CLASH
My problem is trying to figure out the actual for loop here. I don't know what to write to declare my start times and end times. I presume it is a case of taking event1 and getting its start and end and then checking if event 2, 3 or 4 fit the above if statement. I'm trying to get this but could really use some guidance.
EDIT... Based on suggestions below I have implemented the following code:
'return all relevant tables from the Modules database, based on the module code entered by the user.
Dim eventTime = (From mods In db.Modules
Join evnt In db.Events On mods.Module_code Equals evnt.Module_code
Join rm In db.Rooms On rm.Room_ID Equals evnt.Room_ID
Join build In db.Buildings On build.Building_code Equals rm.Building_code
Where ((mods.Module_code = initialModCode) And (evnt.Room_ID = rm.Room_ID))
Select evnt.Event_ID, evnt.Module_code, evnt.Event_type, evnt.Start_Date_Time, evnt.End_Date_Time, build.Building_code, rm.Room_Number)
'use the gridview to display the result returned by the above query
gdvEventsTable.DataSource = eventTime
gdvEventsTable.DataBind()
Dim listClashes As New List(Of Array)
For i As Integer = 0 To eventTime.Count - 1
For j As Integer = i + 1 To eventTime.Count - 1
If (eventTime.ToList(i).Start_Date_Time < eventTime.ToList(j).End_Date_Time) And (eventTime.ToList(i).End_Date_Time > eventTime.ToList(j).Start_Date_Time) Then
MsgBox("Clash", MsgBoxStyle.MsgBoxSetForeground, "")
listClashes.Add(eventTime)
Else
MsgBox("No Clash", MsgBoxStyle.MsgBoxSetForeground, "")
End If
Next
Next
When trying to add an event to my array list I have noticed, in debug, that no events are sent to the list.
Upvotes: 0
Views: 779
Reputation: 413
If you want to compare all the pairs of events that are in an array or some kind of a collection, you can use a loop like:
Dim ModuleEventArray() As ModuleEvent
'...
For i As Integer = 0 To ModuleEventArray.Length - 1
For j As Integer = i + 1 To ModuleEventArray.Length - 1
'test if ModuleEventArray(i) overlaps with ModuleEventArray(j)
Next
Next
ModuleEvent here would be another class or structure that has fields startTime and endTime. The test
if (startTime1 <= endTime2 or endTime1 >= startTime2)
is not enough to test for overlap, but maybe you can figure out the correct test yourself :)
EDIT: Since I see you use some sort of collection, not array, the code you need should be something like:
For i As Integer = 0 To eventTime.Count - 1
For j As Integer = i + 1 To eventTime.Count - 1
If (eventTime.Item(i).Start_Date_Time < eventTime.Item(j).End_Date_Time) And (eventTime.Item(i).End_Date_Time > eventTime.Item(j).Start_Date_Time) Then
MsgBox("Clash")
Else
MsgBox("No Clash")
End If
Next
Next
Upvotes: 1
Reputation: 437
My comparisons are coming from the database. Prior to the code below I have a query which returns all the records from my Events
table, based on the user input of a Module_Code
. This code will show the clashes, through a msgbox. I will be changing it to populate a list. It's not the prettiest and will probably lead to a lot of duplication but it achieves my main objective.
For Each evnt In eventTime
Dim startTime1 = evnt.Start_Date_Time
Dim endTime1 = evnt.End_Date_Time
For Each evat In eventTime
Dim startTime2 = evat.Start_Date_Time
Dim endTime2 = evat.End_Date_Time
If (startTime1 < endTime2) And (endTime1 > startTime2) Then
MsgBox("Clash")
Else
MsgBox("No Clash")
End If
Next
Next
Upvotes: 0
Reputation: 22261
Before you write your code, you need to first decide what your algorithm is going to be. For example, if you use the naive method your presume, the code is indeed straightforward (basically 2 nested loops) but the complexity if O(n²).
Depending on how much data you have, whether it is in a database, how likely you expect clashes to be, whether you always have the full list of events at the start or you need to find clashes incrementally, etc... different solutions might be preferred. One consideration is whether you need to partition the list into non-clashing sets of events or just produce a yes/no answer (one one for each event) stating whether there is a clash.
You might consider doing something different instead, like sorting the list by start time before you start comparing. That will allow you to walk the list only once.
Upvotes: 0