source: Scheduling/trunk/cs/bsdx0200GUISourceCode/CGSchedLib.cs@ 899

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