CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

MetadataFieldOrder.php
Go to the documentation of this file.
1 <?PHP
2
7 class MetadataFieldOrder extends Folder
8 {
9
13 const DISPLAY_FOLDER_NAME = "FieldDisplayFolder";
14
18 const EDIT_FOLDER_NAME = "FieldEditFolder";
19
24 public function GetItems()
25 {
26 $ItemIds = $this->GetItemIds();
27 $Items = array();
28
29 foreach ($ItemIds as $Info)
30 {
31 $Items[] = new $Info["Type"]($Info["ID"]);
32 }
33
34 return $Items;
35 }
36
42 public function CreateGroup($Name)
43 {
44 $FolderFactory = new FolderFactory();
45
46 # create the new group
47 $Folder = $FolderFactory->CreateMixedFolder($Name);
48 $Group = new MetadataFieldGroup($Folder->Id());
49
50 # and add it to this ordering
51 $this->AppendItem($Group->Id(), "MetadataFieldGroup");
52
53 return $Group;
54 }
55
62 public function DeleteGroup(MetadataFieldGroup $Group)
63 {
64 if ($this->ContainsItem($Group->Id(), "MetadataFieldGroup"))
65 {
66 $this->MoveFieldsToOrder($Group);
67 $this->RemoveItem($Group->Id(), "MetadataFieldGroup");
68 }
69 }
70
75 public function GetFields()
76 {
77 $Fields = array();
78
79 foreach ($this->GetItems() as $Item)
80 {
81 # add fields to the list
82 if ($Item instanceof MetadataField)
83 {
84 $Fields[$Item->Id()] = $Item;
85 }
86
87 # add fields of groups to the list
88 else if ($Item instanceof MetadataFieldGroup)
89 {
90 foreach ($Item->GetFields() as $Field)
91 {
92 $Fields[$Field->Id()] = $Field;
93 }
94 }
95 }
96
97 return $Fields;
98 }
99
104 public function GetGroups()
105 {
106 $ItemIds = $this->GetItemIds();
107 $GroupIds = array_filter($ItemIds, array($this, "GroupFilterCallback"));
108
109 $Groups = array();
110
111 # transform group info to group objects
112 foreach ($GroupIds as $GroupId)
113 {
114 try
115 {
116 $Groups[$GroupId["ID"]] = new $GroupId["Type"]($GroupId["ID"]);
117 } catch (Exception $Exception) {}
118 }
119
120 return $Groups;
121 }
122
132 public function MoveItemUp($Item, $Filter=NULL)
133 {
134 # make sure the item is a field or group
135 if (!$this->IsFieldOrGroup($Item))
136 {
137 throw new Exception("Item must be a field or group");
138 }
139
140 # make sure the item is in the order
141 if (!$this->ItemInOrder($Item))
142 {
143 throw new Exception("Item must exist in the ordering");
144 }
145
146 # make sure the filter is callable if set
147 if (!is_null($Filter) && !is_callable($Filter))
148 {
149 throw new Exception("Filter callback must be callable");
150 }
151
152 $ItemType = $this->GetItemType($Item);
153 $Enclosure = $this->GetEnclosure($Item);
154 $EnclosureType = $this->GetItemType($Enclosure);
155 $Previous = $this->GetSiblingItem($Item, -1, $Filter);
156 $PreviousId = $this->GetItemId($Previous);
157 $PreviousType = $this->GetItemType($Previous);
158
159 # determine if the item is at the top of the list
160 $ItemAtTop = is_null($Previous);
161
162 # determine if a field needs to be moved into a group
163 $FieldToGroup = $ItemType == "MetadataField";
164 $FieldToGroup = $FieldToGroup && $EnclosureType == "MetadataFieldOrder";
165 $FieldToGroup = $FieldToGroup && $PreviousType == "MetadataFieldGroup";
166
167 # determine if a field needs to be moved out of a group
168 $FieldToOrder = $ItemType == "MetadataField";
169 $FieldToOrder = $FieldToOrder && $EnclosureType == "MetadataFieldGroup";
170 $FieldToOrder = $FieldToOrder && $ItemAtTop;
171
172 # move a field into a group if necessary
173 if ($FieldToGroup)
174 {
175 $this->MoveFieldToGroup($Previous, $Item, "append");
176 }
177
178 # or move a field from a group to the order if necessary
179 else if ($FieldToOrder)
180 {
181 $this->MoveFieldToOrder($Enclosure, $Item, "before");
182 }
183
184 # otherwise just move the item up if not at the top of the list
185 else if (!$ItemAtTop)
186 {
187 $this->MoveItemAfter($Item, $Previous);
188 }
189 }
190
200 public function MoveItemDown($Item, $Filter=NULL)
201 {
202 # make sure the item is a field or group
203 if (!$this->IsFieldOrGroup($Item))
204 {
205 throw new Exception("Item must be a field or group");
206 }
207
208 # make sure the item is in the order
209 if (!$this->ItemInOrder($Item))
210 {
211 throw new Exception("Item must exist in the ordering");
212 }
213
214 # make sure the filter is callable if set
215 if (!is_null($Filter) && !is_callable($Filter))
216 {
217 throw new Exception("Filter callback must be callable");
218 }
219
220 $ItemType = $this->GetItemType($Item);
221 $Enclosure = $this->GetEnclosure($Item);
222 $EnclosureType = $this->GetItemType($Enclosure);
223 $Next = $this->GetSiblingItem($Item, 1, $Filter);
224 $NextId = $this->GetItemId($Next);
225 $NextType = $this->GetItemType($Next);
226
227 # determine if the item is at the bottom of the list
228 $ItemAtBottom = is_null($Next);
229
230 # determine if a field needs to be moved into a group
231 $FieldToGroup = $ItemType == "MetadataField";
232 $FieldToGroup = $FieldToGroup && $EnclosureType == "MetadataFieldOrder";
233 $FieldToGroup = $FieldToGroup && $NextType == "MetadataFieldGroup";
234
235 # determine if a field needs to be moved out of a group
236 $FieldToOrder = $ItemType == "MetadataField";
237 $FieldToOrder = $FieldToOrder && $EnclosureType == "MetadataFieldGroup";
238 $FieldToOrder = $FieldToOrder && $ItemAtBottom;
239
240 # move a field into a group if necessary
241 if ($FieldToGroup)
242 {
243 $this->MoveFieldToGroup($Next, $Item, "prepend");
244 }
245
246 # or move a field from a group to the order if necessary
247 else if ($FieldToOrder)
248 {
249 $this->MoveFieldToOrder($Enclosure, $Item, "after");
250 }
251
252 # otherwise just move the item down if not at the bottom
253 else if (!$ItemAtBottom)
254 {
255 $this->MoveItemAfter($Next, $Item);
256 }
257 }
258
265 public function MoveItemToTop($Item)
266 {
267 # make sure the item is either a field or group
268 if (!$this->IsFieldOrGroup($Item))
269 {
270 throw new Exception("Item must be a either field or group");
271 }
272
273 # make sure the item is in the order
274 if (!$this->ItemInOrder($Item))
275 {
276 throw new Exception("Item must exist in the ordering");
277 }
278
279 $OrderId = $this->GetItemId($this);
280 $OrderType = $this->GetItemType($this);
281 $ItemId = $this->GetItemId($Item);
282 $ItemType = $this->GetItemType($Item);
283 $ItemEnclosure = $this->GetEnclosure($Item);
284 $ItemEnclosureId = $this->GetItemId($ItemEnclosure);
285 $ItemEnclosureType = $this->GetItemType($ItemEnclosure);
286
287 $SameEnclosureId = $OrderId == $ItemEnclosureId;
288 $SameEnclosureType = $OrderType == $ItemEnclosureType;
289
290 # remove the item from its enclosure if necessary
291 if (!$SameEnclosureId || !$SameEnclosureType)
292 {
293 $ItemEnclosure->RemoveItem($ItemId, $ItemType);
294 }
295
296 # move the item to the top of the order
297 $this->PrependItem($ItemId, $ItemType);
298 }
299
305 public function MoveFieldToTopOfGroup(
306 MetadataFieldGroup $Group,
307 MetadataField $Field)
308 {
309 # make sure the items are in the order
310 if (!$this->ItemInOrder($Group) || !$this->ItemInOrder($Field))
311 {
312 throw new Exception("Item must exist in the ordering");
313 }
314
315 $GroupId = $this->GetItemId($Group);
316 $GroupType = $this->GetItemType($Group);
317 $FieldId = $this->GetItemId($Field);
318 $FieldType = $this->GetItemType($Field);
319 $FieldEnclosure = $this->GetEnclosure($Field);
320 $FieldEnclosureId = $this->GetItemId($FieldEnclosure);
321 $FieldEnclosureType = $this->GetItemType($FieldEnclosure);
322
323 $SameEnclosureId = $GroupId == $FieldEnclosureId;
324 $SameEnclosureType = $GroupType == $FieldEnclosureType;
325
326 # remove the item from its enclosure if necessary
327 if (!$SameEnclosureId || !$SameEnclosureType)
328 {
329 $FieldEnclosure->RemoveItem($FieldId, $FieldType);
330 }
331
332 # move the item to the top of the group
333 $Group->PrependItem($FieldId, $FieldType);
334 }
335
345 public function MoveItemAfter($Target, $Item)
346 {
347 # make sure the items are either a field or group
348 if (!$this->IsFieldOrGroup($Target) || !$this->IsFieldOrGroup($Item))
349 {
350 throw new Exception("Items must be a either field or group");
351 }
352
353 # make sure the items are in the order
354 if (!$this->ItemInOrder($Target) || !$this->ItemInOrder($Item))
355 {
356 throw new Exception("Items must exist in the ordering");
357 }
358
359 $TargetId = $this->GetItemId($Target);
360 $TargetType = $this->GetItemType($Target);
361 $ItemId = $this->GetItemId($Item);
362 $ItemType = $this->GetItemType($Item);
363 $TargetEnclosure = $this->GetEnclosure($Target);
364 $TargetEnclosureId = $this->GetItemId($TargetEnclosure);
365 $TargetEnclosureType = $this->GetItemType($TargetEnclosure);
366 $ItemEnclosure = $this->GetEnclosure($Item);
367 $ItemEnclosureId = $this->GetItemId($ItemEnclosure);
368 $ItemEnclosureType = $this->GetItemType($ItemEnclosure);
369
370 $TargetInGroup = $TargetEnclosure instanceof MetadataFieldGroup;
371 $ItemIsField = $Item instanceof MetadataField;
372
373 # make sure only fields are placed in groups
374 if ($TargetInGroup && !$ItemIsField)
375 {
376 throw new Exception("Only fields can go into field groups");
377 }
378
379 $SameEnclosureId = $TargetEnclosureId == $ItemEnclosureId;
380 $SameEnclosureType = $TargetEnclosureType == $ItemEnclosureType;
381
382 # move a field into a group if necessary
383 if (!$SameEnclosureId || !$SameEnclosureType)
384 {
385 $ItemEnclosure->RemoveItem($ItemId, $ItemType);
386 }
387
388 # move the item after the target
389 $TargetEnclosure->InsertItemAfter(
390 $TargetId,
391 $ItemId,
392 $TargetType,
393 $ItemType);
394 }
395
401 public function ItemInOrder($Item)
402 {
403 # the item would have to be a field or group to be in the order
404 if (!$this->IsFieldOrGroup($Item))
405 {
406 return FALSE;
407 }
408
409 $ItemId = $this->GetItemId($Item);
410 $ItemType = $this->GetItemType($Item);
411
412 # if the item is in the order, i.e., not in a group
413 if ($this->ContainsItem($ItemId, $ItemType))
414 {
415 return TRUE;
416 }
417
418 # the item is in one of the groups, so search each one for it
419 foreach ($this->GetGroups() as $Group)
420 {
421 if ($Group->ContainsItem($ItemId, $ItemType))
422 {
423 return TRUE;
424 }
425 }
426
427 # the item was not found
428 return FALSE;
429 }
430
437 public static function SetConfiguration(SystemConfiguration $SysConfig)
438 {
439 $DisplayFolderId = $SysConfig->FieldDisplayFolder();
440 $EditFolderId = $SysConfig->FieldEditFolder();
441
442 # create the display folder and update the system configuration if
443 # necessary
444 if (!$DisplayFolderId)
445 {
446 $Order = self::CreateOrderingObject(
447 self::DISPLAY_FOLDER_NAME,
448 MetadataSchema::MDFORDER_DISPLAY);
449 $DisplayFolderId = $Order->Id();
450 $SysConfig->FieldDisplayFolder($DisplayFolderId);
451 }
452
453 # create the edit folder and update the system configuration if
454 # necessary
455 if (!$EditFolderId)
456 {
457 $Order = self::CreateOrderingObject(
458 self::EDIT_FOLDER_NAME,
459 MetadataSchema::MDFORDER_EDITING);
460 $EditFolderId = $Order->Id();
461 $SysConfig->FieldEditFolder($EditFolderId);
462 }
463
464 self::$DisplayFolderId = $DisplayFolderId;
465 self::$EditFolderId = $EditFolderId;
466 }
467
473 public static function GetDisplayOrderObject()
474 {
475 self::CheckOrderingConfiguration();
476
477 return new MetadataFieldOrder(self::$DisplayFolderId);
478 }
479
485 public static function GetEditOrderObject()
486 {
487 self::CheckOrderingConfiguration();
488
489 return new MetadataFieldOrder(self::$EditFolderId);
490 }
491
496 public static function MendIssues()
497 {
498 try
499 {
500 $DisplayOrder = self::GetDisplayOrderObject();
501 $EditOrder = self::GetEditOrderObject();
502 $Schema = new MetadataSchema();
503 $Fields = $Schema->GetFields(NULL, NULL, TRUE);
504
505 foreach ($Fields as $Field)
506 {
507 if (!$DisplayOrder->ItemInOrder($Field))
508 {
509 $DisplayOrder->AppendItem($Field->Id(), "MetadataField");
510 }
511
512 if (!$EditOrder->ItemInOrder($Field))
513 {
514 $EditOrder->AppendItem($Field->Id(), "MetadataField");
515 }
516 }
517 } catch (Exception $Exception){}
518 }
519
525 protected function IsFieldOrGroup($Item)
526 {
527 if ($Item instanceof MetadataField)
528 {
529 return TRUE;
530 }
531
532 if ($Item instanceof MetadataFieldGroup)
533 {
534 return TRUE;
535 }
536
537 return FALSE;
538 }
539
545 protected function GetItemId($Item)
546 {
547 return is_object($Item) ? $Item->Id() : NULL;
548 }
549
555 protected function GetItemType($Item)
556 {
557 return is_object($Item) ? get_class($Item) : NULL;
558 }
559
566 protected function GroupFilterCallback($Item)
567 {
568 return $Item["Type"] == "MetadataFieldGroup";
569 }
570
578 protected function GetEnclosure($Item)
579 {
580 $ItemId = $this->GetItemId($Item);
581 $ItemType = $this->GetItemType($Item);
582
583 # the item is in the order, i.e., not in a group
584 if ($this->ContainsItem($ItemId, $ItemType))
585 {
586 return $this;
587 }
588
589 # the item is in one of the groups, so search each one for it
590 foreach ($this->GetGroups() as $Group)
591 {
592 if ($Group->ContainsItem($ItemId, $ItemType))
593 {
594 return $Group;
595 }
596 }
597
598 # the item was not found
599 return NULL;
600 }
601
609 protected function GetSiblingItem($Item, $Offset, $Filter=NULL)
610 {
611 $Id = $this->GetItemId($Item);
612 $Type = $this->GetItemType($Item);
613 $Sibling = NULL;
614
615 # the sibling is in the order, i.e., not in a group
616 if ($this->ContainsItem($Id, $Type))
617 {
618 return $this->FindSiblingItem($this, $Item, $Offset, $Filter);
619 }
620
621 # otherwise search for it in the groups
622 foreach ($this->GetGroups() as $Group)
623 {
624 if ($Group->ContainsItem($Id, $Type))
625 {
626 try
627 {
628 $Sibling = $this->FindSiblingItem(
629 $Group,
630 $Item,
631 $Offset,
632 $Filter);
633
634 if ($Sibling)
635 {
636 return $Sibling;
637 }
638 } catch (Exception $Exception) {}
639
640 break;
641 }
642 }
643
644 return NULL;
645 }
646
656 protected function FindSiblingItem($Enclosure, $Item, $Offset, $Filter=NULL)
657 {
658 $ItemIds = $Enclosure->GetItemIds();
659
660 # filter items if necessary
661 if (is_callable($Filter))
662 {
663 $ItemIds = array_filter($ItemIds, $Filter);
664
665 # maintain continuous indices
666 ksort($ItemIds);
667 $ItemIds = array_values($ItemIds);
668 }
669
670 $Id = $this->GetItemId($Item);
671 $Type = $this->GetItemType($Item);
672 $Index = array_search(array("ID" => $Id, "Type" => $Type), $ItemIds);
673
674 if (!is_null($Index) && array_key_exists($Index+$Offset, $ItemIds))
675 {
676 $SiblingInfo = $ItemIds[$Index+$Offset];
677 return new $SiblingInfo["Type"]($SiblingInfo["ID"]);
678 }
679
680 return NULL;
681 }
682
691 protected function MoveFieldToGroup(
692 MetadataFieldGroup $Group,
693 MetadataField $Field,
694 $Placement)
695 {
696 # determine which action to use based on the placement value
697 $Action = $Placement == "prepend" ? "PrependItem" : "AppendItem";
698
699 $GroupId = $this->GetItemId($Group);
700 $FieldId = $this->GetItemId($Field);
701
702 $OrderHasGroup = $this->ContainsItem($GroupId, "MetadataFieldGroup");
703 $OrderHasField = $this->ContainsItem($FieldId, "MetadataField");
704
705 # make sure the field and group are in the order before editing
706 if ($OrderHasGroup && $OrderHasField)
707 {
708 $this->RemoveItem($FieldId, "MetadataField");
709 $Group->$Action($FieldId, "MetadataField");
710 }
711 }
712
721 protected function MoveFieldToOrder(
722 MetadataFieldGroup $Group,
723 MetadataField $Field,
724 $Placement)
725 {
726 # determine which action to use based on the placement value
727 $Action = $Placement == "before" ? "InsertItemBefore" : "InsertItemAfter";
728
729 $GroupId = $this->GetItemId($Group);
730 $FieldId = $this->GetItemId($Field);
731
732 $OrderHasGroup = $this->ContainsItem($GroupId, "MetadataFieldGroup");
733 $GroupHasField = $Group->ContainsItem($FieldId, "MetadataField");
734
735 # make sure the field is in the group and the group is in the order
736 if ($OrderHasGroup && $GroupHasField)
737 {
738 $Group->RemoveItem($FieldId, "MetadataField");
739 $this->$Action(
740 $GroupId,
741 $FieldId,
742 "MetadataFieldGroup",
743 "MetadataField");
744 }
745 }
746
753 protected function MoveFieldsToOrder(MetadataFieldGroup $Group)
754 {
755 $ItemIds = $Group->GetItemIds();
756 $PreviousItemId = $Group->Id();
757 $PreviousItemType = "MetadataFieldGroup";
758
759 foreach ($ItemIds as $ItemInfo)
760 {
761 $ItemId = $ItemInfo["ID"];
762 $ItemType = $ItemInfo["Type"];
763
764 $this->InsertItemAfter(
765 $PreviousItemId,
766 $ItemId,
767 $PreviousItemType,
768 $ItemType);
769
770 $PreviousItemId = $ItemId;
771 $PreviousItemType = $ItemType;
772 }
773 }
774
781 protected static function CheckOrderingConfiguration()
782 {
783 if (!self::$DisplayFolderId || !self::$EditFolderId)
784 {
785 throw new Exception("Metadata field ordering configuration not set");
786 }
787 }
788
795 protected static function CreateOrderingObject($NewFolderName, $Type)
796 {
797 # create the folder
798 $FolderFactory = new FolderFactory();
799 $Folder = $FolderFactory->CreateMixedFolder($NewFolderName);
800
801 # try to get the existing order from the MetadataFields table, which
802 # won't be available for newer sites
803 $RowsForUpgrade = self::GetRowsForUpgrade($Type);
804
805 # an upgrade should be performed instead of using the defaults
806 if (count($RowsForUpgrade))
807 {
808 # add each field to the folder
809 foreach ($RowsForUpgrade as $Row)
810 {
811 $Folder->AppendItem($Row["FieldId"], "MetadataField");
812 }
813 }
814
815 # otherwise use the defaults
816 else
817 {
818 # used later as a variable variable to get the ordering
819 $DefaultOrder = $Type == MetadataSchema::MDFORDER_DISPLAY
820 ? "DefaultDisplayOrder" : "DefaultEditOrder";
821
822 # add each field to the folder
823 foreach (self::$$DefaultOrder as $Index => $FieldId)
824 {
825 $Folder->AppendItem($FieldId, "MetadataField");
826 }
827 }
828
829 # wrap the folder in a MetadataFieldOrder object
830 return new MetadataFieldOrder($Folder->Id());
831 }
832
840 protected static function GetRowsForUpgrade($Type)
841 {
842 $Database = new Database();
843
844 # temporarily suppress errors
845 $Setting = Database::DisplayQueryErrors();
846 Database::DisplayQueryErrors(FALSE);
847
848 # see if the old columns exist
849 $Handle = $Database->Query("
850 SELECT EditingOrderPosition
851 FROM MetadataFields
852 LIMIT 1");
853
854 # the columns do not exist so an upgrade cannot be performed
855 if ($Handle === FALSE)
856 {
857 return array();
858 }
859
860 # determine which column to use for ordering
861 $Column = $Type == MetadataSchema::MDFORDER_EDITING
862 ? "DisplayOrderPosition" : "EditingOrderPosition";
863
864 # query for the fields in their proper order
865 $Database->Query("
866 SELECT FieldId
867 FROM MetadataFields
868 WHERE FieldId > 0
869 ORDER BY ".$Column." ASC");
870
871 # restore the earlier error setting
872 Database::DisplayQueryErrors($Setting);
873
874 # return the resulting rows
875 return $Database->FetchRows();
876 }
877
881 protected static $DisplayFolderId;
882
886 protected static $EditFolderId;
887
892 protected static $DefaultDisplayOrder = array(
893 0 => 42,
894 1 => 41,
895 2 => 43,
896 3 => 44,
897 4 => 46,
898 5 => 45,
899 6 => 40,
900 7 => 39,
901 8 => 34,
902 9 => 33,
903 10 => 37,
904 11 => 36,
905 12 => 38,
906 13 => 35,
907 14 => 47,
908 15 => 48,
909 16 => 57,
910 17 => 56,
911 18 => 58,
912 19 => 59,
913 20 => 61,
914 21 => 60,
915 22 => 55,
916 23 => 54,
917 24 => 50,
918 25 => 49,
919 26 => 51,
920 27 => 52,
921 28 => 53,
922 29 => 32,
923 30 => 31,
924 31 => 1,
925 32 => 2,
926 33 => 4,
927 34 => 20,
928 35 => 21,
929 36 => 19,
930 37 => 3,
931 38 => 27,
932 39 => 11,
933 41 => 23,
934 42 => 26,
935 43 => 25,
936 44 => 24,
937 45 => 9,
938 46 => 8,
939 47 => 7,
940 48 => 6,
941 49 => 22,
942 50 => 10,
943 51 => 28,
944 52 => 5,
945 53 => 12,
946 54 => 62,
947 55 => 13,
948 56 => 14,
949 57 => 16,
950 58 => 17,
951 59 => 30,
952 60 => 29,
953 61 => 18,
954 62 => 63,
955 63 => 64,
956 64 => 65,
957 65 => 66);
958
963 protected static $DefaultEditOrder = array(
964 0 => 42,
965 1 => 41,
966 2 => 43,
967 3 => 44,
968 4 => 46,
969 5 => 45,
970 6 => 40,
971 7 => 39,
972 8 => 34,
973 9 => 33,
974 10 => 37,
975 11 => 36,
976 12 => 38,
977 13 => 35,
978 14 => 47,
979 15 => 48,
980 16 => 57,
981 17 => 56,
982 18 => 58,
983 19 => 59,
984 20 => 61,
985 21 => 60,
986 22 => 55,
987 23 => 54,
988 24 => 50,
989 25 => 49,
990 26 => 51,
991 27 => 52,
992 28 => 53,
993 29 => 32,
994 30 => 31,
995 31 => 1,
996 32 => 2,
997 33 => 4,
998 34 => 20,
999 36 => 21,
1000 37 => 19,
1001 38 => 3,
1002 39 => 27,
1003 40 => 11,
1004 41 => 23,
1005 42 => 26,
1006 43 => 25,
1007 44 => 24,
1008 45 => 9,
1009 46 => 8,
1010 47 => 30,
1011 48 => 7,
1012 49 => 6,
1013 50 => 29,
1014 51 => 22,
1015 52 => 10,
1016 53 => 28,
1017 54 => 5,
1018 55 => 12,
1019 56 => 62,
1020 57 => 13,
1021 58 => 18,
1022 59 => 14,
1023 60 => 16,
1024 61 => 17,
1025 62 => 63,
1026 63 => 64,
1027 64 => 65,
1028 65 => 66);
1029
1030 }