1: using System;
2: using System.Collections.Generic;
3: using System.Data;
4: using System.Globalization;
5: using System.Linq;
6: using System.Text.RegularExpressions;
7:
8: namespace Ia.Ngn.Cl.Model.Business
9: {
10: ////////////////////////////////////////////////////////////////////////////
11:
12: /// <summary publish="true">
13: /// Service Request support class of Next Generation Network'a (NGN's) business model.
14: /// </summary>
15: ///
16: /// <remarks>
17: /// Copyright © 2006-2020 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
18: ///
19: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
20: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
21: ///
22: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
23: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
24: ///
25: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
26: ///
27: /// Copyright notice: This notice may not be removed or altered from any source distribution.
28: /// </remarks>
29: public partial class ServiceRequest
30: {
31: /// <summary/>
32: public ServiceRequest() { }
33:
34: private static int sequentialProvisioningWorkflowQueueOriginalCount;
35: private static Dictionary<string, DateTime> provisioningWorkflowServiceIdDateTimeDictionary = new Dictionary<string, DateTime>();
36: private static Queue<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>> sequentialProvisioningWorkflowQueue = new Queue<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>>();
37:
38: public const string ServiceRequestCustomerIdInputTypeString = "serviceRequestCustomerId";
39:
40: /// <summary/>
41: public enum Procedure { Create, Read, Update, Delete, None };
42:
43: /// <summary/>
44: public struct ProvisioningWorkflow<T>
45: {
46: /// <summary/>
47: public T Item { get; set; }
48:
49: /// <summary/>
50: public Procedure Procedure { get; set; }
51:
52: /// <summary/>
53: public DateTime DateTime { get; set; }
54: }
55:
56: ////////////////////////////////////////////////////////////////////////////
57:
58: /// <summary>
59: ///
60: /// </summary>
61: public struct NumberSerial
62: {
63: public long Id
64: {
65: get { return (long)Number * 100 + Serial; }
66: }
67: public int Number { get; set; }
68: public int Serial { get; set; }
69: }
70:
71: ////////////////////////////////////////////////////////////////////////////
72: ////////////////////////////////////////////////////////////////////////////
73:
74: /// <summary>
75: ///
76: /// </summary>
77: public static string OracleSqlCommandForServiceRequestIdRange(Tuple<int, int> startEndRange)
78: {
79: return OracleSqlCommandForServiceRequestIdRange(startEndRange.Item1, startEndRange.Item2);
80: }
81:
82: ////////////////////////////////////////////////////////////////////////////
83:
84: /// <summary>
85: ///
86: /// </summary>
87: public static string OracleSqlCommandForServiceRequestIdRange(int start, int end)
88: {
89: string sql;
90:
91: // select * from SRV_REQ_FIPER where SRV_REQ_ID >= 110000 and SRV_REQ_ID <= 110200 order by SRV_REQ_ID asc
92: sql = @"select * from SRV_REQ_FIPER where SRV_REQ_ID >= " + start + " and SRV_REQ_ID <= " + end + " order by SRV_REQ_ID asc";
93:
94: return sql;
95: }
96:
97: ////////////////////////////////////////////////////////////////////////////
98:
99: /// <summary>
100: ///
101: /// </summary>
102: public static string OracleSqlCommandForServiceRequest(string service)
103: {
104: string sql;
105:
106: if (!string.IsNullOrEmpty(service))
107: {
108: // select * from SRV_REQ_FIPER where SRV_NO = 23632222 order by SRV_REQ_ID asc
109: sql = @"select * from SRV_REQ_FIPER where SRV_NO = " + service + " order by SRV_REQ_ID asc";
110: }
111: else sql = string.Empty;
112:
113: return sql;
114: }
115:
116: ////////////////////////////////////////////////////////////////////////////
117:
118: /// <summary>
119: ///
120: /// </summary>
121: private static string OracleSqlCommandForGivenDateTime(DateTime dateTime)
122: {
123: string sql;
124:
125: //sql = @"select * from SRV_REQ_FIPER LEFT OUTER JOIN SRV_REQ_FIPER_TECH ON SRV_REQ_FIPER_TECH.SRV_REQ_ID = SRV_REQ_FIPER.SRV_REQ_ID where REQ_DATE >= '" + dateTime.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) + "' and REQ_DATE < '" + dateTime.AddDays(1).ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) + "' order by REQ_DATE asc, SRV_REQ_ID asc";
126: sql = @"select * from SRV_REQ_FIPER where REQ_DATE >= '" + dateTime.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) + "' and REQ_DATE < '" + dateTime.AddDays(1).ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) + "' order by SRV_REQ_ID asc";
127:
128: return sql;
129: }
130:
131: ////////////////////////////////////////////////////////////////////////////
132:
133: /// <summary>
134: ///
135: /// </summary>
136: private static string OracleSqlCommandForSingleRandomDateTimeWithinTheLastNDays(int rangeOfPastDays, out DateTime selectedDate)
137: {
138: // below:
139: int i;
140: string sql;
141:
142: i = Ia.Cl.Model.Default.Random(rangeOfPastDays);
143:
144: selectedDate = DateTime.UtcNow.AddDays(-i);
145:
146: sql = OracleSqlCommandForGivenDateTime(selectedDate);
147:
148: return sql;
149: }
150:
151: ////////////////////////////////////////////////////////////////////////////
152:
153: /// <summary>
154: ///
155: /// </summary>
156: private static string OracleSqlCommandForSingleDateTimeUsingDayIndexBetweenNowAndEarliestDate(ref int index, out DateTime selectedDate)
157: {
158: // below: select a date between now and the earliest date using an variable index value
159: string sql;
160: DateTime now;
161:
162: now = DateTime.UtcNow.AddHours(3);
163:
164: // below: check that inIndex is an index of a day between earliest day and now, and reset it to 0 if it is bigger than now
165: if (DateTime.Compare(Ia.Ngn.Cl.Model.Business.Administration.EarliestServiceRequestDate.AddDays(index), now) < 0)
166: {
167: // below: within range
168: }
169: else index = 0;
170:
171: selectedDate = Ia.Ngn.Cl.Model.Business.Administration.EarliestServiceRequestDate.AddDays(index++);
172:
173: sql = OracleSqlCommandForGivenDateTime(selectedDate);
174:
175: return sql;
176: }
177:
178: ////////////////////////////////////////////////////////////////////////////
179: ////////////////////////////////////////////////////////////////////////////
180:
181: /// <summary>
182: ///
183: /// </summary>
184: public static ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> SequentialProvisioningWorkflowOfOfServiceRequestOntDetailSyncWithCustomerDepartmentDatabaseListItem(out int sequentialProvisioningWorkflowQueueCount, out string progressCounterString)
185: {
186: ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> pw;
187: List<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>> list;
188:
189: if (sequentialProvisioningWorkflowQueue.Count == 0)
190: {
191: list = Ia.Ngn.Cl.Model.Business.ServiceRequest.ProvisioningWorkflowOfServiceRequestOntDetailSyncWithCustomerDepartmentDatabaseList;
192:
193: sequentialProvisioningWorkflowQueue = new Queue<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>>(list);
194:
195: sequentialProvisioningWorkflowQueueOriginalCount = sequentialProvisioningWorkflowQueue.Count;
196: }
197:
198: if (sequentialProvisioningWorkflowQueue.Count > 0) pw = sequentialProvisioningWorkflowQueue.Dequeue();
199: else pw = new ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> { Item = null, Procedure = Procedure.None };
200:
201: progressCounterString = "(" + sequentialProvisioningWorkflowQueue.Count + "/" + sequentialProvisioningWorkflowQueueOriginalCount + ")";
202:
203: sequentialProvisioningWorkflowQueueCount = sequentialProvisioningWorkflowQueue.Count;
204:
205: return pw;
206: }
207:
208: ////////////////////////////////////////////////////////////////////////////
209:
210: /// <summary>
211: ///
212: /// </summary>
213: public static List<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>> ProvisioningWorkflowOfServiceRequestOntDetailSyncWithCustomerDepartmentDatabaseList
214: {
215: get
216: {
217: DateTime dateTime;
218: ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> provisioningWorkflow;
219: List<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>> provisioningWorkflowList;
220:
221: dateTime = DateTime.UtcNow.AddHours(3);
222:
223: provisioningWorkflowList = new List<ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail>>();
224:
225: Ia.Ngn.Cl.Model.Data.ServiceRequestOntDetail.ServiceRequestOntDetailCreateAndDeleteList(out List<Model.ServiceRequestOntDetail> serviceRequestOntDetailCreateList, out List<Model.ServiceRequestOntDetail> serviceRequestOntDetailDeleteList);
226:
227: foreach (Ia.Ngn.Cl.Model.ServiceRequestOntDetail srod in serviceRequestOntDetailCreateList)
228: {
229: provisioningWorkflow = new ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> { Item = srod, Procedure = Procedure.Create, DateTime = dateTime };
230: provisioningWorkflowList.Add(provisioningWorkflow);
231:
232: provisioningWorkflow = new ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> { Item = srod, Procedure = Procedure.Read, DateTime = dateTime };
233: provisioningWorkflowList.Add(provisioningWorkflow);
234: }
235:
236: foreach (Ia.Ngn.Cl.Model.ServiceRequestOntDetail srod in serviceRequestOntDetailDeleteList)
237: {
238: provisioningWorkflow = new ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> { Item = srod, Procedure = Procedure.Delete, DateTime = dateTime };
239: provisioningWorkflowList.Add(provisioningWorkflow);
240:
241: provisioningWorkflow = new ProvisioningWorkflow<Ia.Ngn.Cl.Model.ServiceRequestOntDetail> { Item = srod, Procedure = Procedure.Read, DateTime = dateTime };
242: provisioningWorkflowList.Add(provisioningWorkflow);
243: }
244:
245: return provisioningWorkflowList;
246: }
247: }
248:
249: ////////////////////////////////////////////////////////////////////////////
250: ////////////////////////////////////////////////////////////////////////////
251:
252: /// <summary>
253: ///
254: /// </summary>
255: public static Ia.Ngn.Cl.Model.Business.ServiceAddress ServiceAddress(string service, string customerAddress, out string level)
256: {
257: int areaId;
258: string provinceArea;
259: Match match;
260: Ia.Ngn.Cl.Model.Business.ServiceAddress serviceAddress;
261:
262: serviceAddress = new ServiceAddress { Service = service };
263:
264: if (!string.IsNullOrEmpty(customerAddress))
265: {
266: customerAddress = Ia.Ngn.Cl.Model.Business.Default.CorrectCustomerAddress(customerAddress);
267:
268: // below: special handeling needed here
269: customerAddress = Ia.Ngn.Cl.Model.Business.Default.CorrectCustomerAddressMissingProvinceArea(service, customerAddress);
270:
271: // ',قطعة 4 قسيمة 538,'
272: // get areaId only
273: match = Regex.Match(customerAddress, @"^(.+?),", RegexOptions.Singleline);
274:
275: if (match.Success)
276: {
277: level = "1";
278:
279: provinceArea = match.Groups[1].Value;
280: areaId = (from a in Ia.Ngn.Cl.Model.Data.Service.KuwaitNgnAreaList where provinceArea == a.ServiceRequestAddressProvinceAreaName select a.Id).SingleOrDefault();
281:
282: if (areaId != 0)
283: {
284: serviceAddress.AreaId = areaId;
285:
286: // الجهراء الجهراء المدينة,قطعة 79 شارع 5 جادة 5 قسيمة 17, منزل 17
287: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+) جادة (.+) قسيمة (.+), منزل (.+)$", RegexOptions.Singleline);
288:
289: if (match.Success)
290: {
291: level = "1-";
292:
293: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
294: serviceAddress.Street = match.Groups[3].Value;
295: serviceAddress.Boulevard = match.Groups[4].Value;
296: serviceAddress.PremisesOld = match.Groups[5].Value;
297: serviceAddress.PremisesNew = match.Groups[6].Value;
298: }
299: else
300: {
301: // حولى بيان,قطعة 12 شارع 1 جادة 9, منزل 38
302: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+) جادة (.+), منزل (.+)$", RegexOptions.Singleline);
303:
304: if (match.Success)
305: {
306: level = "2-";
307:
308: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
309: serviceAddress.Street = match.Groups[3].Value;
310: serviceAddress.Boulevard = match.Groups[4].Value;
311: serviceAddress.PremisesOld = match.Groups[5].Value;
312: serviceAddress.PremisesNew = match.Groups[6].Value;
313: }
314: else
315: {
316: // الجهراء الجهراء المدينة,قطعة 79 شارع 5 قسيمة 17, منزل 17
317: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+) قسيمة (.+), منزل (.+)$", RegexOptions.Singleline);
318:
319: if (match.Success)
320: {
321: level = "3-";
322:
323: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
324: serviceAddress.Street = match.Groups[3].Value;
325: serviceAddress.Boulevard = string.Empty;
326: serviceAddress.PremisesOld = match.Groups[4].Value;
327: serviceAddress.PremisesNew = match.Groups[5].Value;
328: }
329: else
330: {
331: // الجهراء الجهراء المدينة,قطعة 79 شارع 5, منزل 17
332: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+), منزل (.+)$", RegexOptions.Singleline);
333:
334: if (match.Success)
335: {
336: level = "4-";
337:
338: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
339: serviceAddress.Street = match.Groups[3].Value;
340: serviceAddress.Boulevard = string.Empty;
341: serviceAddress.PremisesOld = string.Empty;
342: serviceAddress.PremisesNew = match.Groups[4].Value;
343: }
344: else
345: {
346: // الجهراء الجهراء المدينة,قطعة 79 شارع 5 قسيمة 17
347: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+) قسيمة (.+),$", RegexOptions.Singleline);
348:
349: if (match.Success)
350: {
351: level = "5-";
352:
353: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
354: serviceAddress.Street = match.Groups[3].Value;
355: serviceAddress.Boulevard = string.Empty;
356: serviceAddress.PremisesOld = match.Groups[4].Value;
357: serviceAddress.PremisesNew = string.Empty;
358: }
359: else
360: {
361: // الجهراء الجهراء المدينة,قطعة 79 شارع 5 جادة 5
362: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+) جادة (.+),$", RegexOptions.Singleline);
363:
364: if (match.Success)
365: {
366: level = "6-";
367:
368: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
369: serviceAddress.Street = match.Groups[3].Value;
370: serviceAddress.Boulevard = match.Groups[4].Value;
371: serviceAddress.PremisesOld = string.Empty;
372: serviceAddress.PremisesNew = string.Empty;
373: }
374: else
375: {
376: // الجهراء الجهراء المدينة,قطعة 79 قسيمة 17, منزل 17
377: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) قسيمة (.+), منزل (.+)$", RegexOptions.Singleline);
378:
379: if (match.Success)
380: {
381: level = "7-";
382:
383: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
384: serviceAddress.Street = string.Empty;
385: serviceAddress.Boulevard = string.Empty;
386: serviceAddress.PremisesOld = match.Groups[3].Value;
387: serviceAddress.PremisesNew = match.Groups[4].Value;
388: }
389: else
390: {
391: // الجهراء الجهراء المدينة,قطعة 79 قسيمة 17
392: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) قسيمة (.+),$", RegexOptions.Singleline);
393:
394: if (match.Success)
395: {
396: level = "8-";
397:
398: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
399: serviceAddress.Street = string.Empty;
400: serviceAddress.Boulevard = string.Empty;
401: serviceAddress.PremisesOld = match.Groups[3].Value;
402: serviceAddress.PremisesNew = string.Empty;
403: }
404: else
405: {
406: // الجهراء الجهراء المدينة,قطعة 79, منزل 17
407: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+), منزل (.+)$", RegexOptions.Singleline);
408:
409: if (match.Success)
410: {
411: level = "9-";
412:
413: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
414: serviceAddress.Street = string.Empty;
415: serviceAddress.Boulevard = string.Empty;
416: serviceAddress.PremisesOld = string.Empty;
417: serviceAddress.PremisesNew = match.Groups[3].Value;
418: }
419: else
420: {
421: // الجهراء الجهراء المدينة,قطعة 79 شارع 5
422: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+) شارع (.+)$", RegexOptions.Singleline);
423:
424: if (match.Success)
425: {
426: level = "10-";
427:
428: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
429: serviceAddress.Street = match.Groups[3].Value;
430: serviceAddress.Boulevard = string.Empty;
431: serviceAddress.PremisesOld = string.Empty;
432: serviceAddress.PremisesNew = string.Empty;
433: }
434: else
435: {
436: // الجهراء الجهراء المدينة,قطعة 79
437: match = Regex.Match(customerAddress, @"^(.+),قطعة (.+),$", RegexOptions.Singleline);
438:
439: if (match.Success)
440: {
441: level = "11-";
442:
443: serviceAddress.Block = Ia.Ngn.Cl.Model.Business.Access.NormalizeBlockEntry(match.Groups[2].Value);
444: serviceAddress.Street = string.Empty;
445: serviceAddress.Boulevard = string.Empty;
446: serviceAddress.PremisesOld = string.Empty;
447: serviceAddress.PremisesNew = string.Empty;
448: }
449: else
450: {
451: // حولي السلام,,
452: match = Regex.Match(customerAddress, @"^(.+),,$", RegexOptions.Singleline);
453:
454: if (match.Success)
455: {
456: level = "12-";
457:
458: serviceAddress.Block = string.Empty;
459: serviceAddress.Street = string.Empty;
460: serviceAddress.Boulevard = string.Empty;
461: serviceAddress.PremisesOld = string.Empty;
462: serviceAddress.PremisesNew = string.Empty;
463: }
464: else
465: {
466: level = "13";
467: }
468: }
469: }
470: }
471: }
472: }
473: }
474: }
475: }
476: }
477: }
478: }
479:
480: // below: we will try to store integers in integer format
481:
482: //serviceAddress.Block this is already in int format
483: serviceAddress.Street = int.TryParse(serviceAddress.Street, out int i) ? i.ToString() : serviceAddress.Street;
484: serviceAddress.Boulevard = int.TryParse(serviceAddress.Boulevard, out i) ? i.ToString() : serviceAddress.Boulevard;
485: serviceAddress.PremisesOld = int.TryParse(serviceAddress.PremisesOld, out i) ? i.ToString() : serviceAddress.PremisesOld;
486: serviceAddress.PremisesNew = int.TryParse(serviceAddress.PremisesNew, out i) ? i.ToString() : serviceAddress.PremisesNew;
487:
488: // I will change all 0 entries to string.Empty
489:
490: if (serviceAddress.Block == "0") serviceAddress.Block = string.Empty;
491: if (serviceAddress.Street == "0") serviceAddress.Street = string.Empty;
492: if (serviceAddress.Boulevard == "0") serviceAddress.Boulevard = string.Empty;
493: if (serviceAddress.PremisesOld == "0") serviceAddress.PremisesOld = string.Empty;
494: if (serviceAddress.PremisesNew == "0") serviceAddress.PremisesNew = string.Empty;
495: }
496: else
497: {
498: level = "0";
499:
500: serviceAddress.AreaId = 0;
501: serviceAddress.Block = string.Empty;
502: serviceAddress.Street = string.Empty;
503: serviceAddress.Boulevard = string.Empty;
504: serviceAddress.PremisesOld = string.Empty;
505: serviceAddress.PremisesNew = string.Empty;
506: }
507: }
508: else
509: {
510: level = "0";
511:
512: serviceAddress.AreaId = 0;
513: serviceAddress.Block = string.Empty;
514: serviceAddress.Street = string.Empty;
515: serviceAddress.Boulevard = string.Empty;
516: serviceAddress.PremisesOld = string.Empty;
517: serviceAddress.PremisesNew = string.Empty;
518: }
519: }
520: else
521: {
522: level = "0";
523:
524: serviceAddress.AreaId = 0;
525: serviceAddress.Block = string.Empty;
526: serviceAddress.Street = string.Empty;
527: serviceAddress.Boulevard = string.Empty;
528: serviceAddress.PremisesOld = string.Empty;
529: serviceAddress.PremisesNew = string.Empty;
530: }
531:
532: return serviceAddress;
533: }
534:
535: ////////////////////////////////////////////////////////////////////////////
536:
537: /// <summary>
538: ///
539: /// </summary>
540: public static bool ServiceRequestIdIsAllowedForProcessing(int serviceRequestId)
541: {
542: return true;// (serviceRequestId != 2316113); // 2316113 problamatic causes duplicate primary key error
543: }
544:
545: ////////////////////////////////////////////////////////////////////////////
546:
547: /// <summary>
548: /// Generate a OptimizedStartEndRangeList() but with a range buffer before start and after end.
549: /// </summary>
550: public static List<Tuple<int, int>> OptimizedStartEndRangeBufferedList(List<int> list, int count, int bufferRange)
551: {
552: int start, end;
553: List<Tuple<int, int>> tupleList;
554:
555: tupleList = OptimizedStartEndRangeTupleList(list, count);
556:
557: if (tupleList != null && tupleList.Count > 0)
558: {
559: start = tupleList[0].Item1;
560: end = tupleList[tupleList.Count - 1].Item2;
561:
562: tupleList.Insert(tupleList.Count, new Tuple<int, int>(end + 1, end + bufferRange + 1));
563: tupleList.Insert(0, new Tuple<int, int>((start - bufferRange) > 0 ? (start - bufferRange) : 0, start - 1)); // keep order
564: }
565:
566: tupleList.Sort();
567:
568: return tupleList;
569: }
570:
571: ////////////////////////////////////////////////////////////////////////////
572:
573: /// <summary>
574: /// Generate a list of start-end count optimized to read around count number of values from passed list.
575: /// </summary>
576: public static List<Tuple<int, int>> OptimizedStartEndRangeTupleList(List<int> list, int count)
577: {
578: bool started, done;
579: int c, start, end;
580: Tuple<int, int> tuple;
581: List<Tuple<int, int>> tupleList;
582:
583: tupleList = new List<Tuple<int, int>>();
584:
585: started = true;
586: done = false;
587: c = start = 0;
588:
589: if (list.Count > 0 && count > 0)
590: {
591: foreach (int item in list)
592: {
593: if (started)
594: {
595: start = item;
596: started = false;
597: }
598:
599: if (c == 0)
600: {
601: done = false;
602: }
603:
604: if (c == count - 1)
605: {
606: end = item;
607:
608: tuple = new Tuple<int, int>(start, end);
609:
610: tupleList.Add(tuple);
611:
612: start = item + 1;
613: done = true;
614: c = 0;
615: }
616: else c++;
617: }
618:
619: if (!done)
620: {
621: end = list[list.Count - 1];
622:
623: tuple = new Tuple<int, int>(start, end);
624:
625: tupleList.Add(tuple);
626: }
627: }
628: else throw new System.ArgumentException("List empty or range too short. ");
629:
630: tupleList.Sort();
631:
632: return tupleList;
633: }
634:
635: ////////////////////////////////////////////////////////////////////////////
636: ////////////////////////////////////////////////////////////////////////////
637: }
638:
639: ////////////////////////////////////////////////////////////////////////////
640: ////////////////////////////////////////////////////////////////////////////
641:
642: /// <summary>
643: ///
644: /// </summary>
645: public static class ServiceRequestExtension
646: {
647: ////////////////////////////////////////////////////////////////////////////
648:
649: /// <summary>
650: /// Extension method: Collect number list
651: /// </summary>
652: public static List<int> NumberList(this List<Ia.Ngn.Cl.Model.ServiceRequest> serviceRequestList)
653: {
654: List<int> numberList;
655:
656: numberList = (from n in serviceRequestList select n.Number).Distinct().ToList<int>();
657:
658: return numberList;
659: }
660:
661: ////////////////////////////////////////////////////////////////////////////
662:
663: /// <summary>
664: /// Extension method: Collect distinct number-serials into NumberSerial list
665: /// </summary>
666: public static List<Ia.Ngn.Cl.Model.Business.ServiceRequest.NumberSerial> DistinctNumberSerialList(this List<Ia.Ngn.Cl.Model.ServiceRequest> sourceList)
667: {
668: List<Ia.Ngn.Cl.Model.Business.ServiceRequest.NumberSerial> numberSerialList;
669:
670: numberSerialList = (from n in sourceList select new Ia.Ngn.Cl.Model.Business.ServiceRequest.NumberSerial { Number = n.Number, Serial = n.Serial }).Distinct().ToList();
671:
672: return numberSerialList;
673: }
674:
675: ////////////////////////////////////////////////////////////////////////////
676: ////////////////////////////////////////////////////////////////////////////
677: }
678:
679: ////////////////////////////////////////////////////////////////////////////
680: ////////////////////////////////////////////////////////////////////////////
681: }