source: Scheduling/branches/GUI1.2/CGSchedLib.cs@ 1075

Last change on this file since 1075 was 614, checked in by Sam Habiel, 15 years ago

Initial committ of scheduling package

File size: 27.5 KB
Line 
1using System;
2using System.Data;
3//using System.Data.OleDb;
4using System.Collections;
5using System.Diagnostics;
6using System.Drawing;
7using IndianHealthService.BMXNet;
8
9namespace IndianHealthService.ClinicalScheduling
10{
11 public enum ScheduleType
12 {
13 Resource,
14 Clinic
15 }
16
17 /// <summary>
18 /// CGSchedLib contains static functions that are called from throughout the
19 /// scheduling application.
20 /// </summary>
21 public class CGSchedLib
22 {
23 public CGSchedLib()
24 {
25
26 }
27
28 public static DataTable CreateAppointmentSchedule(CGDocumentManager docManager, ArrayList saryResNames, DateTime StartTime, DateTime EndTime)
29 {
30 string sResName = "";
31 for (int i = 0; i < saryResNames.Count; i++)
32 {
33 sResName += saryResNames[i];
34 if ((i+1) < saryResNames.Count)
35 sResName += "|";
36 }
37 string sStart;
38 string sEnd;
39 sStart = StartTime.ToString("M-d-yyyy");
40 sEnd = EndTime.ToString("M-d-yyyy@HH:m");
41 string sSql = "BSDX CREATE APPT SCHEDULE^" + sResName + "^" + sStart + "^" + sEnd ;
42 DataTable dtRet = docManager.RPMSDataTable(sSql, "AppointmentSchedule");
43 return dtRet;
44
45 }
46
47 public static void OutputArray(DataTable dt, string sName)
48 {
49#if (DEBUG && OUTPUTARRAY)
50 Debug.Write("\n " + sName + " OutputArray:\n");
51 if (dt == null)
52 return;
53
54 foreach (DataColumn c in dt.Columns)
55 {
56 Debug.Write(c.ToString());
57 }
58 Debug.Write("\n");
59 foreach (DataRow r in dt.Rows)
60 {
61 foreach (DataColumn c in dt.Columns)
62 {
63 Debug.Write(r[c].ToString());
64 }
65 Debug.Write("\n");
66 }
67 Debug.Write("\n");
68#endif
69 }
70
71 public static DataTable CreateAvailabilitySchedule(CGDocumentManager docManager,
72 ArrayList saryResourceNames, DateTime StartTime, DateTime EndTime,
73 ArrayList saryApptTypes,/**/ ScheduleType stType, string sSearchInfo)
74 {
75 DataTable rsOut;
76 rsOut = new DataTable("AvailabilitySchedule");
77
78 DataTable rsSlotSchedule;
79 DataTable rsApptSchedule;
80 DataTable rsTemp1;
81
82 int nSize = saryResourceNames.Count;
83 if (nSize == 0)
84 {
85 return rsOut;
86 }
87
88 string sResName;
89 for (int i = 0; i < nSize; i++)
90 {
91 sResName = saryResourceNames[i].ToString();
92
93 rsSlotSchedule = CGSchedLib.CreateAssignedSlotSchedule(docManager, sResName, StartTime, EndTime, saryApptTypes,/**/ stType, sSearchInfo);
94 OutputArray(rsSlotSchedule, "rsSlotSchedule");
95
96 if (rsSlotSchedule.Rows.Count > 0 )
97 {
98 rsApptSchedule = CGSchedLib.CreateAppointmentSlotSchedule(docManager, sResName, StartTime, EndTime, stType);
99 OutputArray(rsApptSchedule, "rsApptSchedule");
100 rsTemp1 = CGSchedLib.SubtractSlotsRS2(rsSlotSchedule, rsApptSchedule, sResName);
101 OutputArray(rsTemp1, "rsTemp1");
102 }
103 else
104 {
105 rsTemp1 = rsSlotSchedule;
106 OutputArray(rsTemp1, "rsTemp1");
107 }
108 if (i == 0)
109 {
110 rsOut = rsTemp1;
111 OutputArray(rsOut, "rsOut");
112 }
113 else
114 {
115 rsOut = CGSchedLib.UnionBlocks(rsTemp1, rsOut);
116 OutputArray(rsOut, "United rsOut");
117 }
118 }
119 return rsOut;
120 }
121
122 public static DataTable CreateAssignedTypeSchedule(CGDocumentManager docManager, string sResourceName, DateTime StartTime, DateTime EndTime, ScheduleType stType)
123 {
124
125 string sStart;
126 string sEnd;
127 sStart = StartTime.ToString("M-d-yyyy");
128 sEnd = EndTime.ToString("M-d-yyyy");
129// string sSource = (stType == ScheduleType.Resource ? "ST_RESOURCE" : "ST_CLINIC");
130 string sSql = "BSDX TYPE BLOCKS OVERLAP^" + sStart + "^" + sEnd + "^" + sResourceName ;//+ "^" + sSource;
131
132 DataTable rs = docManager.RPMSDataTable(sSql, "AssignedTypeSchedule");
133
134 if (rs.Rows.Count == 0)
135 return rs;
136
137 DataTable rsCopy = new DataTable("rsCopy");
138 DataColumn dCol = new DataColumn();
139 dCol.DataType = Type.GetType("System.DateTime");
140 dCol.ColumnName = "StartTime";
141 dCol.ReadOnly = true;
142 dCol.AllowDBNull = false;
143 dCol.Unique = false;
144 rsCopy.Columns.Add(dCol);
145
146 dCol = new DataColumn();
147 dCol.DataType = Type.GetType("System.DateTime");
148 dCol.ColumnName = "EndTime";
149 dCol.ReadOnly = true;
150 dCol.AllowDBNull = false;
151 dCol.Unique = false;
152 rsCopy.Columns.Add(dCol);
153
154 dCol = new DataColumn();
155 dCol.DataType = Type.GetType("System.Int16");
156 dCol.ColumnName = "AppointmentTypeID";
157 dCol.ReadOnly = true;
158 dCol.AllowDBNull = false;
159 dCol.Unique = false;
160 rsCopy.Columns.Add(dCol);
161
162 dCol = new DataColumn();
163 //dCol.DataType = Type.GetType("System.Int16");
164 dCol.DataType = Type.GetType("System.Int32"); //MJL 11/17/2006
165 dCol.ColumnName = "AvailabilityID";
166 dCol.ReadOnly = true;
167 dCol.AllowDBNull = false;
168 dCol.Unique = false;
169 rsCopy.Columns.Add(dCol);
170
171 dCol = new DataColumn();
172 dCol.DataType = Type.GetType("System.String");
173 dCol.ColumnName = "ResourceName";
174 dCol.ReadOnly = true;
175 dCol.AllowDBNull = false;
176 dCol.Unique = false;
177 rsCopy.Columns.Add(dCol);
178
179
180 DateTime dLastEnd;
181 DateTime dStart;
182 DateTime dEnd;
183// DataRow r;
184 DataRow rNew;
185
186 rNew = rs.Rows[rs.Rows.Count - 1];
187 dLastEnd = (DateTime) rNew["EndTime"];
188 rNew = rs.Rows[0];
189 dStart = (DateTime) rNew["StartTime"];
190
191 long UNSPECIFIED_TYPE = 10;
192 long UNSPECIFIED_ID = 0;
193
194 //if first block in vgetrows starts later than StartTime,
195 // then pad with a new block
196
197 if (dStart > StartTime)
198 {
199 dEnd = dStart;
200 rNew = rsCopy.NewRow();
201 rNew["StartTime"] = StartTime;
202 rNew["EndTime"] = dEnd;
203 rNew["AppointmentTypeID"] = UNSPECIFIED_TYPE;
204 rNew["AvailabilityID"] = UNSPECIFIED_ID;
205 rNew["ResourceName"] = sResourceName;
206 rsCopy.Rows.Add(rNew);
207 }
208
209 //if first block start time is < StartTime then trim
210 if (dStart < StartTime)
211 {
212 rNew = rs.Rows[0];
213 rNew["StartTime"] = StartTime;
214 dStart = StartTime;
215 }
216
217 int nAppointmentTypeID;
218 int nAvailabilityID;
219
220 dEnd = dStart;
221 foreach (DataRow rEach in rs.Rows)
222 {
223 dStart = (DateTime) rEach["StartTime"];
224 if (dStart > dEnd)
225 {
226 rNew = rsCopy.NewRow();
227 rNew["StartTime"] = dEnd;
228 rNew["EndTime"] = dStart;
229 rNew["AppointmentTypeID"] = 0;
230 rNew["AvailabilityID"] = UNSPECIFIED_ID;
231 rNew["ResourceName"] = sResourceName;
232 rsCopy.Rows.Add(rNew);
233 }
234
235 dEnd = (DateTime) rEach["EndTime"];
236
237 if (dEnd > EndTime)
238 dEnd = EndTime;
239 nAppointmentTypeID = (int) rEach["AppointmentTypeID"];
240 nAvailabilityID = (int) rEach["AvailabilityID"];
241
242 rNew = rsCopy.NewRow();
243 rNew["StartTime"] = dStart;
244 rNew["EndTime"] = dEnd;
245 rNew["AppointmentTypeID"] = nAppointmentTypeID;
246 rNew["AvailabilityID"] = nAvailabilityID;
247 rNew["ResourceName"] = sResourceName;
248 rsCopy.Rows.Add(rNew);
249 }
250
251 //Pad the end if necessary
252 if (dLastEnd < EndTime)
253 {
254 rNew = rsCopy.NewRow();
255 rNew["StartTime"] = dLastEnd;
256 rNew["EndTime"] = EndTime;
257 rNew["AppointmentTypeID"] = UNSPECIFIED_TYPE;
258 rNew["AvailabilityID"] = UNSPECIFIED_ID;
259 rNew["ResourceName"] = sResourceName;
260 rsCopy.Rows.Add(rNew);
261 }
262 OutputArray(rsCopy, "CreateAssignedTypeSchedule");
263 return rsCopy;
264 }
265
266 public static DataTable CreateAssignedSlotSchedule(CGDocumentManager docManager, string sResourceName, DateTime StartTime, DateTime EndTime, ArrayList rsaryApptTypeIDs, /**/ ScheduleType stType, string sSearchInfo)
267 {
268
269 //Appointment type ids is now always "" so that all appointment types are returned.
270 string sApptTypeIDs = "";
271
272 //The following code block is not used now, but keep for possible later use:
273 //Unpack the Appointment Type IDs
274 /*
275 */
276 int nSize = rsaryApptTypeIDs.Count;
277 for (int i=0; i < nSize; i++)
278 {
279 sApptTypeIDs += rsaryApptTypeIDs[i];
280 if (i < (nSize-1))
281 sApptTypeIDs += "|";
282 }
283
284 string sStart;
285 string sEnd;
286 sStart = StartTime.ToString("M-d-yyyy");
287 sEnd = EndTime.ToString("M-d-yyyy@H:mm");
288 string sSql = "BSDX CREATE ASGND SLOT SCHED^" + sResourceName + "^" + sStart + "^" + sEnd + "^" + sApptTypeIDs + "^" + sSearchInfo; //+ "^" + sSTType ;
289
290 DataTable dtRet = docManager.RPMSDataTable(sSql, "AssignedSlotSchedule");
291
292 if (sResourceName == "")
293 {
294 return dtRet;
295 }
296
297 return dtRet;
298 }
299
300 public static DataTable CreateCopyTable()
301 {
302 DataTable dtCopy = new DataTable("dtCopy");
303 DataColumn dCol = new DataColumn();
304 dCol.DataType = Type.GetType("System.DateTime");
305 dCol.ColumnName = "START_TIME";
306 dCol.ReadOnly = true;
307 dCol.AllowDBNull = false;
308 dCol.Unique = false;
309 dtCopy.Columns.Add(dCol);
310
311 dCol = new DataColumn();
312 dCol.DataType = Type.GetType("System.DateTime");
313 dCol.ColumnName = "END_TIME";
314 dCol.ReadOnly = true;
315 dCol.AllowDBNull = false;
316 dCol.Unique = false;
317 dtCopy.Columns.Add(dCol);
318
319 dCol = new DataColumn();
320 dCol.DataType = Type.GetType("System.Int16");
321 dCol.ColumnName = "SLOTS";
322 dCol.ReadOnly = true;
323 dCol.AllowDBNull = false;
324 dCol.Unique = false;
325 dtCopy.Columns.Add(dCol);
326
327 dCol = new DataColumn();
328 dCol.DataType = Type.GetType("System.String");
329 dCol.ColumnName = "RESOURCE";
330 dCol.ReadOnly = true;
331 dCol.AllowDBNull = true;
332 dCol.Unique = false;
333 dtCopy.Columns.Add(dCol);
334
335 dCol = new DataColumn();
336 dCol.DataType = Type.GetType("System.String");
337 dCol.ColumnName = "ACCESS_TYPE";
338 dCol.ReadOnly = true;
339 dCol.AllowDBNull = true;
340 dCol.Unique = false;
341 dtCopy.Columns.Add(dCol);
342
343 dCol = new DataColumn();
344 dCol.DataType = Type.GetType("System.String");
345 dCol.ColumnName = "NOTE";
346 dCol.ReadOnly = true;
347 dCol.AllowDBNull = true;
348 dCol.Unique = false;
349 dtCopy.Columns.Add(dCol);
350
351
352 return dtCopy;
353 }
354
355 public static DataTable CreateAppointmentSlotSchedule(CGDocumentManager docManager, string sResourceName, DateTime StartTime, DateTime EndTime, ScheduleType stType)
356 {
357
358
359 string sStart;
360 string sEnd;
361 sStart = StartTime.ToString("M-d-yyyy");
362 sEnd = EndTime.ToString("M-d-yyyy");
363
364 string sSTType = (stType == ScheduleType.Resource ? "ST_RESOURCE" : "ST_CLINIC");
365 string sSql = "BSDX APPT BLOCKS OVERLAP^" + sStart + "^" + sEnd + "^" + sResourceName ;//+ "^" + sSTType;
366
367 DataTable dtRet = docManager.RPMSDataTable(sSql, "AppointmentSlotSchedule");
368
369 if (dtRet.Rows.Count < 1)
370 return dtRet;
371
372 //Create CDateTimeArray & load records from rsOut
373 int nRC;
374 nRC = dtRet.Rows.Count;
375 ArrayList cdtArray = new ArrayList();
376 cdtArray.Capacity = (nRC * 2);
377 DateTime v;
378 int i = 0;
379
380 foreach (DataRow r in dtRet.Rows)
381 {
382 v = (DateTime) r[dtRet.Columns["START_TIME"]];
383 cdtArray.Add(v);
384 v = (DateTime) r[dtRet.Columns["END_TIME"]];
385 cdtArray.Add(v);
386 }
387 cdtArray.Sort();
388
389 //Create a CTimeBlockArray and load it from rsOut
390
391 ArrayList ctbAppointments = new ArrayList(nRC);
392 CGAvailability cTB;
393 i = 0;
394 foreach (DataRow r in dtRet.Rows)
395 {
396 cTB = new CGAvailability();
397 cTB.StartTime = (DateTime) r[dtRet.Columns["START_TIME"]];
398 cTB.EndTime = (DateTime) r[dtRet.Columns["END_TIME"]];
399 ctbAppointments.Add(cTB);
400 }
401
402 //Create a TimeBlock Array from the data in the DateTime array
403 ArrayList ctbApptSchedule = new ArrayList();
404 ScheduleFromArray(cdtArray, StartTime, EndTime, ref ctbApptSchedule);
405
406 //Find number of TimeBlocks in ctbApptSchedule that
407 //overlap the TimeBlocks in ctbAppointments
408 ArrayList ctbApptSchedule2 = new ArrayList();
409 CGAvailability cTB2;
410 int nSlots = 0;
411 for (i=0; i< ctbApptSchedule.Count; i++)
412 {
413 cTB = (CGAvailability) ctbApptSchedule[i];
414 nSlots = BlocksOverlap(cTB, ctbAppointments);
415 cTB2 = new CGAvailability();
416 cTB2.Create(cTB.StartTime, cTB.EndTime, nSlots);
417 ctbApptSchedule2.Add(cTB2);
418 }
419
420 ConsolidateBlocks(ctbApptSchedule2);
421
422 DataTable dtCopy = new DataTable("dtCopy");
423 DataColumn dCol = new DataColumn();
424 dCol.DataType = Type.GetType("System.DateTime");
425 dCol.ColumnName = "START_TIME";
426 dCol.ReadOnly = true;
427 dCol.AllowDBNull = false;
428 dCol.Unique = false;
429 dtCopy.Columns.Add(dCol);
430
431 dCol = new DataColumn();
432 dCol.DataType = Type.GetType("System.DateTime");
433 dCol.ColumnName = "END_TIME";
434 dCol.ReadOnly = true;
435 dCol.AllowDBNull = false;
436 dCol.Unique = false;
437 dtCopy.Columns.Add(dCol);
438
439 dCol = new DataColumn();
440 dCol.DataType = Type.GetType("System.Int16");
441 dCol.ColumnName = "SLOTS";
442 dCol.ReadOnly = true;
443 dCol.AllowDBNull = false;
444 dCol.Unique = false;
445 dtCopy.Columns.Add(dCol);
446
447 dCol = new DataColumn();
448 dCol.DataType = Type.GetType("System.String");
449 dCol.ColumnName = "RESOURCE";
450 dCol.ReadOnly = true;
451 dCol.AllowDBNull = false;
452 dCol.Unique = false;
453 dtCopy.Columns.Add(dCol);
454
455 for (int k=0; k < ctbApptSchedule2.Count; k++)
456 {
457 cTB = (CGAvailability) ctbApptSchedule2[k];
458 DataRow newRow;
459 newRow = dtCopy.NewRow();
460 newRow["START_TIME"] = cTB.StartTime;
461 newRow["END_TIME"] = cTB.EndTime;
462 newRow["SLOTS"] = cTB.Slots;
463 newRow["RESOURCE"] = sResourceName;
464 dtCopy.Rows.Add(newRow);
465 }
466
467 return dtCopy;
468
469 }
470
471 public static int BlocksOverlap(CGAvailability rBlock, ArrayList rTBArray)
472 {
473 //this overload implements default false for bCountSlots
474 return CGSchedLib.BlocksOverlap(rBlock, rTBArray, false);
475 }
476 public static int BlocksOverlap(CGAvailability rBlock, ArrayList rTBArray, bool bCountSlots)
477 {
478 //If bCountSlots == true, then returns
479 //sum of Slots in overlapping blocks
480 //instead of the count of overlapping blocks
481
482 DateTime dStart1;
483 DateTime dStart2;
484 DateTime dEnd1;
485 DateTime dEnd2;
486 int nSlots;
487 int nCount = 0;
488 CGAvailability cBlock;
489
490 dStart1 = rBlock.StartTime;
491 dEnd1 = rBlock.EndTime;
492
493 for (int j=0; j< rTBArray.Count; j++)
494 {
495 cBlock = (CGAvailability) rTBArray[j];
496 dStart2 = cBlock.StartTime;
497 dEnd2 = cBlock.EndTime;
498 nSlots = cBlock.Slots;
499 if (TimesOverlap(dStart1, dEnd1, dStart2, dEnd2))
500 {
501 if (bCountSlots == true)
502 {
503 nCount += nSlots;
504 }
505 else
506 {
507 nCount++;
508 }
509 }
510 }
511
512 return nCount;
513 }
514
515 //BOOL CResourceLink::TimesOverlap(COleDateTime dStart1, COleDateTime dEnd1, COleDateTime dStart2, COleDateTime dEnd2)
516 public static bool TimesOverlap(DateTime dStart1, DateTime dEnd1, DateTime dStart2, DateTime dEnd2)
517 {
518 Rectangle rect1 = new Rectangle();
519 Rectangle rect2 = new Rectangle();
520 rect1.X = 0;
521 rect2.X = 0;
522 rect1.Width = 1;
523 rect2.Width = 1;
524
525 rect1.Y = CGSchedLib.MinSince80(dStart1);
526 rect1.Height = CGSchedLib.MinSince80(dEnd1) - rect1.Y;
527 rect2.Y = CGSchedLib.MinSince80(dStart2);
528 rect2.Height = CGSchedLib.MinSince80(dEnd2) - rect2.Y;
529 bool bRet = rect2.IntersectsWith(rect1);
530 return bRet;
531 }
532
533 public static void ConsolidateBlocks(ArrayList rTBArray)
534 {
535 //TODO: Test this function
536
537 int j = 0;
538 bool bDirty = false;
539 CGAvailability cBlockA;
540 CGAvailability cBlockB;
541 CGAvailability cTemp1;
542 if (rTBArray.Count < 2)
543 return;
544 do
545 {
546 bDirty = false;
547 for (j = 0; j < (rTBArray.Count - 1); j++) //TODO: why minus 1?
548 {
549 cBlockA = (CGAvailability) rTBArray[j];
550 cBlockB = (CGAvailability) rTBArray[j+1];
551 if ((cBlockA.EndTime == cBlockB.StartTime)
552 && (cBlockA.Slots == cBlockB.Slots)
553 && (cBlockA.ResourceList == cBlockB.ResourceList)
554 && (cBlockA.AccessRuleList == cBlockB.AccessRuleList)
555 )
556 {
557 cTemp1 = new CGAvailability();
558 cTemp1.StartTime = cBlockA.StartTime;
559 cTemp1.EndTime = cBlockB.EndTime;
560 cTemp1.Slots = cBlockA.Slots;
561 cTemp1.AccessRuleList = cBlockA.AccessRuleList;
562 cTemp1.ResourceList = cBlockA.ResourceList;
563 rTBArray.Insert(j, cTemp1);
564 rTBArray.RemoveRange(j+1, 2);
565 bDirty = true;
566 break;
567 }
568 }
569 }
570 while (!((bDirty == false) || (rTBArray.Count == 1)));
571 }
572
573 public static DataTable SubtractSlotsRS2(DataTable rsBlocks1, DataTable rsBlocks2, string sResource)
574 {
575 //Subtract slots in rsBlocks2 from rsBlocks1
576 //7-16-01 SUBCLINIC data field in rsBlocks1 persists thru routine.
577 //7-18-01 RESOURCE and ACCESS_TYPE fields presisted
578
579 if ((rsBlocks2.Rows.Count == 0) || (rsBlocks1.Rows.Count == 0))
580 return rsBlocks1;
581
582
583 //Create an array of the start and end times of blocks2
584 ArrayList cdtArray = new ArrayList(2*(rsBlocks1.Rows.Count + rsBlocks2.Rows.Count));
585
586 foreach (DataRow r in rsBlocks1.Rows)
587 {
588 cdtArray.Add(r[rsBlocks1.Columns["START_TIME"]]);
589 cdtArray.Add(r[rsBlocks1.Columns["END_TIME"]]);
590 }
591
592 foreach (DataRow r in rsBlocks2.Rows)
593 {
594 cdtArray.Add(r[rsBlocks2.Columns["START_TIME"]]);
595 cdtArray.Add(r[rsBlocks2.Columns["END_TIME"]]);
596 }
597
598 cdtArray.Sort();
599
600 ArrayList ctbReturn = new ArrayList();
601 DateTime cDate = new DateTime();
602 ScheduleFromArray(cdtArray, cDate, cDate, ref ctbReturn);
603
604 //Set up return table
605 DataTable rsCopy = CGSchedLib.CreateCopyTable(); //TODO: There's a datatable method that does this.
606 long nSlots = 0;
607 CGAvailability cTB;
608
609 for (int j=0; j < (ctbReturn.Count -1); j++) //TODO: why minus 1?
610 {
611 cTB = (CGAvailability) ctbReturn[j];
612 nSlots = SlotsInBlock(cTB, rsBlocks1) - SlotsInBlock(cTB, rsBlocks2);
613 string sResourceList = "";
614 string sAccessRuleList = "";
615 string sNote = "";
616
617 if (nSlots > 0)
618 {
619 bool bRet = ResourceRulesInBlock(cTB, rsBlocks1, ref sResourceList, ref sAccessRuleList, ref sNote);
620 }
621 DataRow newRow;
622 newRow = rsCopy.NewRow();
623 newRow["START_TIME"] = cTB.StartTime;
624 newRow["END_TIME"] = cTB.EndTime;
625 newRow["SLOTS"] = nSlots;
626 //Subclinic, Access Rule and Resource are null in subtractedSlot sets
627 newRow["RESOURCE"] = sResource;
628 newRow["ACCESS_TYPE"] = sAccessRuleList;
629
630 newRow["NOTE"] = sNote;
631
632 rsCopy.Rows.Add(newRow);
633 }
634 return rsCopy;
635
636 }
637
638 public static DataTable UnionBlocks(DataTable rs1, DataTable rs2)
639 {
640 //Test input tables
641 Debug.Assert(rs1 != null);
642 Debug.Assert(rs2 != null);
643 CGSchedLib.OutputArray(rs1, "UnionBlocks rs1");
644 CGSchedLib.OutputArray(rs2, "UnionBlocks rs2");
645
646 DataTable rsCopy;
647 DataRow dr;
648 if (rs1.Columns.Count >= rs2.Columns.Count)
649 {
650 rsCopy = rs1.Copy();
651 foreach (DataRow dr2 in rs2.Rows)
652 {
653 dr = rsCopy.NewRow();
654 dr.ItemArray = dr2.ItemArray;
655 //dr["START_TIME"] = dr2["START_TIME"];
656 //dr["END_TIME"] = dr2["END_TIME"];
657 //dr["SLOTS"] = dr2["SLOTS"];
658 rsCopy.Rows.Add(dr);
659 }
660 }
661 else
662 {
663 rsCopy = rs2.Copy();
664 foreach (DataRow dr2 in rs1.Rows)
665 {
666 dr = rsCopy.NewRow();
667 dr.ItemArray = dr2.ItemArray;
668 rsCopy.Rows.Add(dr);
669 }
670 }
671 return rsCopy;
672 }
673
674 public static DataTable IntersectBlocks(DataTable rs1, DataTable rs2)
675 {
676 DataTable rsCopy = CGSchedLib.CreateCopyTable();
677
678 //Test input tables
679
680 if ((rs1 == null) || (rs2 == null))
681 return rsCopy;
682
683 if ((rs1.Rows.Count == 0) || (rs2.Rows.Count == 0))
684 return rsCopy;
685
686 int nSlots1 = 0;
687 int nSlots2 = 0;
688 int nSlots3 = 0;
689 DateTime dStart1;
690 DateTime dStart2;
691 DateTime dStart3;
692 DateTime dEnd1;
693 DateTime dEnd2;
694 DateTime dEnd3;
695 string sClinic;
696 string sClinic2;
697// Rectangle rect1 = new Rectangle();
698// Rectangle rect2 = new Rectangle();
699// rect1.X = 0;
700// rect2.X = 0;
701// rect1.Width = 1;
702// rect2.Width = 1;
703
704 // DataColumn cSlots = rs1.Columns["SLOTS"];
705 foreach (System.Data.DataRow r1 in rs1.Rows)
706 {
707 nSlots1 = (int) r1[rs1.Columns["SLOTS"]];
708 if (nSlots1 > 0)
709 {
710 dStart1 = (DateTime) r1[rs1.Columns["START_TIME"]];
711 dEnd1 = (DateTime) r1[rs1.Columns["END_TIME"]];
712 sClinic = r1[rs1.Columns["SUBCLINIC"]].ToString();
713 if (sClinic == "NULL")
714 sClinic = "";
715// rect1.Y = CGSchedLib.MinSince80(dStart1);
716// rect1.Height = CGSchedLib.MinSince80(dEnd1) - rect1.Y;
717 foreach (System.Data.DataRow r2 in rs2.Rows)
718 {
719 nSlots2 = (int) r2[rs2.Columns["SLOTS"]];
720
721 if (nSlots2 > 0)
722 {
723 dStart2 = (DateTime) r2[rs2.Columns["START_TIME"]];
724 dEnd2 = (DateTime) r2[rs2.Columns["END_TIME"]];
725 sClinic2 = r2[rs2.Columns["SUBCLINIC"]].ToString();
726// rect2.Y = CGSchedLib.MinSince80(dStart2);
727// rect2.Height = CGSchedLib.MinSince80(dEnd2) - rect2.Y;
728 if (
729 /*(rect2.IntersectsWith(rect1) == true)*/
730 (CGSchedLib.TimesOverlap(dStart1, dEnd1, dStart2, dEnd2) == true)
731 &&
732 ((sClinic == sClinic2) || (sClinic == "NONE") || (sClinic2 == "NONE"))
733 )
734 {
735 dStart3 = (dStart1 >= dStart2) ? dStart1 : dStart2 ;
736 dEnd3 = (dEnd1 >= dEnd2) ? dEnd2 : dEnd1;
737 nSlots3 = (nSlots1 >= nSlots2) ? nSlots2 : nSlots1 ;
738
739 DataRow newRow;
740 newRow = rsCopy.NewRow();
741 newRow["START_TIME"] = dStart3;
742 newRow["END_TIME"] = dEnd3;
743 newRow["SLOTS"] = nSlots3;
744 newRow["SUBCLINIC"] = (sClinic == "NONE") ? sClinic2 : sClinic;
745 //Access Rule and Resource are null in interesected sets
746 newRow["ACCESS_TYPE"] = "";
747 newRow["RESOURCE"] = "";
748 rsCopy.Rows.Add(newRow);
749 }
750 }//nSlots2 > 0
751 }//foreach r2 in rs2.rows
752 }//nSlots1 > 0
753 }//foreach r1 in rs1.rows
754 return rsCopy;
755 }//end IntersectBlocks
756
757
758 public static int MinSince80(DateTime d)
759 {
760 //Returns the total minutes between d and 1 Jan 1980
761 DateTime y = new DateTime(1980,1,1,0,0,0);
762 Debug.Assert(d > y);
763 TimeSpan ts = d - y;
764 //Assure ts.TotalMinutes within int range so that cast on next line works
765 Debug.Assert(ts.TotalMinutes < 2147483646);
766 int nMinutes = (int) ts.TotalMinutes;
767 return nMinutes;
768 }
769
770 public static void ScheduleFromArray(ArrayList cdtArray, DateTime dStartTime, DateTime dEndTime, ref ArrayList rTBArray)
771 {
772 int j = 0;
773 CGAvailability cTB;
774
775 if (cdtArray.Count == 0)
776 return;
777
778 Debug.Assert(cdtArray.Count > 0);
779 Debug.Assert(cdtArray[0].GetType() == typeof(DateTime));
780
781 //If StartTime passed in, then adjust for it
782 if (dStartTime.Ticks > 0)
783 {
784 if ((DateTime) cdtArray[0] > dStartTime)
785 {
786 cTB = new CGAvailability();
787 cTB.Create(dStartTime, (DateTime) cdtArray[0], 0);
788 rTBArray.Add(cTB);
789 }
790 if ((DateTime) cdtArray[0] < dStartTime)
791 {
792 for (j = 0; j < cdtArray.Count; j++)
793 {
794 if ((DateTime) cdtArray[j] < dStartTime)
795 cdtArray[j] = dStartTime;
796 }
797 }
798 }
799
800 //Trim the end if necessary
801 if (dEndTime.Ticks > 0)
802 {
803 for (j = 0; j < cdtArray.Count; j++)
804 {
805 if ((DateTime) cdtArray[j] > dEndTime)
806 cdtArray[j] = dEndTime;
807 }
808 }
809
810 //build the schedule in rTBArray
811 DateTime dTemp = new DateTime();
812 DateTime dStart;
813 DateTime dEnd;
814 int k = 0;
815 for (j = 0; j < (cdtArray.Count -1); j++) //TODO: why minus 1?
816 {
817 if ((DateTime) cdtArray[j] != dTemp)
818 {
819 dStart =(DateTime) cdtArray[j];
820 dTemp = dStart;
821 for (k = j+1; k < cdtArray.Count; k++)
822 {
823 dEnd = new DateTime();
824 if ((DateTime) cdtArray[k] != dStart)
825 {
826 dEnd = (DateTime) cdtArray[k];
827 }
828 if (dEnd.Ticks > 0)
829 {
830 cTB = new CGAvailability();
831 cTB.Create(dStart, dEnd, 0);
832 rTBArray.Add(cTB);
833 break;
834 }
835 }
836 }
837 }
838
839 }//end ScheduleFromArray
840
841 //long CResourceLink::SlotsInBlock(CTimeBlock &rTimeBlock, _RecordsetPtr rsBlock)
842 public static int SlotsInBlock(CGAvailability rTimeBlock, DataTable rsBlock)
843 {
844 DateTime dStart1;
845 DateTime dStart2;
846 DateTime dEnd1;
847 DateTime dEnd2;
848 int nSlots = 0;
849
850 if (rsBlock.Rows.Count == 0)
851 return nSlots;
852
853 Rectangle rect1 = new Rectangle();
854 Rectangle rect2 = new Rectangle();
855 rect1.X = 0;
856 rect2.X = 0;
857 rect1.Width = 1;
858 rect2.Width = 1;
859
860 dStart1 = rTimeBlock.StartTime;
861 dEnd1 = rTimeBlock.EndTime;
862 rect1.Y = CGSchedLib.MinSince80(dStart1);
863 rect1.Height = CGSchedLib.MinSince80(dEnd1) - rect1.Y;
864
865 foreach (DataRow r in rsBlock.Rows)
866 {
867 dStart2 = (DateTime) r[rsBlock.Columns["START_TIME"]];
868 dEnd2 = (DateTime) r[rsBlock.Columns["END_TIME"]];
869
870 rect2.Y = CGSchedLib.MinSince80(dStart2);
871 rect2.Height = CGSchedLib.MinSince80(dEnd2) - rect2.Y;
872 if (rect2.IntersectsWith(rect1) == true)
873 {
874 string sSlots = r[rsBlock.Columns["SLOTS"]].ToString();
875 nSlots = System.Convert.ToInt16(sSlots);
876// nSlots = (int) r[rsBlock.Columns["SLOTS"]];
877 break;
878 }
879 }
880 return nSlots;
881 }//end SlotsInBlock
882
883 public static string ClinicInBlock(CGAvailability rTimeBlock, DataTable rsBlock)
884 {
885 DateTime dStart1;
886 DateTime dStart2;
887 DateTime dEnd1;
888 DateTime dEnd2;
889 string sClinic = "";
890
891 if (rsBlock.Rows.Count == 0)
892 return sClinic;
893
894 Rectangle rect1 = new Rectangle();
895 Rectangle rect2 = new Rectangle();
896 rect1.X = 0;
897 rect2.X = 0;
898 rect1.Width = 1;
899 rect2.Width = 1;
900
901 dStart1 = rTimeBlock.StartTime;
902 dEnd1 = rTimeBlock.EndTime;
903 rect1.Y = CGSchedLib.MinSince80(dStart1);
904 rect1.Height = CGSchedLib.MinSince80(dEnd1) - rect1.Y;
905
906 foreach (DataRow r in rsBlock.Rows)
907 {
908 dStart2 = (DateTime) r[rsBlock.Columns["START_TIME"]];
909 dEnd2 = (DateTime) r[rsBlock.Columns["END_TIME"]];
910
911 rect2.Y = CGSchedLib.MinSince80(dStart2);
912 rect2.Height = CGSchedLib.MinSince80(dEnd2) - rect2.Y;
913 if (rect2.IntersectsWith(rect1) == true)
914 {
915 sClinic = r[rsBlock.Columns["SUBCLINIC"]].ToString();
916 break;
917 }
918 }
919 return sClinic;
920 }//end ClinicInBlock
921
922 public static bool ResourceRulesInBlock(CGAvailability rTimeBlock, DataTable rsBlock, ref string sResourceList, ref string sAccessRuleList, ref string sNote)
923 {
924 DateTime dStart1;
925 DateTime dStart2;
926 DateTime dEnd1;
927 DateTime dEnd2;
928 string sResource;
929 string sAccessRule;
930
931 if (rsBlock.Rows.Count == 0)
932 return true;
933
934 Rectangle rect1 = new Rectangle();
935 Rectangle rect2 = new Rectangle();
936 rect1.X = 0;
937 rect2.X = 0;
938 rect1.Width = 1;
939 rect2.Width = 1;
940
941 dStart1 = rTimeBlock.StartTime;
942 dEnd1 = rTimeBlock.EndTime;
943 rect1.Y = CGSchedLib.MinSince80(dStart1);
944 rect1.Height = CGSchedLib.MinSince80(dEnd1) - rect1.Y;
945
946 foreach (DataRow r in rsBlock.Rows)
947 {
948 dStart2 = (DateTime) r[rsBlock.Columns["START_TIME"]];
949 dEnd2 = (DateTime) r[rsBlock.Columns["END_TIME"]];
950
951 rect2.Y = CGSchedLib.MinSince80(dStart2);
952 rect2.Height = CGSchedLib.MinSince80(dEnd2) - rect2.Y;
953 if (rect2.IntersectsWith(rect1) == true)
954 {
955 sResource = r[rsBlock.Columns["RESOURCE"]].ToString();
956 if (sResource == "NULL")
957 sResource = "";
958 if (sResource != "")
959 {
960 if (sResourceList == "")
961 {
962 sResourceList += sResource;
963 }
964 else
965 {
966 sResourceList += "^" + sResource;
967 }
968 }
969 sAccessRule = r[rsBlock.Columns["ACCESS_TYPE"]].ToString();
970 if (sAccessRule == "0")
971 sAccessRule = "";
972 if (sAccessRule != "")
973 {
974 if (sAccessRuleList == "")
975 {
976 sAccessRuleList += sAccessRule;
977 }
978 else
979 {
980 sAccessRuleList += "^" + sAccessRule;
981 }
982 }
983 sNote = r[rsBlock.Columns["NOTE"]].ToString();
984
985 }
986 }
987 return true;
988 }//End ResourceRulesInBlock
989
990
991 }
992}
Note: See TracBrowser for help on using the repository browser.