شركة التطبيقات المتكاملة لتصميم النظم البرمجية الخاصة

Integrated Applications Programming Company

Skip Navigation Links

Public general use code classes and xml files that we've compiled and used over the years:

Group/User support class of Next Generation Network'a (NGN's) business and data model.

   1:  using System.Web;
   2:  using System.Configuration;
   3:  using System.Data;
   4:  using System.Collections.Generic;
   5:  using System.Linq;
   6:  using Telegram.Bot;
   7:  using Telegram.Bot.Args;
   8:  using Telegram.Bot.Types.Enums;
   9:  using Telegram.Bot.Types.InlineQueryResults;
  10:  using Telegram.Bot.Types.ReplyMarkups;
  11:  using System;
  12:   
  13:  namespace Ia.Ngn.Cl.Model.Telegram
  14:  {
  15:      ////////////////////////////////////////////////////////////////////////////
  16:   
  17:      /// <summary publish="true">
  18:      /// Group/User support class of Next Generation Network'a (NGN's) business and data model.
  19:      /// </summary>
  20:      /// 
  21:      /// <remarks> 
  22:      /// Copyright © 2018-2019 Jasem Y. Al-Shamlan (info@ia.com.kw), Internet Applications - Kuwait. All Rights Reserved.
  23:      ///
  24:      /// 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
  25:      /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  26:      ///
  27:      /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  28:      /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  29:      /// 
  30:      /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
  31:      /// 
  32:      /// Copyright notice: This notice may not be removed or altered from any source distribution.
  33:      /// </remarks> 
  34:      public partial class Chat
  35:      {
  36:          private static List<int> usedImageIdList = new List<int>();
  37:          private static List<Ia.Ngn.Cl.Model.Telegram.Chat> chatList;
  38:          private static readonly object objectLock = new object();
  39:   
  40:          public enum ChatType { Unknown, PrivateGroup, PrivateChannel, PublicGroup, PublicChannel }
  41:   
  42:          /// <summary/>
  43:          public int ImageId { get; set; }
  44:   
  45:          /// <summary/>
  46:          public string NameId { get; set; }
  47:   
  48:   
  49:          /// <summary/>
  50:          public long ChatId { get; set; }
  51:   
  52:          /// <summary/>
  53:          public string Name { get; set; }
  54:   
  55:          /// <summary/>
  56:          public string Description { get; set; }
  57:   
  58:          /// <summary/>
  59:          public Ia.Ngn.Cl.Model.Telegram.Chat.ChatType Type { get; set; }
  60:   
  61:          /// <summary/>
  62:          public bool RestrictedByFrameworkSite { get; set; }
  63:   
  64:          /// <summary/>
  65:          public Ia.Ngn.Cl.Model.Business.Administration.Framework Framework { get; set; }
  66:   
  67:          /// <summary/>
  68:          public string TelegramGroupUrl { get { return "https://web.telegram.org/#/im?p=g" + System.Math.Abs(this.ChatId) + ""; } }
  69:   
  70:   
  71:          /// <summary/>
  72:          public string TelegramLogoImageUrl { get { return "~/image/telegram/logo.png"; } }
  73:   
  74:          /// <summary/>
  75:          public string TelegramLogoHtmlImageUrl { get { return TelegramLogoImageUrl.Replace("~", "../.."); ; } }
  76:   
  77:          /// <summary/>
  78:          public static string OfnUserBotApiToken { get { return ConfigurationManager.AppSettings["ofnUserBotApiToken"].ToString(); } }
  79:   
  80:          /// <summary/>
  81:          public static readonly string OfnUserBotNameId = "ofnUserBot"; // logo 32.png
  82:   
  83:          ////////////////////////////////////////////////////////////////////////////
  84:   
  85:          /// <summary>
  86:          ///
  87:          /// </summary>
  88:          public Chat() { }
  89:   
  90:          ////////////////////////////////////////////////////////////////////////////
  91:   
  92:          /// <summary>
  93:          ///
  94:          /// <see cref="https://stackoverflow.com/questions/9311857/convert-alphabetic-string-into-integer-in-c-sharp"/>
  95:          /// </summary>
  96:          private static long ConvertAlphabeticStringIntoLong(string line)
  97:          {
  98:              long l;
  99:              System.Text.Encoding ascii;
 100:              Byte[] encodedBytes;
 101:   
 102:              l = 0;
 103:              ascii = System.Text.Encoding.ASCII;
 104:              encodedBytes = ascii.GetBytes(line);
 105:   
 106:              foreach (Byte b in encodedBytes) l += b;
 107:   
 108:              return l;
 109:          }
 110:   
 111:          ////////////////////////////////////////////////////////////////////////////
 112:   
 113:          /// <summary>
 114:          ///
 115:          /// </summary>
 116:          public string LogoImageUrl
 117:          {
 118:              get
 119:              {
 120:                  return "~/image/telegram/ftth-logo/" + this.ImageId + ".png";
 121:              }
 122:          }
 123:   
 124:          ////////////////////////////////////////////////////////////////////////////
 125:   
 126:          /// <summary>
 127:          ///
 128:          /// </summary>
 129:          public string LogoHtmlImageUrl
 130:          {
 131:              get
 132:              {
 133:                  return "../../image/telegram/ftth-logo/" + this.ImageId + ".png";
 134:              }
 135:          }
 136:   
 137:          ////////////////////////////////////////////////////////////////////////////
 138:   
 139:          /// <summary>
 140:          ///
 141:          /// </summary>
 142:          public static Ia.Ngn.Cl.Model.Telegram.Chat ReadFromFramework(Ia.Ngn.Cl.Model.Business.Administration.Framework framework)
 143:          {
 144:              var chat = (from t in Ia.Ngn.Cl.Model.Telegram.Chat.List where t.Framework == framework select t).SingleOrDefault();
 145:   
 146:              return chat;
 147:          }
 148:   
 149:          ////////////////////////////////////////////////////////////////////////////
 150:   
 151:          /// <summary>
 152:          ///
 153:          /// </summary>
 154:          public static long ReadChatIdFromNameId(string nameId)
 155:          {
 156:              long chatId;
 157:   
 158:              chatId = ChatNameIdToChatIdDictionary.ContainsKey(nameId) ? ChatNameIdToChatIdDictionary[nameId] : 0;
 159:   
 160:              // chatId = (from c in List where c.NameId == nameId select c.ChatId).SingleOrDefault();
 161:   
 162:              return chatId;
 163:          }
 164:   
 165:          ////////////////////////////////////////////////////////////////////////////
 166:   
 167:          /// <summary>
 168:          ///
 169:          /// </summary>
 170:          public static Ia.Ngn.Cl.Model.Telegram.Chat Read(long chatId)
 171:          {
 172:              var chat = (from c in Ia.Ngn.Cl.Model.Telegram.Chat.List where c.ChatId == chatId select c).SingleOrDefault();
 173:   
 174:              if (chat == null)
 175:              {
 176:                  chat = new Chat() { Type = ChatType.Unknown };
 177:              }
 178:   
 179:              return chat;
 180:          }
 181:   
 182:          ////////////////////////////////////////////////////////////////////////////
 183:   
 184:          /// <summary>
 185:          ///
 186:          /// </summary>
 187:          public static List<Ia.Ngn.Cl.Model.Telegram.Chat> List
 188:          {
 189:              get
 190:              {
 191:                  if (chatList == null || chatList.Count == 0)
 192:                  {
 193:                      if (HttpContext.Current != null && HttpContext.Current.Application["chatList"] != null)
 194:                      {
 195:                          chatList = HttpContext.Current.Application["chatList"] as List<Ia.Ngn.Cl.Model.Telegram.Chat>;
 196:                      }
 197:                      else
 198:                      {
 199:                          lock (objectLock)
 200:                          {
 201:                              chatList = Ia.Ngn.Cl.Model.Telegram.Chat._List;
 202:   
 203:                              if (HttpContext.Current != null) HttpContext.Current.Application["chatList"] = chatList;
 204:                          }
 205:                      }
 206:                  }
 207:   
 208:                  return chatList;
 209:              }
 210:          }
 211:   
 212:          ////////////////////////////////////////////////////////////////////////////
 213:   
 214:          /// <summary>
 215:          ///
 216:          /// </summary>
 217:          private static List<Ia.Ngn.Cl.Model.Telegram.Chat> _List
 218:          {
 219:              get
 220:              {
 221:                  long chatId;
 222:                  string nameId;
 223:                  Ia.Ngn.Cl.Model.Telegram.Chat chat;
 224:                  List<Ia.Ngn.Cl.Model.Business.Administration.Framework> frameworkList;
 225:   
 226:                  if (chatList == null || chatList.Count == 0)
 227:                  {
 228:                      chatList = new List<Ia.Ngn.Cl.Model.Telegram.Chat>(40);
 229:   
 230:                      // groups: framework site restricted
 231:                      foreach (KeyValuePair<string, long> kvp in ChatNameIdToChatIdDictionary)
 232:                      {
 233:                          nameId = kvp.Key;
 234:                          chatId = kvp.Value;
 235:   
 236:                          frameworkList = (from f in Ia.Ngn.Cl.Model.Data.Administration.FrameworkList where f.Type == "division" && f.Site != null && nameId.ToUpper().Contains(f.Site.Name) select f).ToList();  // division: مراقبة
 237:                          chat = new Ia.Ngn.Cl.Model.Telegram.Chat();
 238:   
 239:                          if (frameworkList.Count > 0)
 240:                          {
 241:                              foreach (var framework in frameworkList)
 242:                              {
 243:                                  chat = new Ia.Ngn.Cl.Model.Telegram.Chat()
 244:                                  {
 245:                                      ImageId = ChatNameIdToLogoNameImageIdDictionary[nameId],
 246:                                      NameId = nameId,
 247:                                      ChatId = chatId,
 248:                                      Name = framework.ArabicName + ": موظفي وفنيي التواصل مع شبكة الألياف الضوئية",
 249:                                      Description = @"هذه مجموعة تيليجرام الخاصة بموظفي وفنيي " + framework.ArabicName + @" للتواصل مع خادم (سيرفر) إدارة شبكة الألياف الضوئية. للحصول على معلومات وقوائم تصليح، تراسَل مع المستخدم @" + Ia.Ngn.Cl.Model.Telegram.Chat.OfnUserBotNameId + @" معك في هذه المجموعة وسيرد عليك بالمعلومات المطلوبة.",
 250:                                      Type = Ia.Ngn.Cl.Model.Telegram.Chat.ChatType.PrivateGroup,
 251:                                      RestrictedByFrameworkSite = true,
 252:                                      Framework = framework
 253:                                  };
 254:                              }
 255:   
 256:                              chatList.Add(chat);
 257:                          }
 258:                          else
 259:                          {
 260:                          }
 261:                      }
 262:   
 263:                      // channels
 264:                      chatList.Add(new Ia.Ngn.Cl.Model.Telegram.Chat()
 265:                      {
 266:                          ImageId = ChatNameIdToLogoNameImageIdDictionary["ofnChannelId"],
 267:                          NameId = "ofnChannelId",
 268:                          ChatId = ChatNameIdToChatIdDictionary["ofnChannelId"],
 269:                          Type = Ia.Ngn.Cl.Model.Telegram.Chat.ChatType.PrivateChannel,
 270:                          RestrictedByFrameworkSite = false,
 271:                      });
 272:   
 273:                      // groups
 274:                      chatList.Add(new Ia.Ngn.Cl.Model.Telegram.Chat()
 275:                      {
 276:                          ImageId = ChatNameIdToLogoNameImageIdDictionary["ofnGroupId"],
 277:                          NameId = "ofnGroupId",
 278:                          ChatId = ChatNameIdToChatIdDictionary["ofnGroupId"],
 279:                          Type = Ia.Ngn.Cl.Model.Telegram.Chat.ChatType.PrivateGroup,
 280:                          RestrictedByFrameworkSite = false,
 281:                      });
 282:                  }
 283:   
 284:                  return chatList;
 285:              }
 286:          }
 287:   
 288:          ////////////////////////////////////////////////////////////////////////////
 289:   
 290:          /// <summary>
 291:          /// 
 292:          /// </summary>
 293:          public static Dictionary<string, long> ChatNameIdToChatIdDictionary
 294:          {
 295:              get
 296:              {
 297:                  return new Dictionary<string, long>
 298:                  {
 299:                      ["ofnChannelId"] = -1001223248678,
 300:                      ["ofnGroupId"] = -261107707,
 301:                      //["ofnFieldTnmdSupplierChannelId"] = -1001278178752,
 302:                      //["ofnFieldTnmdSupplierGroupId"] = -225558580,
 303:                      //["ofnHuaweiGroupId"] = -311929669,
 304:                      //["ofnHuaweiChannelId"] = -1361384142,
 305:                      ["ofnSurGroupId"] = -270294758,
 306:                      ["ofnSkbGroupId"] = -294568632,
 307:                      ["ofnSlbGroupId"] = -391495618,
 308:                      ["ofnQrnGroupId"] = -320056533,
 309:                      ["ofnMsfGroupId"] = -376519373,
 310:                      ["ofnRslGroupId"] = -370905362,
 311:                      ["ofnJlsGroupId"] = -389361722,
 312:                      ["ofnArdGroupId"] = -377650856,
 313:                      ["ofnRkkGroupId"] = -321982802,
 314:                      ["ofnSbaGroupId"] = -353233683,
 315:                      ["ofnMgfGroupId"] = -385099568,
 316:                      ["ofnKhpGroupId"] = -193997759,
 317:                      ["ofnKhrGroupId"] = -336590544,
 318:                      ["ofnJhbGroupId"] = -261167826
 319:                  };
 320:              }
 321:          }
 322:   
 323:          ////////////////////////////////////////////////////////////////////////////
 324:   
 325:          /// <summary>
 326:          /// 
 327:          /// </summary>
 328:          public static Dictionary<string, int> ChatNameIdToLogoNameImageIdDictionary
 329:          {
 330:              get
 331:              {
 332:                  return new Dictionary<string, int>
 333:                  {
 334:                      ["ofnChannelId"] = 12,
 335:                      ["ofnGroupId"] = 21,
 336:                      ["ofnFieldTnmdSupplierChannelId"] = 27,
 337:                      ["ofnFieldTnmdSupplierGroupId"] = 24,
 338:                      ["ofnSurGroupId"] = 1,
 339:                      ["ofnSkbGroupId"] = 2,
 340:                      ["ofnSlbGroupId"] = 30,
 341:                      ["ofnQrnGroupId"] = 11,
 342:                      ["ofnMsfGroupId"] = 8,
 343:                      ["ofnRslGroupId"] = 3,
 344:                      ["ofnJlsGroupId"] = 18,
 345:                      ["ofnArdGroupId"] = 26,
 346:                      ["ofnRkkGroupId"] = 33,
 347:                      ["ofnSbaGroupId"] = 32,
 348:                      ["ofnMgfGroupId"] = 24,
 349:                      ["ofnRkkGroupId"] = 6,
 350:                      ["ofnKhpGroupId"] = 10,
 351:                      ["ofnKhrGroupId"] = 17,
 352:                      ["ofnJhbGroupId"] = 20
 353:                  };
 354:              }
 355:          }
 356:      }
 357:   
 358:      ////////////////////////////////////////////////////////////////////////////
 359:      ////////////////////////////////////////////////////////////////////////////
 360:   
 361:   
 362:      ////////////////////////////////////////////////////////////////////////////
 363:   
 364:      /// <summary>
 365:      ///
 366:      /// </summary>
 367:      public class User
 368:      {
 369:          /// <summary/>
 370:          public int UserId { get; set; }
 371:          /// <summary/>
 372:          public List<Ia.Ngn.Cl.Model.Telegram.Chat> ChatList { get; set; }
 373:   
 374:          /// <summary/>
 375:          public bool IsRestrictedBySite
 376:          {
 377:              get
 378:              {
 379:                  // a user is restricted by site if all his chats are restricted by site
 380:   
 381:                  bool isRestrictedBySite;
 382:   
 383:                  isRestrictedBySite = true;
 384:   
 385:                  foreach (var c in this.ChatList)
 386:                  {
 387:                      isRestrictedBySite = isRestrictedBySite & c.RestrictedByFrameworkSite;
 388:                  }
 389:   
 390:                  return isRestrictedBySite;
 391:              }
 392:          }
 393:   
 394:          /// <summary/>
 395:          public Ia.Ngn.Cl.Model.Business.Administration.Framework Framework
 396:          {
 397:              get
 398:              {
 399:                  // if a user is not restrected, framework will be null, otherwise I will take the first framework
 400:                  Ia.Ngn.Cl.Model.Business.Administration.Framework framework;
 401:   
 402:                  if (!this.IsRestrictedBySite) framework = null;
 403:                  else
 404:                  {
 405:                      framework = (from c in this.ChatList select c.Framework).First();
 406:                  }
 407:   
 408:                  return framework;
 409:              }
 410:          }
 411:   
 412:          ////////////////////////////////////////////////////////////////////////////
 413:   
 414:          /// <summary>
 415:          ///
 416:          /// </summary>
 417:          public static List<Ia.Ngn.Cl.Model.Telegram.User> List()
 418:          {
 419:              int index;
 420:              User user;
 421:              List<int> list;
 422:              List<Ia.Ngn.Cl.Model.Telegram.User> userList;
 423:   
 424:              list = new List<int>();
 425:              userList = new List<Ia.Ngn.Cl.Model.Telegram.User>();
 426:   
 427:              foreach (var uccm in Ia.Ngn.Cl.Model.Telegram.UserIdChatIdChatMember.List())
 428:              {
 429:                  if (!list.Contains(uccm.UserId))
 430:                  {
 431:                      list.Add(uccm.UserId);
 432:   
 433:                      user = new Ia.Ngn.Cl.Model.Telegram.User();
 434:                      user.ChatList = new List<Ia.Ngn.Cl.Model.Telegram.Chat>();
 435:   
 436:                      user.UserId = uccm.UserId;
 437:                      user.ChatList.Add(uccm.Chat);
 438:   
 439:                      userList.Add(user);
 440:                  }
 441:                  else
 442:                  {
 443:                      index = userList.FindIndex(u => u.UserId == uccm.UserId);
 444:   
 445:                      userList[index].ChatList.Add(uccm.Chat);
 446:                  }
 447:              }
 448:   
 449:              return userList;
 450:          }
 451:   
 452:          ////////////////////////////////////////////////////////////////////////////
 453:   
 454:          /// <summary>
 455:          ///
 456:          /// </summary>
 457:          public static Ia.Ngn.Cl.Model.Telegram.User Read(TelegramBotClient telegramBotClient, int userId)
 458:          {
 459:              var user = (from u in Ia.Ngn.Cl.Model.Telegram.User.List() where u.UserId == userId select u).SingleOrDefault();
 460:   
 461:              if (user == null)
 462:              {
 463:                  // update readings
 464:                  Ia.Ngn.Cl.Model.Telegram.UserIdChatIdChatMember.UpdateAllChatListForUserId(telegramBotClient, userId);
 465:   
 466:                  user = (from u in Ia.Ngn.Cl.Model.Telegram.User.List() where u.UserId == userId select u).SingleOrDefault();
 467:              }
 468:   
 469:              return user;
 470:          }
 471:   
 472:          ////////////////////////////////////////////////////////////////////////////
 473:          ////////////////////////////////////////////////////////////////////////////
 474:      }
 475:   
 476:      ////////////////////////////////////////////////////////////////////////////
 477:      ////////////////////////////////////////////////////////////////////////////
 478:   
 479:      /// <summary>
 480:      ///
 481:      /// </summary>
 482:      public class UserIdChatIdChatMember
 483:      {
 484:          private static List<UserIdChatIdChatMember> list = new List<UserIdChatIdChatMember>();
 485:   
 486:          /// <summary/>
 487:          public string Id { get; }
 488:          /// <summary/>
 489:          public int UserId { get; set; }
 490:          /// <summary/>
 491:          public long ChatId { get; set; }
 492:          /// <summary/>
 493:          public global::Telegram.Bot.Types.ChatMember ChatMember { get; set; }
 494:          /// <summary/>
 495:          public Ia.Ngn.Cl.Model.Telegram.Chat Chat { get; set; }
 496:   
 497:          ////////////////////////////////////////////////////////////////////////////
 498:   
 499:          /// <summary>
 500:          ///
 501:          /// </summary>
 502:          public UserIdChatIdChatMember(int userId, long chatId, global::Telegram.Bot.Types.ChatMember chatMember)
 503:          {
 504:              Id = userId + ":" + chatId;
 505:   
 506:              UserId = userId;
 507:              ChatId = chatId;
 508:              ChatMember = chatMember;
 509:   
 510:              Chat = (from c in Ia.Ngn.Cl.Model.Telegram.Chat.List where c.ChatId == chatId select c).SingleOrDefault();
 511:          }
 512:   
 513:          ////////////////////////////////////////////////////////////////////////////
 514:   
 515:          /// <summary>
 516:          ///
 517:          /// </summary>
 518:          public static List<UserIdChatIdChatMember> List()
 519:          {
 520:              return list;
 521:          }
 522:   
 523:          ////////////////////////////////////////////////////////////////////////////
 524:   
 525:          /// <summary>
 526:          ///
 527:          /// </summary>
 528:          public static List<UserIdChatIdChatMember> List(int userId)
 529:          {
 530:              return (from l in list where l.UserId == userId select l).ToList();
 531:          }
 532:   
 533:          ////////////////////////////////////////////////////////////////////////////
 534:   
 535:          /// <summary>
 536:          ///
 537:          /// </summary>
 538:          public static List<UserIdChatIdChatMember> List(long chatId)
 539:          {
 540:              return (from l in list where l.ChatId == chatId select l).ToList();
 541:          }
 542:   
 543:          ////////////////////////////////////////////////////////////////////////////
 544:   
 545:          /// <summary>
 546:          ///
 547:          /// </summary>
 548:          public static UserIdChatIdChatMember List(int userId, long chatId)
 549:          {
 550:              return (from l in list where l.UserId == userId && l.ChatId == chatId select l).SingleOrDefault();
 551:          }
 552:   
 553:          ////////////////////////////////////////////////////////////////////////////
 554:   
 555:          /// <summary>
 556:          ///
 557:          /// </summary>
 558:          public static bool UpdateAllChatListForUserId(TelegramBotClient telegramBotClient, int userId)
 559:          {
 560:              bool isUpdated;
 561:              long chatId;
 562:              global::Telegram.Bot.Types.ChatMember chatMember;
 563:   
 564:              isUpdated = false;
 565:   
 566:              foreach (KeyValuePair<string, long> kvp in Ia.Ngn.Cl.Model.Telegram.Chat.ChatNameIdToChatIdDictionary)
 567:              {
 568:                  chatId = kvp.Value;
 569:   
 570:                  if (chatId != 0)
 571:                  {
 572:                      chatMember = telegramBotClient.GetChatMemberAsync(chatId, userId).Result;
 573:   
 574:                      if(chatMember.Status == ChatMemberStatus.Creator || chatMember.Status == ChatMemberStatus.Administrator || chatMember.Status == ChatMemberStatus.Member)
 575:                          isUpdated = isUpdated | Update(userId, chatId, chatMember);
 576:                  }
 577:              }
 578:   
 579:              return isUpdated;
 580:          }
 581:   
 582:          ////////////////////////////////////////////////////////////////////////////
 583:   
 584:          /// <summary>
 585:          ///
 586:          /// </summary>
 587:          public static bool Update(int userId, long chatId, global::Telegram.Bot.Types.ChatMember chatMember)
 588:          {
 589:              bool isUpdated;
 590:              int index;
 591:   
 592:              index = list.FindIndex(c => c.UserId == userId && c.ChatId == chatId);
 593:   
 594:              if (index >= 0)
 595:              {
 596:                  if (list[index].ChatMember == chatMember)
 597:                  {
 598:                      isUpdated = false;
 599:                  }
 600:                  else
 601:                  {
 602:                      list[index].ChatMember = chatMember;
 603:   
 604:                      list[index].Chat = (from c in Ia.Ngn.Cl.Model.Telegram.Chat.List where c.ChatId == chatId select c).SingleOrDefault();
 605:   
 606:                      isUpdated = true;
 607:                  }
 608:              }
 609:              else
 610:              {
 611:                  list.Add(new UserIdChatIdChatMember(userId, chatId, chatMember));
 612:   
 613:                  isUpdated = true;
 614:              }
 615:   
 616:              return isUpdated;
 617:          }
 618:      }
 619:   
 620:      ////////////////////////////////////////////////////////////////////////////
 621:      ////////////////////////////////////////////////////////////////////////////   
 622:  }