1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 | Attribute VB_Name = "modScenario" Option Explicit Option Base 1 Private oConfig As Config Private oAppErrorObject As AppError Private oFX As FX Private oFso As FileSystemObject Private dBatchQuoteDate As Date Private vRiskCl As Variant Private oCmdLine As CmdLineParams Private dQuoteDate As Date Private dcGridPaths As Dictionary Private Enum ColsScenario RiskClass = 1 Ticket BookType BookRegion TradeName ScenarioName Index Tranche Tenor Delta LastField NoOfCols = LastField - 1 End Enum Private Enum ColsOldStyle TradeName = 1 Group OBSTicketNo OBSGroupNo TradeType RiskClass CCY StartDate Curve Bucket BucketDate Tv RealDelta Delta ProductDelta MarketFactorDelta LiborGamma TVChange DeltaChange ProductDeltaChange UniversalCurrency RealDeltaChange CreditCurveShocks ScenarioName Index Tenor Tranche BookType LastField NoOfCols = LastField - 1 End Enum Private Const thisObjectName As String = "modScenario" Private Const PIVOT_DATA_RANGE As String = "PivotData" Private Const PIVOT_TABLE_NAME As String = "ScenarioPivotTable" 'Rev 29 - Addition of RegionToIndex function within config class, rename of output fields + the addtion of bookregion, ' Indexname, tranche & tenor as new data items. '############################################################################################# ' METHODS '############################################################################################# Public Sub Main() Dim xBatch As IXMLDOMElement Dim xCopyTo As IXMLDOMElement Dim xList As IXMLDOMNodeList Dim xList2 As IXMLDOMNodeList Dim vFeed As Variant Dim sPath As String On Error GoTo GenErr WriteToLog LogTypes.loginfo, "Batch creation begins for Quotedate:" & Format(RunDate, "dd-mmm-yyyy") & " Version: " & App.Major & "." & App.Minor & ":" & App.Revision Set xList = modScenario.Config.ConfigFile.selectNodes("app/batches/batch") 'for each batch do For Each xBatch In xList 'if all batches are meant to be run, or this specific batch is one targeted by command line param If CommandLineParams.BatchName = "" Or UCase(xBatch.getAttribute("name")) = CommandLineParams.BatchName Then 'Create the report data from trade valuation source data WriteToLog LogTypes.loginfo, "Creating report data for batch (" & xBatch.getAttribute("name") & ")" vFeed = BuildReport(dQuoteDate, xBatch.getAttribute("name"), xBatch.getAttribute("skew_pattern")) 'OUtput to where ever sPath = "" If Config.Environment = "UAT" Then If Not IsNull(xBatch.getAttribute("output_path_uat")) And xBatch.getAttribute("output_path_uat") <> "" Then sPath = Config.OverlayDateString(xBatch.getAttribute("output_path_uat"), dQuoteDate) End If End If If sPath = "" Then sPath = Config.OverlayDateString(xBatch.getAttribute("output_path"), dQuoteDate) End If WriteToLog LogTypes.loginfo, "Outputing data to (" & sPath & ")" SaveFeed dQuoteDate, sPath, vFeed 'Free Unlimited 'Copy To's!!! Set xList2 = xBatch.selectNodes("copyto") For Each xCopyTo In xList2 sPath = Config.OverlayDateString(xCopyTo.getAttribute("output_path"), dQuoteDate) SaveFeed dQuoteDate, sPath, vFeed Next xCopyTo End If Next xBatch WriteToLog LogTypes.loginfo, "Generation COMPLETE" 'close down On Error GoTo 0 Exit Sub GenErr: 'Log any errors that crop up WriteToLog LogTypes.LogError, AppErrors.Description End Sub Public Sub SaveFeed(ByVal QuoteDate As Date _ , ByVal Path As String _ , ByVal FeedData As Variant) Dim lRow As Long Dim lField As Long Dim sString As String Dim oStrm As TextStream On Error GoTo GenErr Set oStrm = FSO.CreateTextFile(Path, QuoteDate) For lRow = LBound(FeedData, 2) To UBound(FeedData, 2) sString = FeedData(LBound(FeedData), lRow) For lField = LBound(FeedData) + 1 To UBound(FeedData) sString = sString & vbTab & FeedData(lField, lRow) Next lField oStrm.WriteLine (sString) Next lRow oStrm.Write (sString) oStrm.Close Set oStrm = FSO.CreateTextFile(Left(Path, Len(Path) - Len(FSO.GetExtensionName(Path)) - 1) & ".done") On Error GoTo 0 Exit Sub GenErr: modScenario.AppErrors.Raise thisObjectName & "..SaveFeed" _ , Err.Source & ":" & Err.Description Resume 0 End Sub Private Function BuildReport(ByVal QuoteDate As Date _ , ByVal ReportAlias As String _ , ByVal SkewGridPattern As String) As Variant Dim xElem As IXMLDOMElement Dim xDom As DOMDocument Dim vOutput As Variant Dim vTrade As Variant Dim lRow As Long Dim lRowSub As Long Dim lField As Long Dim oFso As FileSystemObject Dim oFile As File Dim sFile As Variant Dim bLoaded As Boolean Dim oStrm As TextStream On Error GoTo GenErr lRow = 1 ReDim vOutput(ColsOldStyle.NoOfCols, 1) 'Seed output array vOutput(ColsOldStyle.Bucket, 1) = "Bucket" vOutput(ColsOldStyle.BucketDate, 1) = "BucketDate" vOutput(ColsOldStyle.CCY, 1) = "CCY" vOutput(ColsOldStyle.CreditCurveShocks, 1) = "CreditCurveShocks" vOutput(ColsOldStyle.Curve, 1) = "Curve" vOutput(ColsOldStyle.Delta, 1) = "Delta" vOutput(ColsOldStyle.DeltaChange, 1) = "DeltaChange" vOutput(ColsOldStyle.Group, 1) = "Group" vOutput(ColsOldStyle.LiborGamma, 1) = "LiborGamma" vOutput(ColsOldStyle.MarketFactorDelta, 1) = "MarketFactorDelta" vOutput(ColsOldStyle.OBSGroupNo, 1) = "OBSGroupNo" vOutput(ColsOldStyle.OBSTicketNo, 1) = "OBSTicketNo" vOutput(ColsOldStyle.ProductDelta, 1) = "ProductDelta" vOutput(ColsOldStyle.ProductDeltaChange, 1) = "ProductDeltaChange" vOutput(ColsOldStyle.RealDelta, 1) = "RealDelta" vOutput(ColsOldStyle.RealDeltaChange, 1) = "RealDeltaChange" vOutput(ColsOldStyle.RiskClass, 1) = "RiskClass" vOutput(ColsOldStyle.ScenarioName, 1) = "ScenarioName" vOutput(ColsOldStyle.Index, 1) = "Index" vOutput(ColsOldStyle.Tenor, 1) = "Tenor" vOutput(ColsOldStyle.Tranche, 1) = "Tranche" vOutput(ColsOldStyle.BookType, 1) = "BookType" vOutput(ColsOldStyle.StartDate, 1) = "StartDate" vOutput(ColsOldStyle.TradeName, 1) = "TradeName" vOutput(ColsOldStyle.TradeType, 1) = "TradeType" vOutput(ColsOldStyle.Tv, 1) = "Tv" vOutput(ColsOldStyle.TVChange, 1) = "TVChange" vOutput(ColsOldStyle.UniversalCurrency, 1) = "UniversalCurrency" Set oFso = New FileSystemObject Set xDom = New DOMDocument With xDom .async = True .validateOnParse = False End With For Each sFile In modScenario.Config.FileGroups("trade_valuation_info", QuoteDate) 'Get the source file WriteToLog LogTypes.loginfo, "Converting TradeValuation file (" & sFile & ")" If oFso.FileExists(sFile) Then Set oFile = oFso.GetFile(sFile) 'Load source file into xml dom, and loop thru each trade 'bLoaded = xDom.Load(oFile.Path) Set oStrm = oFile.OpenAsTextStream oStrm.ReadLine bLoaded = xDom.loadXML(oStrm.ReadAll) If bLoaded Then For Each xElem In xDom.selectNodes("ValuationReport/TradeReport") If Config.DebugLevel = 1 Then WriteToLog LogTypes.LogDebug, "Converting trade (" & xElem.selectSingleNode("TradeDetails/TradeName").Text & ")" 'Build the sub report per trade, this is the bit that does the work. vTrade = GenerateScenario(xElem, QuoteDate, ReportAlias, SkewGridPattern) If IsArray(vTrade) Then 'store in master array ReDim Preserve vOutput(ColsOldStyle.NoOfCols, UBound(vOutput, 2) + UBound(vTrade, 2)) For lRowSub = LBound(vTrade, 2) To UBound(vTrade, 2) lRow = lRow + 1 For lField = LBound(vTrade) To UBound(vTrade) vOutput(lField, lRow) = vTrade(lField, lRowSub) Next lField Next lRowSub Else WriteToLog LogTypes.LogWarning, "Conversion of data for trade(" & xElem.selectSingleNode("TradeDetails/TradeName").Text & ")" _ & " returned an empty array, TradeType(" & xElem.selectSingleNode("TradeDetails/TradeType").Text & ")" End If Next xElem Else WriteToLog LogTypes.LogError, "A required source file is corrupt and cannot be loaded : " & sFile End If Else On Error GoTo 0 WriteToLog LogTypes.LogError, "A required source file is missing : " & sFile End If Next sFile BuildReport = vOutput Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..BuildReport" _ , Err.Source & ":" & Err.Description Exit Function Resume 0 End Function Private Function GenerateScenario(TradeValueInfo As IXMLDOMElement _ , ByVal QuoteDate As Date _ , ByVal ReportAlias As String _ , Optional ByVal SkewGridPattern As String) As Variant Dim dbEquivAttach As Double Dim dbEquivDetach As Double Dim dbAttachSens As Double Dim dbDetachSens As Double Dim dbCorrDeltaDetach As Double Dim dbCorrDeltaAttach As Double Dim dbCorrDeltaBaseDetach As Double Dim dbCorrDeltaBaseAttach As Double Dim sRegions As String Dim sCalibration As String Dim sPortfolio As String Dim sIndex As String Dim vRegions As Variant Dim vTenors As Variant Dim vTranches As Variant Dim vSkewTable As Variant Dim sTicket As String Dim sRiskCl As String Dim sTradeName As String Dim lMaturity As Long Dim lValid As Long Dim vReturn As Variant Dim sCalibFullPath As String Dim iRegion As Integer Dim iMat As Integer Dim iTranche As Integer Dim iNoTranche As Integer Dim sCCY As String Dim dFX As Double Dim sSkewsRoot As String Dim sTrancheAlias As String Dim sStartDate As String Dim sGroup As String Dim vRiskClassDetails As Variant Dim bIsValid As Boolean Dim bCalcTrueTVChange As Boolean Dim dLastTVChange As Double Dim vTenorDates As Variant Dim dRollDate As Date On Error GoTo GenErr 'Get the trade value information from the xml blob sTicket = TradeValueInfo.selectSingleNode("TradeDetails/TicketNum").Text sGroup = TradeValueInfo.selectSingleNode("TradeDetails/DealGroupBy").Text sRiskCl = TradeValueInfo.selectSingleNode("TradeDetails/RiskClass").Text sTradeName = TradeValueInfo.selectSingleNode("TradeDetails/TradeName").Text lMaturity = CDate(TradeValueInfo.selectSingleNode("TradeDetails/Maturity").Text) sStartDate = TradeValueInfo.selectSingleNode("TradeDetails/StartDate").Text 'get xml data data If Not TradeValueInfo.selectNodes("ValuationInfoReport/o/r") Is Nothing Then GetTradeValueData TradeValueInfo, dbEquivAttach, dbEquivDetach, dbAttachSens, dbDetachSens, sCCY, bIsValid Else GetTradeValueData_TVXML TradeValueInfo, dbEquivAttach, dbEquivDetach, dbAttachSens, dbDetachSens, sCCY, bIsValid End If If Not bIsValid Then Exit Function dFX = modScenario.FxObject.FxSpotRate(QuoteDate, sCCY, RegionCutsFX.EMEA) dbAttachSens = dbAttachSens * dFX dbDetachSens = dbDetachSens * dFX If Config.DebugLevel = 1 Then WriteToLog LogTypes.LogDebug, "ValuationInfo" & vbTab & sTradeName & vbTab & dbEquivAttach & vbTab _ & dbEquivDetach & vbTab & dbAttachSens & vbTab & dbDetachSens & vbTab & sCCY End If 'Get RiskCL If Not Config.RiskClassStatic.Exists(sRiskCl) Then WriteToLog LogTypes.LogError, "Unknown RiskClass :" & sRiskCl & ", ignoring. (Ticket:" & sTicket & " TradeName:" & sTradeName Exit Function End If vRiskClassDetails = Config.RiskClassStatic(sRiskCl) sRegions = vRiskClassDetails(ColsRiskCl.IndexRegion) sCalibration = vRiskClassDetails(ColsRiskCl.CalibrationName) lValid = 1 'put in base valuation data, not needed really, but olap wont work without it for LBCBR ReDim vReturn(ColsOldStyle.NoOfCols, 1) vReturn(ColsOldStyle.TradeName, lValid) = sTradeName vReturn(ColsOldStyle.RiskClass, lValid) = sRiskCl vReturn(ColsOldStyle.Group, lValid) = sRiskCl & "_" & sTicket vReturn(ColsOldStyle.OBSTicketNo, lValid) = sTicket vReturn(ColsOldStyle.OBSGroupNo, lValid) = sGroup vReturn(ColsOldStyle.StartDate, lValid) = sStartDate vReturn(ColsOldStyle.CCY, lValid) = sCCY vReturn(ColsOldStyle.TVChange, lValid) = 0 'Get the relevant skew grid vRegions = Split(sRegions, "_") sSkewsRoot = GetSkewgridRootPath(QuoteDate, sCalibration) sCalibFullPath = sSkewsRoot & "\" & sCalibration & ".txt" vSkewTable = modScenario.Config.SkewGrid(sCalibFullPath) 'Get the tenor list, assume that the tenor list is the same for both regions if there are mulitple ones. modScenario.Config.RegionDetails vRegions(LBound(vRegions)), sIndex, sPortfolio, vTranches, vTenors, dRollDate ReDim vTenorsDates(LBound(vTenors) To UBound(vTenors)) For iMat = LBound(vTenors) To UBound(vTenors) If dRollDate = 0 Then vTenorsDates(iMat) = Format(GetIndexMaturityDate(vTenors(iMat), QuoteDate), "ddmmmyy") Else vTenorsDates(iMat) = Format(GetIndexMaturityDateForRollDate(vTenors(iMat), dRollDate), "ddmmmyy") End If Next iMat 'derive the Base Att/Det pts. dbCorrDeltaBaseAttach = CorrelationDeltaInterpFromSkewTable(dbEquivAttach / 100, lMaturity, vSkewTable, vTenorsDates) dbCorrDeltaBaseDetach = CorrelationDeltaInterpFromSkewTable(dbEquivDetach / 100, lMaturity, vSkewTable, vTenorsDates) 'for each region, do For iRegion = LBound(vRegions) To UBound(vRegions) modScenario.Config.RegionDetails vRegions(iRegion), sIndex, sPortfolio, vTranches, vTenors, dRollDate ReDim vTenorsDates(LBound(vTenors) To UBound(vTenors)) For iMat = LBound(vTenors) To UBound(vTenors) If dRollDate = 0 Then vTenorsDates(iMat) = Format(GetIndexMaturityDate(vTenors(iMat), QuoteDate), "ddmmmyy") Else vTenorsDates(iMat) = Format(GetIndexMaturityDateForRollDate(vTenors(iMat), dRollDate), "ddmmmyy") End If Next iMat For iMat = LBound(vTenors) To UBound(vTenors) dLastTVChange = 0 For iTranche = 1 To UBound(vTranches) 'if this is lbcr, need to override Eq to 0 If vTranches(iTranche) = "Eq" And ReportAlias = "lbcr" Then vTranches(iTranche) = "0" End If If InStr(1, SkewGridPattern, "#TranchEnd#") Then If iTranche = UBound(vTranches) Then Exit For End If sTrancheAlias = vTranches(iTranche) & "-" & vTranches(iTranche + 1) Else sTrancheAlias = vTranches(iTranche) End If lValid = lValid + 1 ReDim Preserve vReturn(ColsOldStyle.NoOfCols, lValid) If iTranche = UBound(vTranches) Then bCalcTrueTVChange = False sCalibFullPath = BuildSkewGridPath(sSkewsRoot, SkewGridPattern, sPortfolio _ , vTenors(iMat), sCalibration, vTranches(iTranche)) Else bCalcTrueTVChange = True sCalibFullPath = BuildSkewGridPath(sSkewsRoot, SkewGridPattern, sPortfolio _ , vTenors(iMat), sCalibration, vTranches(iTranche) _ , vTranches(iTranche + 1)) End If 'basic data vReturn(ColsOldStyle.TradeName, lValid) = sTradeName vReturn(ColsOldStyle.RiskClass, lValid) = sRiskCl vReturn(ColsOldStyle.Group, lValid) = sRiskCl & "_" & sTicket vReturn(ColsOldStyle.OBSTicketNo, lValid) = sTicket vReturn(ColsOldStyle.OBSGroupNo, lValid) = sGroup vReturn(ColsOldStyle.StartDate, lValid) = sStartDate vReturn(ColsOldStyle.CCY, lValid) = sCCY 'Added for CMV2.0 - Hack for the scenario name 'Replace Eq with 0 vReturn(ColsOldStyle.ScenarioName, lValid) = Replace(sTrancheAlias, "Eq", 0) & vRegions(iRegion) & vTenors(iMat) vReturn(ColsOldStyle.Index, lValid) = sIndex vReturn(ColsOldStyle.Tenor, lValid) = vTenors(iMat) vReturn(ColsOldStyle.Tranche, lValid) = sTrancheAlias 'Delta vSkewTable = modScenario.Config.SkewGrid(sCalibFullPath) dbCorrDeltaDetach = CorrelationDeltaInterpFromSkewTable(dbEquivDetach / 100, lMaturity, vSkewTable, vTenorsDates) dbCorrDeltaAttach = CorrelationDeltaInterpFromSkewTable(dbEquivAttach / 100, lMaturity, vSkewTable, vTenorsDates) 'Hibbinni: Since CMV 2.5 we multiply this by -1 as the bump direction has been reversed. vReturn(ColsOldStyle.TVChange, lValid) = -((dbCorrDeltaBaseDetach - dbCorrDeltaDetach) * dbDetachSens _ + (dbCorrDeltaBaseAttach - dbCorrDeltaAttach) * dbAttachSens) * 100 * -1 vReturn(ColsOldStyle.DeltaChange, lValid) = vReturn(ColsOldStyle.TVChange, lValid) - dLastTVChange dLastTVChange = vReturn(ColsOldStyle.TVChange, lValid) Next iTranche Next iMat Next iRegion GenerateScenario = vReturn On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..GenerateScenario" _ , Err.Source & ":" & Err.Description Resume 0 End Function Private Sub GetTradeValueData_TVXML(TradeValueXml As IXMLDOMElement _ , Attach As Double _ , Detach As Double _ , AttachSensitivity As Double _ , DetachSensitivity As Double _ , ValuationCcy As String _ , isValidCaOutput As Boolean) Dim lAttrib As Long Dim sAttach As String Dim sWidth As String Dim sDetach As String Dim sAttachSensitivity As String Dim sDetachSensitivity As String On Error GoTo GenErr 'Check data exists If TradeValueXml.selectSingleNode("TVReport/EquivSubord") Is Nothing _ Or TradeValueXml.selectSingleNode("TVReport/EquivWidth") Is Nothing _ Or TradeValueXml.selectSingleNode("TVReport/dBasePVdRho") Is Nothing _ Or TradeValueXml.selectSingleNode("TVReport/dTopPVdRho") Is Nothing _ Or TradeValueXml.selectSingleNode("TVReport/TV") Is Nothing Then isValidCaOutput = False Exit Sub End If sAttach = TradeValueXml.selectSingleNode("TVReport/EquivSubord").Attributes.getNamedItem("value").Text If IsNumeric(sAttach) Then Attach = sAttach End If sWidth = TradeValueXml.selectSingleNode("TVReport/EquivWidth").Attributes.getNamedItem("value").Text If IsNumeric(sWidth) Then Detach = Attach + sWidth End If sAttachSensitivity = TradeValueXml.selectSingleNode("TVReport/dBasePVdRho").Attributes.getNamedItem("value").Text If IsNumeric(sAttachSensitivity) Then AttachSensitivity = sAttachSensitivity End If sDetachSensitivity = TradeValueXml.selectSingleNode("TVReport/dTopPVdRho").Attributes.getNamedItem("value").Text If IsNumeric(sDetachSensitivity) Then DetachSensitivity = sDetachSensitivity End If ValuationCcy = TradeValueXml.selectSingleNode("TVReport/TV").Attributes.getNamedItem("currency").Text isValidCaOutput = True On Error GoTo 0 Exit Sub GenErr: modScenario.AppErrors.Raise thisObjectName & "..GetTradeValueData_TVXML" _ , Err.Source & ":" & Err.Description Resume 0 End Sub Private Sub GetTradeValueData(TradeValueXml As IXMLDOMElement _ , Attach As Double _ , Detach As Double _ , AttachSensitivity As Double _ , DetachSensitivity As Double _ , ValuationCcy As String _ , isValidCaOutput As Boolean) Dim lRow As Long Dim lRowAttach As Long Dim lRowWidth As Long Dim lColAttDetach As Long Dim lColSensitivity As Long Dim lCol As Long Dim dWidth As Double Dim xRow As IXMLDOMElement Dim bStart As Boolean Dim lCurrentFound As Long Const maxColsToFind As Long = 2 Const maxRowsToFind As Long = 2 On Error GoTo GenErr For Each xRow In TradeValueXml.selectNodes("ValuationInfoReport/o/r") lCurrentFound = 0 'Get valuation ccy If xRow.childNodes(0).Text = Config.TvRowTradeValuekey Then ValuationCcy = xRow.childNodes(2).Text 'Get main measures If Not bStart Then If xRow.childNodes(0).Text = Config.TvStartkey Then bStart = True For lCol = 0 To xRow.childNodes.length - 1 Select Case xRow.childNodes(lCol).Text Case Config.TvcolAttachkey lColAttDetach = lCol lCurrentFound = lCurrentFound + 1 Case Config.TvcolSensitivitykey lColSensitivity = lCol lCurrentFound = lCurrentFound + 1 End Select If lCurrentFound = maxColsToFind Then Exit For End If Next lCol If lCurrentFound <> maxColsToFind Then WriteToLog LogTypes.LogWarning, "XML appears incomplete for this trade, unable to find required data. (Initial Value is 0) " _ & "Attach/Detach Column : " & lColAttDetach & ". Sensitivity Column : " & lColSensitivity Exit Sub End If End If Else Select Case xRow.childNodes(0).Text Case Config.TvRowAttachkey If IsNumeric(xRow.childNodes(lColAttDetach).Text) Then Attach = xRow.childNodes(lColAttDetach).Text Else WriteToLog LogTypes.LogWarning, "Attach value is non numeric (" & xRow.childNodes(lColAttDetach).Text & ")" Exit Sub End If If IsNumeric(xRow.childNodes(lColSensitivity).Text) Then AttachSensitivity = xRow.childNodes(lColSensitivity).Text Else On Error GoTo 0 WriteToLog LogTypes.LogWarning, "AttachSensitivity value is non numeric (" & xRow.childNodes(lColSensitivity).Text & ")" Exit Sub End If Detach = Attach + dWidth lCurrentFound = lCurrentFound + 1 Case Config.TvRowWidthkey If IsNumeric(xRow.childNodes(lColAttDetach).Text) Then dWidth = xRow.childNodes(lColAttDetach).Text Else On Error GoTo 0 WriteToLog LogTypes.LogWarning, "Width value is non numeric (" & xRow.childNodes(lColAttDetach).Text & ")" Exit Sub End If If IsNumeric(xRow.childNodes(lColSensitivity).Text) Then DetachSensitivity = xRow.childNodes(lColSensitivity).Text Else On Error GoTo 0 WriteToLog LogTypes.LogWarning, "DetachSensitivity value is non numeric (" & xRow.childNodes(lColSensitivity).Text & ")" Exit Sub End If Detach = Attach + dWidth lCurrentFound = lCurrentFound + 1 End Select If lCurrentFound = maxRowsToFind Then Exit For End If Next xRow 'If it wasn't found, return false isValidCaOutput = bStart On Error GoTo 0 Exit Sub GenErr: modScenario.AppErrors.Raise thisObjectName & "..GetTradeValueData" _ , Err.Source & ":" & Err.Description Resume 0 End Sub Private Function GetSkewgridRootPath(ByVal QuoteDate As Date _ , ByVal CalibrationName As String) Dim lShift As Long Dim sPath As String Dim oFso As FileSystemObject On Error GoTo GenErr If dcGridPaths Is Nothing Then Set dcGridPaths = New Dictionary End If 'supress the error that may be returned because folder doesn't exist If Not dcGridPaths.Exists(QuoteDate & "~" & CalibrationName) Then On Error Resume Next sPath = modScenario.Config.Path("skew_grids", QuoteDate) Set oFso = New FileSystemObject If sPath = "" Or Not oFso.FileExists(oFso.BuildPath(sPath, CalibrationName & ".txt")) Then If sPath <> "" Then WriteToLog LogTypes.LogWarning, "Archive folder exists for " _ & Format(QuoteDate, "dd-mmm-yy") & ", but no skew grids for " & CalibrationName & " on path : " & oFso.BuildPath(sPath, CalibrationName & ".txt") End If For lShift = 1 To Config.MaxSkewShift sPath = modScenario.Config.Path("skew_grids", QuoteDate - lShift) If Err.Number <> 0 Then WriteToLog LogTypes.LogWarning, Err.Description ElseIf Not oFso.FileExists(oFso.BuildPath(sPath, CalibrationName & ".txt")) Then WriteToLog LogTypes.LogWarning, "Archive folder exists for " _ & Format(QuoteDate - lShift, "dd-mmm-yy") & ", but no skew grids for " & CalibrationName & " on path : " & oFso.BuildPath(sPath, CalibrationName & ".txt") sPath = "" Else Exit For End If Next lShift End If On Error GoTo GenErr If sPath = "" Then On Error GoTo 0 modScenario.AppErrors.Raise thisObjectName & "..GetSkewgridRootPath" _ , "There are no archived skewgrids in date range start(" & QuoteDate & _ ") end(" & QuoteDate - Config.MaxSkewShift & ")" Else dcGridPaths.Add QuoteDate & "~" & CalibrationName, sPath End If End If GetSkewgridRootPath = dcGridPaths.Item(QuoteDate & "~" & CalibrationName) On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..GetSkewgridRootPath" _ , Err.Source & ":" & Err.Description Resume 0 End Function Private Function BuildSkewGridPath(ByVal SkewGridRoot As String _ , ByVal SkewGridPattern As String _ , ByVal Portfolio As String _ , ByVal Tenor As String _ , ByVal Calibration As String _ , ByVal TranchStart As String _ , Optional ByVal TranchEnd As String) As String On Error GoTo GenErr SkewGridPattern = Replace(SkewGridPattern, "#Portfolio#", Portfolio) SkewGridPattern = Replace(SkewGridPattern, "#Tenor#", Tenor) SkewGridPattern = Replace(SkewGridPattern, "#Calibration#", Calibration) SkewGridPattern = Replace(SkewGridPattern, "#TranchStart#", TranchStart) SkewGridPattern = Replace(SkewGridPattern, "#TranchEnd#", TranchEnd) BuildSkewGridPath = SkewGridRoot & "\" & SkewGridPattern & ".txt" On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..BuildSkewGridPath" _ , Err.Source & ":" & Err.Description Resume Next End Function ' ' 'Private Function GetIndexForRegion(ByVal Region As String) As String 'On Error GoTo GenErr ' Select Case Region ' Case "USD" ' GetIndexForRegion = "CDX" ' Case "EUR" ' GetIndexForRegion = "iTraxx" ' Case Else ' modScenario.AppErrors.Raise thisObjectName & "..GetIndexForRegion" _ ' , "Region : " & Region & ", does not have an Index within the config." ' End Select 'On Error GoTo 0 ' Exit Function 'GenErr: ' modScenario.AppErrors.Raise thisObjectName & "..GetIndexForRegion" _ ' , Err.Source & ":" & Err.Description ' Resume Next 'End Function Private Function CorrelationDeltaInterpFromSkewTable(dAttachment, maturity, vSkewTable, TenorsDates) On Error GoTo GenErr ' find the parameter cells in the table Dim nrow, i, k, NumPages, nRowsPerPage, offset Dim iSh As Integer Dim iDate As Integer Dim dMat As Date Dim sMat As String Dim n1, n2 Dim bIsRequired As Boolean Dim iActual As Integer nrow = UBound(vSkewTable) For i = 2 To nrow If Not IsNumeric(vSkewTable(i, 1)) Then nRowsPerPage = i - 1 Exit For End If Next i If nRowsPerPage = 0 Then nRowsPerPage = nrow NumPages = nrow / nRowsPerPage ReDim skewPagesParams(1 To 1) ReDim trancheBounds(1 To nRowsPerPage - 2, 1 To 1) ReDim skewValues(1 To nRowsPerPage - 2, 1 To 1) For k = 1 To NumPages offset = (k - 1) * nRowsPerPage 'Get the maturity date from teh skew grid n1 = InStr(vSkewTable(offset + 1, 1), "MAT=") n2 = InStr(n1, vSkewTable(offset + 1, 1), ":") sMat = Mid(vSkewTable(offset + 1, 1), n1 + 4, n2 - n1 - 4) 'Work out if this tenor is required bIsRequired = False For i = LBound(TenorsDates) To UBound(TenorsDates) If TenorsDates(i) = sMat Then bIsRequired = True Exit For 'Else 'Stop End If Next i 'If it is, prepare for passing If bIsRequired Then iActual = iActual + 1 ReDim Preserve skewPagesParams(1 To iActual) ReDim Preserve trancheBounds(1 To nRowsPerPage - 2, 1 To iActual) ReDim Preserve skewValues(1 To nRowsPerPage - 2, 1 To iActual) skewPagesParams(iActual) = vSkewTable(offset + 1, 1) For i = 1 To nRowsPerPage - 2 trancheBounds(i, iActual) = vSkewTable(offset + 2 + i, 1) skewValues(i, iActual) = vSkewTable(offset + 1 + i, 2) Next i End If Next k CorrelationDeltaInterpFromSkewTable = CorrelationDeltaInterp(dAttachment, maturity, skewPagesParams, TransposeArray(trancheBounds), TransposeArray(skewValues)) On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..CorrelationDeltaInterpFromSkewTable" _ , Err.Source & ":" & Err.Description Resume 0 End Function ' given a detachment and a maturity ' and for each skew page: ' parameters(cell(1,1)) ' the skew boundaries(cell(2,1)..(n,1)) ' the skew values (cell(2,2)..(n,2)) ' this will return the dinterpolated skew value ' (linear in maturity. Cubic spline natural bc's in attachment Private Function CorrelationDeltaInterp(dAttachment, maturity, skewPageParms, trancheBounds, skewValues) ' stage 1 - extract from skewPageParms the maturity dates ' is found between "MAT=" and ":" Dim n ' no ofpages Dim i, n1, n2, sDat On Error GoTo GenErr n = UBound(skewPageParms) - LBound(skewPageParms) + 1 ReDim pageIndices(1 To n) As Long ReDim pageDates(1 To n) As Long For i = 1 To n n1 = InStr(skewPageParms(i), "MAT=") If n1 <= 0 Then CorrelationDeltaInterp = "Cannot find date in " + skewPageParms(i) Exit Function End If n2 = InStr(n1, skewPageParms(i), ":") sDat = Mid(skewPageParms(i), n1 + 4, n2 - n1 - 4) pageIndices(i) = i sDat = Left(sDat, 2) + "-" + Mid(sDat, 3, 3) + "-" + Right(sDat, Len(sDat) - 5) pageDates(i) = CDate(sDat) Next i ' find our date in this range ' organise interpolation Dim gDate, iDate, fDate, ns gDate = SimpleInterp(maturity, pageDates, pageIndices) If gDate < 1 Then gDate = 1 If gDate > n Then gDate = n iDate = Int(gDate) fDate = gDate - iDate ' build interpolated skew curve ns = UBound(trancheBounds, 2) ReDim TrancheBoundsLessZero(1 To ns) ReDim InterpolatedSkews(1 To ns) For i = 1 To ns TrancheBoundsLessZero(i) = trancheBounds(1, i) If fDate = 0 Then InterpolatedSkews(i) = skewValues(iDate, i) Else InterpolatedSkews(i) = (1 - fDate) * skewValues(iDate, i) + fDate * skewValues(iDate + 1, i) End If Next i CorrelationDeltaInterp = SplineMe(dAttachment, TrancheBoundsLessZero, InterpolatedSkews) On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..CorrelationDeltaInterp" _ , Err.Source & ":" & Err.Description Resume Next End Function Public Function GetIndexMaturityDateForRollDate(ByVal Tenor As String _ , Optional ByVal QuoteDate As Date) As Date Dim lYearShift As Long Dim lMaturityMonth As Long lMaturityMonth = Month(QuoteDate) Select Case UCase(Tenor) Case "3YR", "3Y", "03Y" lYearShift = 3 Case "5YR", "5Y", "05Y" lYearShift = 5 Case "7YR", "7Y", "07Y" lYearShift = 7 Case "10YR", "10Y" lYearShift = 10 End Select GetIndexMaturityDateForRollDate = DateSerial(Year(QuoteDate) + lYearShift, lMaturityMonth + 3, 20) End Function Public Function GetIndexMaturityDate(ByVal Tenor As String _ , Optional ByVal QuoteDate As Date) As Date On Error GoTo GenErr Dim lMaturityMonth As Long Dim lYearShift As Long Dim bIsRollMonth As Boolean If QuoteDate = 0 Then QuoteDate = Date Select Case Month(QuoteDate) Case Is > 8 lMaturityMonth = 12 If Month(QuoteDate) = 9 Then bIsRollMonth = True Case Is > 2 lMaturityMonth = 6 If Month(QuoteDate) = 3 Then bIsRollMonth = True Case Else lMaturityMonth = 0 If Month(QuoteDate) = 12 Then bIsRollMonth = True End Select If Day(QuoteDate) < 20 And bIsRollMonth Then lMaturityMonth = lMaturityMonth - 6 End If Select Case UCase(Tenor) Case "3YR", "3Y", "03Y" lYearShift = 3 Case "5YR", "5Y", "05Y" lYearShift = 5 Case "7YR", "7Y", "07Y" lYearShift = 7 Case "10YR", "10Y" lYearShift = 10 End Select GetIndexMaturityDate = DateSerial(Year(QuoteDate) + lYearShift, lMaturityMonth, 20) If GetIndexMaturityDate = 0 Then Stop End If Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..CdsMaturityDate" _ , Err.Description Resume Next End Function Private Function SplineMe(x, px, py) On Error GoTo GenErr Dim vpx, vpy, n, nr If TypeName(px) = "Range" Then n = px.Cells.Count nr = px.Rows.Count Else n = UBound(px) nr = UBound(px) End If If x <= px(1) Then SplineMe = py(1) ElseIf x >= px(n) Then SplineMe = py(n) Else Dim d If nr > 1 Then SplineMe = Spline(px, py, False, 0, False, 0, x, False) End If End If On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..SplineMe" _ , Err.Source & ":" & Err.Description Resume Next End Function Private Function SimpleInterp(ByVal x As Double _ , ByVal px As Variant _ , ByVal py As Variant) Dim lCount As Long On Error GoTo GenErr If x <= px(1) Then SimpleInterp = py(1) ElseIf x >= px(UBound(py)) Then SimpleInterp = py(UBound(py)) Else For lCount = LBound(px) To UBound(px) - 1 If x >= px(lCount) And x <= px(lCount + 1) Then SimpleInterp = (py(lCount + 1) - py(lCount)) / (px(lCount + 1) - px(lCount)) * (x - px(lCount)) + py(lCount) Exit For End If Next lCount End If On Error GoTo 0 Exit Function GenErr: modScenario.AppErrors.Raise thisObjectName & "..SimpleInterp" _ , Err.Source & ":" & Err.Description Resume Next End Function Function TransposeArray(ByVal MyArray As Variant _ , Optional ByVal TransposeForExcel As Boolean) As Variant Dim x As Long, Y As Long Dim vTemp As Variant Dim xShift As Integer Dim yShift As Integer If IsEmpty(MyArray) Then Exit Function End If If TransposeForExcel Then xShift = 1 - LBound(MyArray, 2) yShift = 1 - LBound(MyArray) End If On Error GoTo errTranspose ReDim vTemp(LBound(MyArray, 2) + xShift To UBound(MyArray, 2) + xShift, _ LBound(MyArray) + yShift To UBound(MyArray) + yShift) For Y = LBound(MyArray) To UBound(MyArray) For x = LBound(MyArray, 2) To UBound(MyArray, 2) vTemp(x + xShift, Y + yShift) = MyArray(Y, x) Next x Next Y TransposeArray = vTemp On Error GoTo 0 Exit Function errTranspose: modScenario.AppErrors.Raise "modUtil..TransposeArray", _ "Error Transposing array." & vbLf, _ Err.Source & ":" & Err.Description End Function '############################################################################################# ' PROPERTIES '############################################################################################# Public Property Get AppErrors() As AppError If oAppErrorObject Is Nothing Then Set oAppErrorObject = New AppError End If Set AppErrors = oAppErrorObject End Property Public Property Get Config() As Config If oConfig Is Nothing Then Set oConfig = New Config If CommandLineParams.ConfigFilePath = "" Then Set oConfig.ConfigFile = xmlLoad(App.Path, "app.xml") Else Dim sPath As String sPath = CommandLineParams.ConfigFilePath Set oConfig.ConfigFile = xmlLoad(FSO.GetParentFolderName(sPath), FSO.GetFileName(sPath)) End If End If Set Config = oConfig End Property Public Property Set Config(RHS As Config) Set oConfig = RHS End Property Public Property Get FSO() As FileSystemObject If oFso Is Nothing Then Set oFso = New FileSystemObject End If Set FSO = New FileSystemObject End Property Sub test() MsgBox FxObject.FxSpotRate("8 april 2006", "GBP", RegionCutsFX.EMEA) End Sub Public Property Get FxObject() As FX If oFX Is Nothing Then Set oFX = New FX Set FxObject = oFX End Property Public Property Get RunDate() As Date dQuoteDate = CommandLineParams.QuoteDate If dQuoteDate = 0 Then dQuoteDate = AddWeekDay(Date, -1) End If RunDate = dQuoteDate End Property Public Property Get CommandLineParams() As CmdLineParams 'Get the quote date if its been past in command line, else default to previous business date If oCmdLine Is Nothing Then Set oCmdLine = New CmdLineParams Set CommandLineParams = oCmdLine End Property |
QXR0cmlidXRlIFZCX05hbWUgPSAibW9kU2NlbmFyaW8iCk9wdGlvbiBFeHBsaWNpdApPcHRpb24gQmFzZSAxCgpQcml2YXRlIG9Db25maWcgICAgICAgICAgICAgQXMgQ29uZmlnClByaXZhdGUgb0FwcEVycm9yT2JqZWN0ICAgICBBcyBBcHBFcnJvcgpQcml2YXRlIG9GWCAgICAgICAgICAgICAgICAgQXMgRlgKUHJpdmF0ZSBvRnNvICAgICAgICAgICAgICAgIEFzIEZpbGVTeXN0ZW1PYmplY3QKUHJpdmF0ZSBkQmF0Y2hRdW90ZURhdGUgICAgIEFzIERhdGUKUHJpdmF0ZSB2Umlza0NsICAgICAgICAgICAgIEFzIFZhcmlhbnQKUHJpdmF0ZSBvQ21kTGluZSAgICAgICAgICAgIEFzIENtZExpbmVQYXJhbXMKUHJpdmF0ZSBkUXVvdGVEYXRlICAgICAgICAgIEFzIERhdGUKUHJpdmF0ZSBkY0dyaWRQYXRocyAgICAgICAgIEFzIERpY3Rpb25hcnkKCgpQcml2YXRlIEVudW0gQ29sc1NjZW5hcmlvCiAgICBSaXNrQ2xhc3MgPSAxCiAgICBUaWNrZXQKICAgIEJvb2tUeXBlCiAgICBCb29rUmVnaW9uCiAgICBUcmFkZU5hbWUKICAgIFNjZW5hcmlvTmFtZQogICAgSW5kZXgKICAgIFRyYW5jaGUKICAgIFRlbm9yCiAgICBEZWx0YQogICAgCiAgICBMYXN0RmllbGQKICAgIE5vT2ZDb2xzID0gTGFzdEZpZWxkIC0gMQpFbmQgRW51bQoKClByaXZhdGUgRW51bSBDb2xzT2xkU3R5bGUKICAgIFRyYWRlTmFtZSA9IDEKICAgIEdyb3VwCiAgICBPQlNUaWNrZXRObwogICAgT0JTR3JvdXBObwogICAgVHJhZGVUeXBlCiAgICBSaXNrQ2xhc3MKICAgIENDWQogICAgU3RhcnREYXRlCiAgICBDdXJ2ZQogICAgQnVja2V0CiAgICBCdWNrZXREYXRlCiAgICBUdgogICAgUmVhbERlbHRhCiAgICBEZWx0YQogICAgUHJvZHVjdERlbHRhCiAgICBNYXJrZXRGYWN0b3JEZWx0YQogICAgTGlib3JHYW1tYQogICAgVFZDaGFuZ2UKICAgIERlbHRhQ2hhbmdlCiAgICBQcm9kdWN0RGVsdGFDaGFuZ2UKICAgIFVuaXZlcnNhbEN1cnJlbmN5CiAgICBSZWFsRGVsdGFDaGFuZ2UKICAgIENyZWRpdEN1cnZlU2hvY2tzCiAgICBTY2VuYXJpb05hbWUKICAgIEluZGV4CiAgICBUZW5vcgogICAgVHJhbmNoZQogICAgQm9va1R5cGUKICAgIAogICAgTGFzdEZpZWxkCiAgICBOb09mQ29scyA9IExhc3RGaWVsZCAtIDEKCkVuZCBFbnVtCgoKClByaXZhdGUgQ29uc3QgdGhpc09iamVjdE5hbWUgICAgQXMgU3RyaW5nID0gIm1vZFNjZW5hcmlvIgpQcml2YXRlIENvbnN0IFBJVk9UX0RBVEFfUkFOR0UgIEFzIFN0cmluZyA9ICJQaXZvdERhdGEiClByaXZhdGUgQ29uc3QgUElWT1RfVEFCTEVfTkFNRSAgQXMgU3RyaW5nID0gIlNjZW5hcmlvUGl2b3RUYWJsZSIKCgonUmV2IDI5IC0gICBBZGRpdGlvbiBvZiBSZWdpb25Ub0luZGV4IGZ1bmN0aW9uIHdpdGhpbiBjb25maWcgY2xhc3MsIHJlbmFtZSBvZiBvdXRwdXQgZmllbGRzICsgdGhlIGFkZHRpb24gb2YgYm9va3JlZ2lvbiwKJyAgICAgICAgICAgSW5kZXhuYW1lLCB0cmFuY2hlICYgdGVub3IgYXMgbmV3IGRhdGEgaXRlbXMuCiAgICAKJyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwonICAgTUVUSE9EUwonIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjClB1YmxpYyBTdWIgTWFpbigpCiAgICBEaW0geEJhdGNoICAgICAgQXMgSVhNTERPTUVsZW1lbnQKICAgIERpbSB4Q29weVRvICAgICBBcyBJWE1MRE9NRWxlbWVudAogICAgRGltIHhMaXN0ICAgICAgIEFzIElYTUxET01Ob2RlTGlzdAogICAgRGltIHhMaXN0MiAgICAgIEFzIElYTUxET01Ob2RlTGlzdAogICAgRGltIHZGZWVkICAgICAgIEFzIFZhcmlhbnQKICAgIERpbSBzUGF0aCAgICAgICBBcyBTdHJpbmcKICAgICAgICAKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgIAogICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5sb2dpbmZvLCAiQmF0Y2ggY3JlYXRpb24gYmVnaW5zIGZvciBRdW90ZWRhdGU6IiAmIEZvcm1hdChSdW5EYXRlLCAiZGQtbW1tLXl5eXkiKSAmICIgVmVyc2lvbjogIiAmIEFwcC5NYWpvciAmICIuIiAmIEFwcC5NaW5vciAmICI6IiAmIEFwcC5SZXZpc2lvbgogICAgCiAgICBTZXQgeExpc3QgPSBtb2RTY2VuYXJpby5Db25maWcuQ29uZmlnRmlsZS5zZWxlY3ROb2RlcygiYXBwL2JhdGNoZXMvYmF0Y2giKQogICAgJ2ZvciBlYWNoIGJhdGNoIGRvCiAgICBGb3IgRWFjaCB4QmF0Y2ggSW4geExpc3QKICAgICAgICAnaWYgYWxsIGJhdGNoZXMgYXJlIG1lYW50IHRvIGJlIHJ1biwgb3IgdGhpcyBzcGVjaWZpYyBiYXRjaCBpcyBvbmUgdGFyZ2V0ZWQgYnkgY29tbWFuZCBsaW5lIHBhcmFtCiAgICAgICAgSWYgQ29tbWFuZExpbmVQYXJhbXMuQmF0Y2hOYW1lID0gIiIgT3IgVUNhc2UoeEJhdGNoLmdldEF0dHJpYnV0ZSgibmFtZSIpKSA9IENvbW1hbmRMaW5lUGFyYW1zLkJhdGNoTmFtZSBUaGVuCiAgICAgICAgICAgIAogICAgICAgICAgICAnQ3JlYXRlIHRoZSByZXBvcnQgZGF0YSBmcm9tIHRyYWRlIHZhbHVhdGlvbiBzb3VyY2UgZGF0YQogICAgICAgICAgICBXcml0ZVRvTG9nIExvZ1R5cGVzLmxvZ2luZm8sICJDcmVhdGluZyByZXBvcnQgZGF0YSBmb3IgYmF0Y2ggKCIgJiB4QmF0Y2guZ2V0QXR0cmlidXRlKCJuYW1lIikgJiAiKSIKICAgICAgICAgICAgdkZlZWQgPSBCdWlsZFJlcG9ydChkUXVvdGVEYXRlLCB4QmF0Y2guZ2V0QXR0cmlidXRlKCJuYW1lIiksIHhCYXRjaC5nZXRBdHRyaWJ1dGUoInNrZXdfcGF0dGVybiIpKQogICAgICAgICAgICAKICAgICAgICAgICAgJ09VdHB1dCB0byB3aGVyZSBldmVyCiAgICAgICAgICAgIHNQYXRoID0gIiIKICAgICAgICAgICAgSWYgQ29uZmlnLkVudmlyb25tZW50ID0gIlVBVCIgVGhlbgogICAgICAgICAgICAgICAgSWYgTm90IElzTnVsbCh4QmF0Y2guZ2V0QXR0cmlidXRlKCJvdXRwdXRfcGF0aF91YXQiKSkgQW5kIHhCYXRjaC5nZXRBdHRyaWJ1dGUoIm91dHB1dF9wYXRoX3VhdCIpIDw+ICIiIFRoZW4KICAgICAgICAgICAgICAgICAgICBzUGF0aCA9IENvbmZpZy5PdmVybGF5RGF0ZVN0cmluZyh4QmF0Y2guZ2V0QXR0cmlidXRlKCJvdXRwdXRfcGF0aF91YXQiKSwgZFF1b3RlRGF0ZSkKICAgICAgICAgICAgICAgIEVuZCBJZgogICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgSWYgc1BhdGggPSAiIiBUaGVuCiAgICAgICAgICAgICAgICBzUGF0aCA9IENvbmZpZy5PdmVybGF5RGF0ZVN0cmluZyh4QmF0Y2guZ2V0QXR0cmlidXRlKCJvdXRwdXRfcGF0aCIpLCBkUXVvdGVEYXRlKQogICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5sb2dpbmZvLCAiT3V0cHV0aW5nIGRhdGEgdG8gKCIgJiBzUGF0aCAmICIpIgogICAgICAgICAgICAKICAgICAgICAgICAgU2F2ZUZlZWQgZFF1b3RlRGF0ZSwgc1BhdGgsIHZGZWVkCiAgICAgICAgICAgIAogICAgICAgICAgICAnRnJlZSBVbmxpbWl0ZWQgJ0NvcHkgVG8ncyEhIQogICAgICAgICAgICBTZXQgeExpc3QyID0geEJhdGNoLnNlbGVjdE5vZGVzKCJjb3B5dG8iKQogICAgICAgICAgICBGb3IgRWFjaCB4Q29weVRvIEluIHhMaXN0MgogICAgICAgICAgICAgICAgc1BhdGggPSBDb25maWcuT3ZlcmxheURhdGVTdHJpbmcoeENvcHlUby5nZXRBdHRyaWJ1dGUoIm91dHB1dF9wYXRoIiksIGRRdW90ZURhdGUpCiAgICAgICAgICAgICAgICBTYXZlRmVlZCBkUXVvdGVEYXRlLCBzUGF0aCwgdkZlZWQKICAgICAgICAgICAgTmV4dCB4Q29weVRvCiAgICAgICAgICAgIAogICAgICAgIEVuZCBJZgogICAgTmV4dCB4QmF0Y2gKICAgIAogICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5sb2dpbmZvLCAiR2VuZXJhdGlvbiBDT01QTEVURSIKICAgICdjbG9zZSBkb3duCk9uIEVycm9yIEdvVG8gMAogICAgRXhpdCBTdWIKR2VuRXJyOgogICAgJ0xvZyBhbnkgZXJyb3JzIHRoYXQgY3JvcCB1cAogICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dFcnJvciwgQXBwRXJyb3JzLkRlc2NyaXB0aW9uCkVuZCBTdWIKCgpQdWJsaWMgU3ViIFNhdmVGZWVkKEJ5VmFsIFF1b3RlRGF0ZSBBcyBEYXRlIF8KICAgICAgICAgICAgICAgICAgICAgICAgLCBCeVZhbCBQYXRoIEFzIFN0cmluZyBfCiAgICAgICAgICAgICAgICAgICAgICAgICwgQnlWYWwgRmVlZERhdGEgQXMgVmFyaWFudCkKICAgIERpbSBsUm93ICAgIEFzIExvbmcKICAgIERpbSBsRmllbGQgIEFzIExvbmcKICAgIERpbSBzU3RyaW5nIEFzIFN0cmluZwogICAgRGltIG9TdHJtICAgQXMgVGV4dFN0cmVhbQpPbiBFcnJvciBHb1RvIEdlbkVycgogICAgU2V0IG9TdHJtID0gRlNPLkNyZWF0ZVRleHRGaWxlKFBhdGgsIFF1b3RlRGF0ZSkKICAgIEZvciBsUm93ID0gTEJvdW5kKEZlZWREYXRhLCAyKSBUbyBVQm91bmQoRmVlZERhdGEsIDIpCiAgICAgICAgc1N0cmluZyA9IEZlZWREYXRhKExCb3VuZChGZWVkRGF0YSksIGxSb3cpCiAgICAgICAgRm9yIGxGaWVsZCA9IExCb3VuZChGZWVkRGF0YSkgKyAxIFRvIFVCb3VuZChGZWVkRGF0YSkKICAgICAgICAgICAgc1N0cmluZyA9IHNTdHJpbmcgJiB2YlRhYiAmIEZlZWREYXRhKGxGaWVsZCwgbFJvdykKICAgICAgICBOZXh0IGxGaWVsZAogICAgICAgIG9TdHJtLldyaXRlTGluZSAoc1N0cmluZykKICAgIE5leHQgbFJvdwogICAgb1N0cm0uV3JpdGUgKHNTdHJpbmcpCiAgICBvU3RybS5DbG9zZQogICAgU2V0IG9TdHJtID0gRlNPLkNyZWF0ZVRleHRGaWxlKExlZnQoUGF0aCwgTGVuKFBhdGgpIC0gTGVuKEZTTy5HZXRFeHRlbnNpb25OYW1lKFBhdGgpKSAtIDEpICYgIi5kb25lIikKT24gRXJyb3IgR29UbyAwCiAgICBFeGl0IFN1YgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5TYXZlRmVlZCIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgMApFbmQgU3ViCgoKUHJpdmF0ZSBGdW5jdGlvbiBCdWlsZFJlcG9ydChCeVZhbCBRdW90ZURhdGUgQXMgRGF0ZSBfCiAgICAgICAgICAgICAgICAgICAgICAgICwgQnlWYWwgUmVwb3J0QWxpYXMgQXMgU3RyaW5nIF8KICAgICAgICAgICAgICAgICAgICAgICAgLCBCeVZhbCBTa2V3R3JpZFBhdHRlcm4gQXMgU3RyaW5nKSBBcyBWYXJpYW50CiAgICBEaW0geEVsZW0gICBBcyBJWE1MRE9NRWxlbWVudAogICAgRGltIHhEb20gICAgQXMgRE9NRG9jdW1lbnQKICAgIERpbSB2T3V0cHV0IEFzIFZhcmlhbnQKICAgIERpbSB2VHJhZGUgIEFzIFZhcmlhbnQKICAgIERpbSBsUm93ICAgIEFzIExvbmcKICAgIERpbSBsUm93U3ViIEFzIExvbmcKICAgIERpbSBsRmllbGQgIEFzIExvbmcKICAgIERpbSBvRnNvICAgIEFzIEZpbGVTeXN0ZW1PYmplY3QKICAgIERpbSBvRmlsZSAgIEFzIEZpbGUKICAgIERpbSBzRmlsZSAgIEFzIFZhcmlhbnQKICAgIERpbSBiTG9hZGVkIEFzIEJvb2xlYW4KICAgIERpbSBvU3RybSAgIEFzIFRleHRTdHJlYW0KICAgIApPbiBFcnJvciBHb1RvIEdlbkVycgogICAgbFJvdyA9IDEKICAgIFJlRGltIHZPdXRwdXQoQ29sc09sZFN0eWxlLk5vT2ZDb2xzLCAxKQogICAgCiAgICAnU2VlZCBvdXRwdXQgYXJyYXkKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLkJ1Y2tldCwgMSkgPSAiQnVja2V0IgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuQnVja2V0RGF0ZSwgMSkgPSAiQnVja2V0RGF0ZSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLkNDWSwgMSkgPSAiQ0NZIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuQ3JlZGl0Q3VydmVTaG9ja3MsIDEpID0gIkNyZWRpdEN1cnZlU2hvY2tzIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuQ3VydmUsIDEpID0gIkN1cnZlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuRGVsdGEsIDEpID0gIkRlbHRhIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuRGVsdGFDaGFuZ2UsIDEpID0gIkRlbHRhQ2hhbmdlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuR3JvdXAsIDEpID0gIkdyb3VwIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuTGlib3JHYW1tYSwgMSkgPSAiTGlib3JHYW1tYSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLk1hcmtldEZhY3RvckRlbHRhLCAxKSA9ICJNYXJrZXRGYWN0b3JEZWx0YSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLk9CU0dyb3VwTm8sIDEpID0gIk9CU0dyb3VwTm8iCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5PQlNUaWNrZXRObywgMSkgPSAiT0JTVGlja2V0Tm8iCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5Qcm9kdWN0RGVsdGEsIDEpID0gIlByb2R1Y3REZWx0YSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLlByb2R1Y3REZWx0YUNoYW5nZSwgMSkgPSAiUHJvZHVjdERlbHRhQ2hhbmdlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuUmVhbERlbHRhLCAxKSA9ICJSZWFsRGVsdGEiCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5SZWFsRGVsdGFDaGFuZ2UsIDEpID0gIlJlYWxEZWx0YUNoYW5nZSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLlJpc2tDbGFzcywgMSkgPSAiUmlza0NsYXNzIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuU2NlbmFyaW9OYW1lLCAxKSA9ICJTY2VuYXJpb05hbWUiCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5JbmRleCwgMSkgPSAiSW5kZXgiCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5UZW5vciwgMSkgPSAiVGVub3IiCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5UcmFuY2hlLCAxKSA9ICJUcmFuY2hlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuQm9va1R5cGUsIDEpID0gIkJvb2tUeXBlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuU3RhcnREYXRlLCAxKSA9ICJTdGFydERhdGUiCiAgICB2T3V0cHV0KENvbHNPbGRTdHlsZS5UcmFkZU5hbWUsIDEpID0gIlRyYWRlTmFtZSIKICAgIHZPdXRwdXQoQ29sc09sZFN0eWxlLlRyYWRlVHlwZSwgMSkgPSAiVHJhZGVUeXBlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuVHYsIDEpID0gIlR2IgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuVFZDaGFuZ2UsIDEpID0gIlRWQ2hhbmdlIgogICAgdk91dHB1dChDb2xzT2xkU3R5bGUuVW5pdmVyc2FsQ3VycmVuY3ksIDEpID0gIlVuaXZlcnNhbEN1cnJlbmN5IgogICAgCiAgICBTZXQgb0ZzbyA9IE5ldyBGaWxlU3lzdGVtT2JqZWN0CiAgICBTZXQgeERvbSA9IE5ldyBET01Eb2N1bWVudAogICAgV2l0aCB4RG9tCiAgICAgICAgLmFzeW5jID0gVHJ1ZQogICAgICAgIC52YWxpZGF0ZU9uUGFyc2UgPSBGYWxzZQogICAgRW5kIFdpdGgKICAgIAogICAgRm9yIEVhY2ggc0ZpbGUgSW4gbW9kU2NlbmFyaW8uQ29uZmlnLkZpbGVHcm91cHMoInRyYWRlX3ZhbHVhdGlvbl9pbmZvIiwgUXVvdGVEYXRlKQogICAgICAgICdHZXQgdGhlIHNvdXJjZSBmaWxlCiAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5sb2dpbmZvLCAiQ29udmVydGluZyBUcmFkZVZhbHVhdGlvbiBmaWxlICgiICYgc0ZpbGUgJiAiKSIKICAgICAgICBJZiBvRnNvLkZpbGVFeGlzdHMoc0ZpbGUpIFRoZW4KICAgICAgICAgICAgU2V0IG9GaWxlID0gb0Zzby5HZXRGaWxlKHNGaWxlKQogICAgICAgICAgICAKICAgICAgICAgICAgJ0xvYWQgc291cmNlIGZpbGUgaW50byB4bWwgZG9tLCBhbmQgbG9vcCB0aHJ1IGVhY2ggdHJhZGUKICAgICAgICAgICAgJ2JMb2FkZWQgPSB4RG9tLkxvYWQob0ZpbGUuUGF0aCkKICAgICAgICAgICAgU2V0IG9TdHJtID0gb0ZpbGUuT3BlbkFzVGV4dFN0cmVhbQogICAgICAgICAgICBvU3RybS5SZWFkTGluZQogICAgICAgICAgICBiTG9hZGVkID0geERvbS5sb2FkWE1MKG9TdHJtLlJlYWRBbGwpCiAgICAgICAgICAgIElmIGJMb2FkZWQgVGhlbgogICAgICAgICAgICAgICAgRm9yIEVhY2ggeEVsZW0gSW4geERvbS5zZWxlY3ROb2RlcygiVmFsdWF0aW9uUmVwb3J0L1RyYWRlUmVwb3J0IikKICAgICAgICAgICAgICAgICAgICBJZiBDb25maWcuRGVidWdMZXZlbCA9IDEgVGhlbiBXcml0ZVRvTG9nIExvZ1R5cGVzLkxvZ0RlYnVnLCAiQ29udmVydGluZyB0cmFkZSAoIiAmIHhFbGVtLnNlbGVjdFNpbmdsZU5vZGUoIlRyYWRlRGV0YWlscy9UcmFkZU5hbWUiKS5UZXh0ICYgIikiCiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgJ0J1aWxkIHRoZSBzdWIgcmVwb3J0IHBlciB0cmFkZSwgdGhpcyBpcyB0aGUgYml0IHRoYXQgZG9lcyB0aGUgd29yay4KICAgICAgICAgICAgICAgICAgICB2VHJhZGUgPSBHZW5lcmF0ZVNjZW5hcmlvKHhFbGVtLCBRdW90ZURhdGUsIFJlcG9ydEFsaWFzLCBTa2V3R3JpZFBhdHRlcm4pCiAgICAgICAgICAgICAgICAgICAgSWYgSXNBcnJheSh2VHJhZGUpIFRoZW4KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgJ3N0b3JlIGluIG1hc3RlciBhcnJheQogICAgICAgICAgICAgICAgICAgICAgICBSZURpbSBQcmVzZXJ2ZSB2T3V0cHV0KENvbHNPbGRTdHlsZS5Ob09mQ29scywgVUJvdW5kKHZPdXRwdXQsIDIpICsgVUJvdW5kKHZUcmFkZSwgMikpCiAgICAgICAgICAgICAgICAgICAgICAgIEZvciBsUm93U3ViID0gTEJvdW5kKHZUcmFkZSwgMikgVG8gVUJvdW5kKHZUcmFkZSwgMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxSb3cgPSBsUm93ICsgMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9yIGxGaWVsZCA9IExCb3VuZCh2VHJhZGUpIFRvIFVCb3VuZCh2VHJhZGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdk91dHB1dChsRmllbGQsIGxSb3cpID0gdlRyYWRlKGxGaWVsZCwgbFJvd1N1YikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5leHQgbEZpZWxkCiAgICAgICAgICAgICAgICAgICAgICAgIE5leHQgbFJvd1N1YgogICAgICAgICAgICAgICAgICAgIEVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dXYXJuaW5nLCAiQ29udmVyc2lvbiBvZiBkYXRhIGZvciB0cmFkZSgiICYgeEVsZW0uc2VsZWN0U2luZ2xlTm9kZSgiVHJhZGVEZXRhaWxzL1RyYWRlTmFtZSIpLlRleHQgJiAiKSIgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmICIgcmV0dXJuZWQgYW4gZW1wdHkgYXJyYXksIFRyYWRlVHlwZSgiICYgeEVsZW0uc2VsZWN0U2luZ2xlTm9kZSgiVHJhZGVEZXRhaWxzL1RyYWRlVHlwZSIpLlRleHQgJiAiKSIKICAgICAgICAgICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgICAgIE5leHQgeEVsZW0KICAgICAgICAgICAgRWxzZQogICAgICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dFcnJvciwgIkEgcmVxdWlyZWQgc291cmNlIGZpbGUgaXMgY29ycnVwdCBhbmQgY2Fubm90IGJlIGxvYWRlZCA6ICIgJiBzRmlsZQogICAgICAgICAgICBFbmQgSWYKICAgICAgICBFbHNlCiAgICAgICAgICAgIE9uIEVycm9yIEdvVG8gMAogICAgICAgICAgICBXcml0ZVRvTG9nIExvZ1R5cGVzLkxvZ0Vycm9yLCAiQSByZXF1aXJlZCBzb3VyY2UgZmlsZSBpcyBtaXNzaW5nIDogIiAmIHNGaWxlCiAgICAgICAgRW5kIElmCiAgICBOZXh0IHNGaWxlCiAgICAKICAgIEJ1aWxkUmVwb3J0ID0gdk91dHB1dAogICAgRXhpdCBGdW5jdGlvbgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5CdWlsZFJlcG9ydCIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBFeGl0IEZ1bmN0aW9uCiAgICBSZXN1bWUgMApFbmQgRnVuY3Rpb24KCgpQcml2YXRlIEZ1bmN0aW9uIEdlbmVyYXRlU2NlbmFyaW8oVHJhZGVWYWx1ZUluZm8gQXMgSVhNTERPTUVsZW1lbnQgXwogICAgICAgICAgICAgICAgICAgICwgQnlWYWwgUXVvdGVEYXRlIEFzIERhdGUgXwogICAgICAgICAgICAgICAgICAgICwgQnlWYWwgUmVwb3J0QWxpYXMgQXMgU3RyaW5nIF8KICAgICAgICAgICAgICAgICAgICAsIE9wdGlvbmFsIEJ5VmFsIFNrZXdHcmlkUGF0dGVybiBBcyBTdHJpbmcpIEFzIFZhcmlhbnQKICAgIAogICAgRGltIGRiRXF1aXZBdHRhY2ggICAgICAgQXMgRG91YmxlCiAgICBEaW0gZGJFcXVpdkRldGFjaCAgICAgICBBcyBEb3VibGUKICAgIERpbSBkYkF0dGFjaFNlbnMgICAgICAgIEFzIERvdWJsZQogICAgRGltIGRiRGV0YWNoU2VucyAgICAgICAgQXMgRG91YmxlCiAgICBEaW0gZGJDb3JyRGVsdGFEZXRhY2ggICBBcyBEb3VibGUKICAgIERpbSBkYkNvcnJEZWx0YUF0dGFjaCAgIEFzIERvdWJsZQogICAgRGltIGRiQ29yckRlbHRhQmFzZURldGFjaCBBcyBEb3VibGUKICAgIERpbSBkYkNvcnJEZWx0YUJhc2VBdHRhY2ggQXMgRG91YmxlCiAgICAKICAgIERpbSBzUmVnaW9ucyAgICAgICAgICAgIEFzIFN0cmluZwogICAgRGltIHNDYWxpYnJhdGlvbiAgICAgICAgQXMgU3RyaW5nCiAgICBEaW0gc1BvcnRmb2xpbyAgICAgICAgICBBcyBTdHJpbmcKICAgIERpbSBzSW5kZXggICAgICAgICAgICAgIEFzIFN0cmluZwogICAgRGltIHZSZWdpb25zICAgICAgICAgICAgQXMgVmFyaWFudAogICAgRGltIHZUZW5vcnMgICAgICAgICAgICAgQXMgVmFyaWFudAogICAgRGltIHZUcmFuY2hlcyAgICAgICAgICAgQXMgVmFyaWFudAogICAgRGltIHZTa2V3VGFibGUgICAgICAgICAgQXMgVmFyaWFudAogICAgRGltIHNUaWNrZXQgICAgICAgICAgICAgQXMgU3RyaW5nCiAgICBEaW0gc1Jpc2tDbCAgICAgICAgICAgICBBcyBTdHJpbmcKICAgIERpbSBzVHJhZGVOYW1lICAgICAgICAgIEFzIFN0cmluZwogICAgRGltIGxNYXR1cml0eSAgICAgICAgICAgQXMgTG9uZwogICAgRGltIGxWYWxpZCAgICAgICAgICAgICAgQXMgTG9uZwogICAgRGltIHZSZXR1cm4gICAgICAgICAgICAgQXMgVmFyaWFudAogICAgRGltIHNDYWxpYkZ1bGxQYXRoICAgICAgQXMgU3RyaW5nCiAgICBEaW0gaVJlZ2lvbiAgICAgICAgICAgICBBcyBJbnRlZ2VyCiAgICBEaW0gaU1hdCAgICAgICAgICAgICAgICBBcyBJbnRlZ2VyCiAgICBEaW0gaVRyYW5jaGUgICAgICAgICAgICBBcyBJbnRlZ2VyCiAgICBEaW0gaU5vVHJhbmNoZSAgICAgICAgICBBcyBJbnRlZ2VyCiAgICBEaW0gc0NDWSAgICAgICAgICAgICAgICBBcyBTdHJpbmcKICAgIERpbSBkRlggICAgICAgICAgICAgICAgIEFzIERvdWJsZQogICAgRGltIHNTa2V3c1Jvb3QgICAgICAgICAgQXMgU3RyaW5nCiAgICBEaW0gc1RyYW5jaGVBbGlhcyAgICAgICBBcyBTdHJpbmcKICAgIERpbSBzU3RhcnREYXRlICAgICAgICAgIEFzIFN0cmluZwogICAgRGltIHNHcm91cCAgICAgICAgICAgICAgQXMgU3RyaW5nCiAgICBEaW0gdlJpc2tDbGFzc0RldGFpbHMgICBBcyBWYXJpYW50CiAgICBEaW0gYklzVmFsaWQgICAgICAgICAgICBBcyBCb29sZWFuCiAgICBEaW0gYkNhbGNUcnVlVFZDaGFuZ2UgICBBcyBCb29sZWFuCiAgICBEaW0gZExhc3RUVkNoYW5nZSAgICAgICBBcyBEb3VibGUKICAgIERpbSB2VGVub3JEYXRlcyAgICAgICAgIEFzIFZhcmlhbnQKICAgIERpbSBkUm9sbERhdGUgICAgICAgICAgIEFzIERhdGUKICAgIApPbiBFcnJvciBHb1RvIEdlbkVycgogICAgJ0dldCB0aGUgdHJhZGUgdmFsdWUgaW5mb3JtYXRpb24gZnJvbSB0aGUgeG1sIGJsb2IKICAgIHNUaWNrZXQgPSBUcmFkZVZhbHVlSW5mby5zZWxlY3RTaW5nbGVOb2RlKCJUcmFkZURldGFpbHMvVGlja2V0TnVtIikuVGV4dAogICAgc0dyb3VwID0gVHJhZGVWYWx1ZUluZm8uc2VsZWN0U2luZ2xlTm9kZSgiVHJhZGVEZXRhaWxzL0RlYWxHcm91cEJ5IikuVGV4dAogICAgc1Jpc2tDbCA9IFRyYWRlVmFsdWVJbmZvLnNlbGVjdFNpbmdsZU5vZGUoIlRyYWRlRGV0YWlscy9SaXNrQ2xhc3MiKS5UZXh0CiAgICBzVHJhZGVOYW1lID0gVHJhZGVWYWx1ZUluZm8uc2VsZWN0U2luZ2xlTm9kZSgiVHJhZGVEZXRhaWxzL1RyYWRlTmFtZSIpLlRleHQKICAgIGxNYXR1cml0eSA9IENEYXRlKFRyYWRlVmFsdWVJbmZvLnNlbGVjdFNpbmdsZU5vZGUoIlRyYWRlRGV0YWlscy9NYXR1cml0eSIpLlRleHQpCiAgICBzU3RhcnREYXRlID0gVHJhZGVWYWx1ZUluZm8uc2VsZWN0U2luZ2xlTm9kZSgiVHJhZGVEZXRhaWxzL1N0YXJ0RGF0ZSIpLlRleHQKICAgIAogICAgJ2dldCB4bWwgZGF0YSBkYXRhCiAgICBJZiBOb3QgVHJhZGVWYWx1ZUluZm8uc2VsZWN0Tm9kZXMoIlZhbHVhdGlvbkluZm9SZXBvcnQvby9yIikgSXMgTm90aGluZyBUaGVuCiAgICAgICAgR2V0VHJhZGVWYWx1ZURhdGEgVHJhZGVWYWx1ZUluZm8sIGRiRXF1aXZBdHRhY2gsIGRiRXF1aXZEZXRhY2gsIGRiQXR0YWNoU2VucywgZGJEZXRhY2hTZW5zLCBzQ0NZLCBiSXNWYWxpZAogICAgRWxzZQogICAgICAgIEdldFRyYWRlVmFsdWVEYXRhX1RWWE1MIFRyYWRlVmFsdWVJbmZvLCBkYkVxdWl2QXR0YWNoLCBkYkVxdWl2RGV0YWNoLCBkYkF0dGFjaFNlbnMsIGRiRGV0YWNoU2Vucywgc0NDWSwgYklzVmFsaWQKICAgIEVuZCBJZgogICAgCiAgICBJZiBOb3QgYklzVmFsaWQgVGhlbiBFeGl0IEZ1bmN0aW9uCiAgICBkRlggPSBtb2RTY2VuYXJpby5GeE9iamVjdC5GeFNwb3RSYXRlKFF1b3RlRGF0ZSwgc0NDWSwgUmVnaW9uQ3V0c0ZYLkVNRUEpCiAgICBkYkF0dGFjaFNlbnMgPSBkYkF0dGFjaFNlbnMgKiBkRlgKICAgIGRiRGV0YWNoU2VucyA9IGRiRGV0YWNoU2VucyAqIGRGWAogICAgCiAgICBJZiBDb25maWcuRGVidWdMZXZlbCA9IDEgVGhlbgogICAgICAgIFdyaXRlVG9Mb2cgTG9nVHlwZXMuTG9nRGVidWcsICJWYWx1YXRpb25JbmZvIiAmIHZiVGFiICYgc1RyYWRlTmFtZSAmIHZiVGFiICYgZGJFcXVpdkF0dGFjaCAmIHZiVGFiIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgZGJFcXVpdkRldGFjaCAmIHZiVGFiICYgZGJBdHRhY2hTZW5zICYgdmJUYWIgJiBkYkRldGFjaFNlbnMgJiB2YlRhYiAmIHNDQ1kKICAgIEVuZCBJZgogICAgCiAgICAnR2V0IFJpc2tDTAogICAgSWYgTm90IENvbmZpZy5SaXNrQ2xhc3NTdGF0aWMuRXhpc3RzKHNSaXNrQ2wpIFRoZW4KICAgICAgICBXcml0ZVRvTG9nIExvZ1R5cGVzLkxvZ0Vycm9yLCAiVW5rbm93biBSaXNrQ2xhc3MgOiIgJiBzUmlza0NsICYgIiwgaWdub3JpbmcuIChUaWNrZXQ6IiAmIHNUaWNrZXQgJiAiIFRyYWRlTmFtZToiICYgc1RyYWRlTmFtZQogICAgICAgIEV4aXQgRnVuY3Rpb24KICAgIEVuZCBJZgogICAgCiAgICB2Umlza0NsYXNzRGV0YWlscyA9IENvbmZpZy5SaXNrQ2xhc3NTdGF0aWMoc1Jpc2tDbCkKICAgIHNSZWdpb25zID0gdlJpc2tDbGFzc0RldGFpbHMoQ29sc1Jpc2tDbC5JbmRleFJlZ2lvbikKICAgIHNDYWxpYnJhdGlvbiA9IHZSaXNrQ2xhc3NEZXRhaWxzKENvbHNSaXNrQ2wuQ2FsaWJyYXRpb25OYW1lKQogICAgCiAgICAKICAgIGxWYWxpZCA9IDEKICAgICdwdXQgaW4gYmFzZSB2YWx1YXRpb24gZGF0YSwgbm90IG5lZWRlZCByZWFsbHksIGJ1dCBvbGFwIHdvbnQgd29yayB3aXRob3V0IGl0IGZvciBMQkNCUgogICAgUmVEaW0gdlJldHVybihDb2xzT2xkU3R5bGUuTm9PZkNvbHMsIDEpCiAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5UcmFkZU5hbWUsIGxWYWxpZCkgPSBzVHJhZGVOYW1lCiAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5SaXNrQ2xhc3MsIGxWYWxpZCkgPSBzUmlza0NsCiAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5Hcm91cCwgbFZhbGlkKSA9IHNSaXNrQ2wgJiAiXyIgJiBzVGlja2V0CiAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5PQlNUaWNrZXRObywgbFZhbGlkKSA9IHNUaWNrZXQKICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLk9CU0dyb3VwTm8sIGxWYWxpZCkgPSBzR3JvdXAKICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLlN0YXJ0RGF0ZSwgbFZhbGlkKSA9IHNTdGFydERhdGUKICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLkNDWSwgbFZhbGlkKSA9IHNDQ1kKICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLlRWQ2hhbmdlLCBsVmFsaWQpID0gMAogICAgCiAgICAnR2V0IHRoZSByZWxldmFudCBza2V3IGdyaWQKICAgIHZSZWdpb25zID0gU3BsaXQoc1JlZ2lvbnMsICJfIikKICAgIHNTa2V3c1Jvb3QgPSBHZXRTa2V3Z3JpZFJvb3RQYXRoKFF1b3RlRGF0ZSwgc0NhbGlicmF0aW9uKQogICAgc0NhbGliRnVsbFBhdGggPSBzU2tld3NSb290ICYgIlwiICYgc0NhbGlicmF0aW9uICYgIi50eHQiCiAgICB2U2tld1RhYmxlID0gbW9kU2NlbmFyaW8uQ29uZmlnLlNrZXdHcmlkKHNDYWxpYkZ1bGxQYXRoKQogICAgCiAgICAnR2V0IHRoZSB0ZW5vciBsaXN0LCBhc3N1bWUgdGhhdCB0aGUgdGVub3IgbGlzdCBpcyB0aGUgc2FtZSBmb3IgYm90aCByZWdpb25zIGlmIHRoZXJlIGFyZSBtdWxpdHBsZSBvbmVzLgogICAgbW9kU2NlbmFyaW8uQ29uZmlnLlJlZ2lvbkRldGFpbHMgdlJlZ2lvbnMoTEJvdW5kKHZSZWdpb25zKSksIHNJbmRleCwgc1BvcnRmb2xpbywgdlRyYW5jaGVzLCB2VGVub3JzLCBkUm9sbERhdGUKICAgIFJlRGltIHZUZW5vcnNEYXRlcyhMQm91bmQodlRlbm9ycykgVG8gVUJvdW5kKHZUZW5vcnMpKQogICAgRm9yIGlNYXQgPSBMQm91bmQodlRlbm9ycykgVG8gVUJvdW5kKHZUZW5vcnMpCiAgICAgICAgSWYgZFJvbGxEYXRlID0gMCBUaGVuCiAgICAgICAgICAgIHZUZW5vcnNEYXRlcyhpTWF0KSA9IEZvcm1hdChHZXRJbmRleE1hdHVyaXR5RGF0ZSh2VGVub3JzKGlNYXQpLCBRdW90ZURhdGUpLCAiZGRtbW15eSIpCiAgICAgICAgRWxzZQogICAgICAgICAgICB2VGVub3JzRGF0ZXMoaU1hdCkgPSBGb3JtYXQoR2V0SW5kZXhNYXR1cml0eURhdGVGb3JSb2xsRGF0ZSh2VGVub3JzKGlNYXQpLCBkUm9sbERhdGUpLCAiZGRtbW15eSIpCiAgICAgICAgRW5kIElmCiAgICBOZXh0IGlNYXQKICAgIAogICAgJ2Rlcml2ZSB0aGUgQmFzZSBBdHQvRGV0IHB0cy4KICAgIGRiQ29yckRlbHRhQmFzZUF0dGFjaCA9IENvcnJlbGF0aW9uRGVsdGFJbnRlcnBGcm9tU2tld1RhYmxlKGRiRXF1aXZBdHRhY2ggLyAxMDAsIGxNYXR1cml0eSwgdlNrZXdUYWJsZSwgdlRlbm9yc0RhdGVzKQogICAgZGJDb3JyRGVsdGFCYXNlRGV0YWNoID0gQ29ycmVsYXRpb25EZWx0YUludGVycEZyb21Ta2V3VGFibGUoZGJFcXVpdkRldGFjaCAvIDEwMCwgbE1hdHVyaXR5LCB2U2tld1RhYmxlLCB2VGVub3JzRGF0ZXMpCiAgICAKICAgICdmb3IgZWFjaCByZWdpb24sIGRvCiAgICBGb3IgaVJlZ2lvbiA9IExCb3VuZCh2UmVnaW9ucykgVG8gVUJvdW5kKHZSZWdpb25zKQogICAgICAgIG1vZFNjZW5hcmlvLkNvbmZpZy5SZWdpb25EZXRhaWxzIHZSZWdpb25zKGlSZWdpb24pLCBzSW5kZXgsIHNQb3J0Zm9saW8sIHZUcmFuY2hlcywgdlRlbm9ycywgZFJvbGxEYXRlCiAgICAgICAgUmVEaW0gdlRlbm9yc0RhdGVzKExCb3VuZCh2VGVub3JzKSBUbyBVQm91bmQodlRlbm9ycykpCiAgICAgICAgRm9yIGlNYXQgPSBMQm91bmQodlRlbm9ycykgVG8gVUJvdW5kKHZUZW5vcnMpCiAgICAgICAgICAgIElmIGRSb2xsRGF0ZSA9IDAgVGhlbgogICAgICAgICAgICAgICAgdlRlbm9yc0RhdGVzKGlNYXQpID0gRm9ybWF0KEdldEluZGV4TWF0dXJpdHlEYXRlKHZUZW5vcnMoaU1hdCksIFF1b3RlRGF0ZSksICJkZG1tbXl5IikKICAgICAgICAgICAgRWxzZQogICAgICAgICAgICAgICAgdlRlbm9yc0RhdGVzKGlNYXQpID0gRm9ybWF0KEdldEluZGV4TWF0dXJpdHlEYXRlRm9yUm9sbERhdGUodlRlbm9ycyhpTWF0KSwgZFJvbGxEYXRlKSwgImRkbW1teXkiKQogICAgICAgICAgICBFbmQgSWYKICAgICAgICBOZXh0IGlNYXQKCiAgICAgICAgRm9yIGlNYXQgPSBMQm91bmQodlRlbm9ycykgVG8gVUJvdW5kKHZUZW5vcnMpCiAgICAgICAgICAgIGRMYXN0VFZDaGFuZ2UgPSAwCiAgICAgICAgICAgIEZvciBpVHJhbmNoZSA9IDEgVG8gVUJvdW5kKHZUcmFuY2hlcykKICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAnaWYgdGhpcyBpcyBsYmNyLCBuZWVkIHRvIG92ZXJyaWRlIEVxIHRvIDAKICAgICAgICAgICAgICAgIElmIHZUcmFuY2hlcyhpVHJhbmNoZSkgPSAiRXEiIEFuZCBSZXBvcnRBbGlhcyA9ICJsYmNyIiBUaGVuCiAgICAgICAgICAgICAgICAgICAgdlRyYW5jaGVzKGlUcmFuY2hlKSA9ICIwIgogICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgIAogICAgICAgICAgICAgICAgSWYgSW5TdHIoMSwgU2tld0dyaWRQYXR0ZXJuLCAiI1RyYW5jaEVuZCMiKSBUaGVuCiAgICAgICAgICAgICAgICAgICAgSWYgaVRyYW5jaGUgPSBVQm91bmQodlRyYW5jaGVzKSBUaGVuCiAgICAgICAgICAgICAgICAgICAgICAgIEV4aXQgRm9yCiAgICAgICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgICAgICAgICAgc1RyYW5jaGVBbGlhcyA9IHZUcmFuY2hlcyhpVHJhbmNoZSkgJiAiLSIgJiB2VHJhbmNoZXMoaVRyYW5jaGUgKyAxKQogICAgICAgICAgICAgICAgRWxzZQogICAgICAgICAgICAgICAgICAgIHNUcmFuY2hlQWxpYXMgPSB2VHJhbmNoZXMoaVRyYW5jaGUpCiAgICAgICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgbFZhbGlkID0gbFZhbGlkICsgMQogICAgICAgICAgICAgICAgUmVEaW0gUHJlc2VydmUgdlJldHVybihDb2xzT2xkU3R5bGUuTm9PZkNvbHMsIGxWYWxpZCkKICAgICAgICAgICAgICAgIElmIGlUcmFuY2hlID0gVUJvdW5kKHZUcmFuY2hlcykgVGhlbgogICAgICAgICAgICAgICAgICAgIGJDYWxjVHJ1ZVRWQ2hhbmdlID0gRmFsc2UKICAgICAgICAgICAgICAgICAgICBzQ2FsaWJGdWxsUGF0aCA9IEJ1aWxkU2tld0dyaWRQYXRoKHNTa2V3c1Jvb3QsIFNrZXdHcmlkUGF0dGVybiwgc1BvcnRmb2xpbyBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIHZUZW5vcnMoaU1hdCksIHNDYWxpYnJhdGlvbiwgdlRyYW5jaGVzKGlUcmFuY2hlKSkKICAgICAgICAgICAgICAgIEVsc2UKICAgICAgICAgICAgICAgICAgICBiQ2FsY1RydWVUVkNoYW5nZSA9IFRydWUKICAgICAgICAgICAgICAgICAgICBzQ2FsaWJGdWxsUGF0aCA9IEJ1aWxkU2tld0dyaWRQYXRoKHNTa2V3c1Jvb3QsIFNrZXdHcmlkUGF0dGVybiwgc1BvcnRmb2xpbyBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIHZUZW5vcnMoaU1hdCksIHNDYWxpYnJhdGlvbiwgdlRyYW5jaGVzKGlUcmFuY2hlKSBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIHZUcmFuY2hlcyhpVHJhbmNoZSArIDEpKQogICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICdiYXNpYyBkYXRhCiAgICAgICAgICAgICAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5UcmFkZU5hbWUsIGxWYWxpZCkgPSBzVHJhZGVOYW1lCiAgICAgICAgICAgICAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5SaXNrQ2xhc3MsIGxWYWxpZCkgPSBzUmlza0NsCiAgICAgICAgICAgICAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5Hcm91cCwgbFZhbGlkKSA9IHNSaXNrQ2wgJiAiXyIgJiBzVGlja2V0CiAgICAgICAgICAgICAgICB2UmV0dXJuKENvbHNPbGRTdHlsZS5PQlNUaWNrZXRObywgbFZhbGlkKSA9IHNUaWNrZXQKICAgICAgICAgICAgICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLk9CU0dyb3VwTm8sIGxWYWxpZCkgPSBzR3JvdXAKICAgICAgICAgICAgICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLlN0YXJ0RGF0ZSwgbFZhbGlkKSA9IHNTdGFydERhdGUKICAgICAgICAgICAgICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLkNDWSwgbFZhbGlkKSA9IHNDQ1kKICAgICAgICAgICAgICAgICdBZGRlZCBmb3IgQ01WMi4wIC0gSGFjayBmb3IgdGhlIHNjZW5hcmlvIG5hbWUKICAgICAgICAgICAgICAgICdSZXBsYWNlIEVxIHdpdGggMAogICAgICAgICAgICAgICAgdlJldHVybihDb2xzT2xkU3R5bGUuU2NlbmFyaW9OYW1lLCBsVmFsaWQpID0gUmVwbGFjZShzVHJhbmNoZUFsaWFzLCAiRXEiLCAwKSAmIHZSZWdpb25zKGlSZWdpb24pICYgdlRlbm9ycyhpTWF0KQogICAgICAgICAgICAgICAgdlJldHVybihDb2xzT2xkU3R5bGUuSW5kZXgsIGxWYWxpZCkgPSBzSW5kZXgKICAgICAgICAgICAgICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLlRlbm9yLCBsVmFsaWQpID0gdlRlbm9ycyhpTWF0KQogICAgICAgICAgICAgICAgdlJldHVybihDb2xzT2xkU3R5bGUuVHJhbmNoZSwgbFZhbGlkKSA9IHNUcmFuY2hlQWxpYXMKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgJ0RlbHRhCiAgICAgICAgICAgICAgICB2U2tld1RhYmxlID0gbW9kU2NlbmFyaW8uQ29uZmlnLlNrZXdHcmlkKHNDYWxpYkZ1bGxQYXRoKQogICAgICAgICAgICAgICAgZGJDb3JyRGVsdGFEZXRhY2ggPSBDb3JyZWxhdGlvbkRlbHRhSW50ZXJwRnJvbVNrZXdUYWJsZShkYkVxdWl2RGV0YWNoIC8gMTAwLCBsTWF0dXJpdHksIHZTa2V3VGFibGUsIHZUZW5vcnNEYXRlcykKICAgICAgICAgICAgICAgIGRiQ29yckRlbHRhQXR0YWNoID0gQ29ycmVsYXRpb25EZWx0YUludGVycEZyb21Ta2V3VGFibGUoZGJFcXVpdkF0dGFjaCAvIDEwMCwgbE1hdHVyaXR5LCB2U2tld1RhYmxlLCB2VGVub3JzRGF0ZXMpCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICdIaWJiaW5uaTogU2luY2UgQ01WIDIuNSB3ZSBtdWx0aXBseSB0aGlzIGJ5IC0xIGFzIHRoZSBidW1wIGRpcmVjdGlvbiBoYXMgYmVlbiByZXZlcnNlZC4KICAgICAgICAgICAgICAgIHZSZXR1cm4oQ29sc09sZFN0eWxlLlRWQ2hhbmdlLCBsVmFsaWQpID0gLSgoZGJDb3JyRGVsdGFCYXNlRGV0YWNoIC0gZGJDb3JyRGVsdGFEZXRhY2gpICogZGJEZXRhY2hTZW5zIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgKGRiQ29yckRlbHRhQmFzZUF0dGFjaCAtIGRiQ29yckRlbHRhQXR0YWNoKSAqIGRiQXR0YWNoU2VucykgKiAxMDAgKiAtMQogICAgICAgICAgICAgICAgdlJldHVybihDb2xzT2xkU3R5bGUuRGVsdGFDaGFuZ2UsIGxWYWxpZCkgPSB2UmV0dXJuKENvbHNPbGRTdHlsZS5UVkNoYW5nZSwgbFZhbGlkKSAtIGRMYXN0VFZDaGFuZ2UKICAgICAgICAgICAgICAgIGRMYXN0VFZDaGFuZ2UgPSB2UmV0dXJuKENvbHNPbGRTdHlsZS5UVkNoYW5nZSwgbFZhbGlkKQogICAgICAgICAgICBOZXh0IGlUcmFuY2hlCiAgICAgICAgTmV4dCBpTWF0CiAgICBOZXh0IGlSZWdpb24KICAgIEdlbmVyYXRlU2NlbmFyaW8gPSB2UmV0dXJuCk9uIEVycm9yIEdvVG8gMAogICAgRXhpdCBGdW5jdGlvbgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5HZW5lcmF0ZVNjZW5hcmlvIiBfCiAgICAgICAgICAgICAgICAsIEVyci5Tb3VyY2UgJiAiOiIgJiBFcnIuRGVzY3JpcHRpb24KICAgIFJlc3VtZSAwCkVuZCBGdW5jdGlvbgoKUHJpdmF0ZSBTdWIgR2V0VHJhZGVWYWx1ZURhdGFfVFZYTUwoVHJhZGVWYWx1ZVhtbCBBcyBJWE1MRE9NRWxlbWVudCBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBBdHRhY2ggQXMgRG91YmxlIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIERldGFjaCBBcyBEb3VibGUgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgQXR0YWNoU2Vuc2l0aXZpdHkgQXMgRG91YmxlIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIERldGFjaFNlbnNpdGl2aXR5IEFzIERvdWJsZSBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBWYWx1YXRpb25DY3kgQXMgU3RyaW5nIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIGlzVmFsaWRDYU91dHB1dCBBcyBCb29sZWFuKQoKICAgIERpbSBsQXR0cmliIEFzIExvbmcKICAgIERpbSBzQXR0YWNoIEFzIFN0cmluZwogICAgRGltIHNXaWR0aCAgQXMgU3RyaW5nCiAgICBEaW0gc0RldGFjaCBBcyBTdHJpbmcKICAgIERpbSBzQXR0YWNoU2Vuc2l0aXZpdHkgIEFzIFN0cmluZwogICAgRGltIHNEZXRhY2hTZW5zaXRpdml0eSAgQXMgU3RyaW5nCiAgICAKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgICdDaGVjayBkYXRhIGV4aXN0cwogICAgSWYgVHJhZGVWYWx1ZVhtbC5zZWxlY3RTaW5nbGVOb2RlKCJUVlJlcG9ydC9FcXVpdlN1Ym9yZCIpIElzIE5vdGhpbmcgXwogICAgT3IgVHJhZGVWYWx1ZVhtbC5zZWxlY3RTaW5nbGVOb2RlKCJUVlJlcG9ydC9FcXVpdldpZHRoIikgSXMgTm90aGluZyBfCiAgICBPciBUcmFkZVZhbHVlWG1sLnNlbGVjdFNpbmdsZU5vZGUoIlRWUmVwb3J0L2RCYXNlUFZkUmhvIikgSXMgTm90aGluZyBfCiAgICBPciBUcmFkZVZhbHVlWG1sLnNlbGVjdFNpbmdsZU5vZGUoIlRWUmVwb3J0L2RUb3BQVmRSaG8iKSBJcyBOb3RoaW5nIF8KICAgIE9yIFRyYWRlVmFsdWVYbWwuc2VsZWN0U2luZ2xlTm9kZSgiVFZSZXBvcnQvVFYiKSBJcyBOb3RoaW5nIFRoZW4KICAgICAgICAKICAgICAgICBpc1ZhbGlkQ2FPdXRwdXQgPSBGYWxzZQogICAgICAgIEV4aXQgU3ViCiAgICAKICAgIEVuZCBJZgogICAgICAgCiAgICBzQXR0YWNoID0gVHJhZGVWYWx1ZVhtbC5zZWxlY3RTaW5nbGVOb2RlKCJUVlJlcG9ydC9FcXVpdlN1Ym9yZCIpLkF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKCJ2YWx1ZSIpLlRleHQKICAgIElmIElzTnVtZXJpYyhzQXR0YWNoKSBUaGVuCiAgICAgICAgQXR0YWNoID0gc0F0dGFjaAogICAgRW5kIElmCiAgICAKICAgIHNXaWR0aCA9IFRyYWRlVmFsdWVYbWwuc2VsZWN0U2luZ2xlTm9kZSgiVFZSZXBvcnQvRXF1aXZXaWR0aCIpLkF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKCJ2YWx1ZSIpLlRleHQKICAgIElmIElzTnVtZXJpYyhzV2lkdGgpIFRoZW4KICAgICAgICBEZXRhY2ggPSBBdHRhY2ggKyBzV2lkdGgKICAgIEVuZCBJZgogICAgCiAgICBzQXR0YWNoU2Vuc2l0aXZpdHkgPSBUcmFkZVZhbHVlWG1sLnNlbGVjdFNpbmdsZU5vZGUoIlRWUmVwb3J0L2RCYXNlUFZkUmhvIikuQXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oInZhbHVlIikuVGV4dAogICAgSWYgSXNOdW1lcmljKHNBdHRhY2hTZW5zaXRpdml0eSkgVGhlbgogICAgICAgIEF0dGFjaFNlbnNpdGl2aXR5ID0gc0F0dGFjaFNlbnNpdGl2aXR5CiAgICBFbmQgSWYKICAgIAogICAgc0RldGFjaFNlbnNpdGl2aXR5ID0gVHJhZGVWYWx1ZVhtbC5zZWxlY3RTaW5nbGVOb2RlKCJUVlJlcG9ydC9kVG9wUFZkUmhvIikuQXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oInZhbHVlIikuVGV4dAogICAgSWYgSXNOdW1lcmljKHNEZXRhY2hTZW5zaXRpdml0eSkgVGhlbgogICAgICAgIERldGFjaFNlbnNpdGl2aXR5ID0gc0RldGFjaFNlbnNpdGl2aXR5CiAgICBFbmQgSWYKICAgICAgICAKICAgIFZhbHVhdGlvbkNjeSA9IFRyYWRlVmFsdWVYbWwuc2VsZWN0U2luZ2xlTm9kZSgiVFZSZXBvcnQvVFYiKS5BdHRyaWJ1dGVzLmdldE5hbWVkSXRlbSgiY3VycmVuY3kiKS5UZXh0CiAgICAgICAgCiAgICBpc1ZhbGlkQ2FPdXRwdXQgPSBUcnVlCk9uIEVycm9yIEdvVG8gMAogICAgRXhpdCBTdWIKR2VuRXJyOgogICAgbW9kU2NlbmFyaW8uQXBwRXJyb3JzLlJhaXNlIHRoaXNPYmplY3ROYW1lICYgIi4uR2V0VHJhZGVWYWx1ZURhdGFfVFZYTUwiIF8KICAgICAgICAgICAgICAgICwgRXJyLlNvdXJjZSAmICI6IiAmIEVyci5EZXNjcmlwdGlvbgogICAgUmVzdW1lIDAKRW5kIFN1YgoKCgpQcml2YXRlIFN1YiBHZXRUcmFkZVZhbHVlRGF0YShUcmFkZVZhbHVlWG1sIEFzIElYTUxET01FbGVtZW50IF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEF0dGFjaCBBcyBEb3VibGUgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRGV0YWNoIEFzIERvdWJsZSBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBBdHRhY2hTZW5zaXRpdml0eSBBcyBEb3VibGUgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRGV0YWNoU2Vuc2l0aXZpdHkgQXMgRG91YmxlIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIFZhbHVhdGlvbkNjeSBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgaXNWYWxpZENhT3V0cHV0IEFzIEJvb2xlYW4pCiAgICBEaW0gbFJvdyAgICAgICAgICAgIEFzIExvbmcKICAgIERpbSBsUm93QXR0YWNoICAgICAgQXMgTG9uZwogICAgRGltIGxSb3dXaWR0aCAgICAgICBBcyBMb25nCiAgICBEaW0gbENvbEF0dERldGFjaCAgIEFzIExvbmcKICAgIERpbSBsQ29sU2Vuc2l0aXZpdHkgQXMgTG9uZwogICAgRGltIGxDb2wgICAgICAgICAgICBBcyBMb25nCiAgICBEaW0gZFdpZHRoICAgICAgICAgIEFzIERvdWJsZQogICAgRGltIHhSb3cgICAgICAgICAgICBBcyBJWE1MRE9NRWxlbWVudAogICAgRGltIGJTdGFydCAgICAgICAgICBBcyBCb29sZWFuCiAgICBEaW0gbEN1cnJlbnRGb3VuZCAgIEFzIExvbmcKICAgIAogICAgQ29uc3QgbWF4Q29sc1RvRmluZCAgIEFzIExvbmcgPSAyCiAgICBDb25zdCBtYXhSb3dzVG9GaW5kICAgQXMgTG9uZyA9IDIKICAgIApPbiBFcnJvciBHb1RvIEdlbkVycgogICAgRm9yIEVhY2ggeFJvdyBJbiBUcmFkZVZhbHVlWG1sLnNlbGVjdE5vZGVzKCJWYWx1YXRpb25JbmZvUmVwb3J0L28vciIpCiAgICAgICAgbEN1cnJlbnRGb3VuZCA9IDAKICAgICAgICAnR2V0IHZhbHVhdGlvbiBjY3kKICAgICAgICBJZiB4Um93LmNoaWxkTm9kZXMoMCkuVGV4dCA9IENvbmZpZy5UdlJvd1RyYWRlVmFsdWVrZXkgVGhlbiBWYWx1YXRpb25DY3kgPSB4Um93LmNoaWxkTm9kZXMoMikuVGV4dAogICAgICAgIAogICAgICAgICdHZXQgbWFpbiBtZWFzdXJlcwogICAgICAgIElmIE5vdCBiU3RhcnQgVGhlbgogICAgICAgICAgICBJZiB4Um93LmNoaWxkTm9kZXMoMCkuVGV4dCA9IENvbmZpZy5UdlN0YXJ0a2V5IFRoZW4KICAgICAgICAgICAgICAgIGJTdGFydCA9IFRydWUKICAgICAgICAgICAgICAgIEZvciBsQ29sID0gMCBUbyB4Um93LmNoaWxkTm9kZXMubGVuZ3RoIC0gMQogICAgICAgICAgICAgICAgICAgIFNlbGVjdCBDYXNlIHhSb3cuY2hpbGROb2RlcyhsQ29sKS5UZXh0CiAgICAgICAgICAgICAgICAgICAgICAgIENhc2UgQ29uZmlnLlR2Y29sQXR0YWNoa2V5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsQ29sQXR0RGV0YWNoID0gbENvbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbEN1cnJlbnRGb3VuZCA9IGxDdXJyZW50Rm91bmQgKyAxCiAgICAgICAgICAgICAgICAgICAgICAgIENhc2UgQ29uZmlnLlR2Y29sU2Vuc2l0aXZpdHlrZXkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxDb2xTZW5zaXRpdml0eSA9IGxDb2wKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxDdXJyZW50Rm91bmQgPSBsQ3VycmVudEZvdW5kICsgMQogICAgICAgICAgICAgICAgICAgIEVuZCBTZWxlY3QKICAgICAgICAgICAgICAgICAgICBJZiBsQ3VycmVudEZvdW5kID0gbWF4Q29sc1RvRmluZCBUaGVuCiAgICAgICAgICAgICAgICAgICAgICAgIEV4aXQgRm9yCiAgICAgICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgICAgICBOZXh0IGxDb2wKICAgICAgICAgICAgICAgIElmIGxDdXJyZW50Rm91bmQgPD4gbWF4Q29sc1RvRmluZCBUaGVuCiAgICAgICAgICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dXYXJuaW5nLCAiWE1MIGFwcGVhcnMgaW5jb21wbGV0ZSBmb3IgdGhpcyB0cmFkZSwgdW5hYmxlIHRvIGZpbmQgcmVxdWlyZWQgZGF0YS4gKEluaXRpYWwgVmFsdWUgaXMgMCkgIiBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAmICJBdHRhY2gvRGV0YWNoIENvbHVtbiA6ICIgJiBsQ29sQXR0RGV0YWNoICYgIi4gIFNlbnNpdGl2aXR5IENvbHVtbiA6ICIgJiBsQ29sU2Vuc2l0aXZpdHkKICAgICAgICAgICAgICAgICAgICBFeGl0IFN1YgogICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgIEVuZCBJZgogICAgICAgIEVsc2UKICAgICAgICAgICAgU2VsZWN0IENhc2UgeFJvdy5jaGlsZE5vZGVzKDApLlRleHQKICAgICAgICAgICAgICAgIENhc2UgQ29uZmlnLlR2Um93QXR0YWNoa2V5CiAgICAgICAgICAgICAgICAgICAgSWYgSXNOdW1lcmljKHhSb3cuY2hpbGROb2RlcyhsQ29sQXR0RGV0YWNoKS5UZXh0KSBUaGVuCiAgICAgICAgICAgICAgICAgICAgICAgIEF0dGFjaCA9IHhSb3cuY2hpbGROb2RlcyhsQ29sQXR0RGV0YWNoKS5UZXh0CiAgICAgICAgICAgICAgICAgICAgRWxzZQogICAgICAgICAgICAgICAgICAgICAgICBXcml0ZVRvTG9nIExvZ1R5cGVzLkxvZ1dhcm5pbmcsICJBdHRhY2ggdmFsdWUgaXMgbm9uIG51bWVyaWMgKCIgJiB4Um93LmNoaWxkTm9kZXMobENvbEF0dERldGFjaCkuVGV4dCAmICIpIgogICAgICAgICAgICAgICAgICAgICAgICBFeGl0IFN1YgogICAgICAgICAgICAgICAgICAgIEVuZCBJZgogICAgICAgICAgICAgICAgICAgIElmIElzTnVtZXJpYyh4Um93LmNoaWxkTm9kZXMobENvbFNlbnNpdGl2aXR5KS5UZXh0KSBUaGVuCiAgICAgICAgICAgICAgICAgICAgICAgIEF0dGFjaFNlbnNpdGl2aXR5ID0geFJvdy5jaGlsZE5vZGVzKGxDb2xTZW5zaXRpdml0eSkuVGV4dAogICAgICAgICAgICAgICAgICAgIEVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgT24gRXJyb3IgR29UbyAwCiAgICAgICAgICAgICAgICAgICAgICAgIFdyaXRlVG9Mb2cgTG9nVHlwZXMuTG9nV2FybmluZywgIkF0dGFjaFNlbnNpdGl2aXR5IHZhbHVlIGlzIG5vbiBudW1lcmljICgiICYgeFJvdy5jaGlsZE5vZGVzKGxDb2xTZW5zaXRpdml0eSkuVGV4dCAmICIpIgogICAgICAgICAgICAgICAgICAgICAgICBFeGl0IFN1YgogICAgICAgICAgICAgICAgICAgIEVuZCBJZgogICAgICAgICAgICAgICAgICAgIERldGFjaCA9IEF0dGFjaCArIGRXaWR0aAogICAgICAgICAgICAgICAgICAgIGxDdXJyZW50Rm91bmQgPSBsQ3VycmVudEZvdW5kICsgMQogICAgICAgICAgICAgICAgQ2FzZSBDb25maWcuVHZSb3dXaWR0aGtleQogICAgICAgICAgICAgICAgICAgIElmIElzTnVtZXJpYyh4Um93LmNoaWxkTm9kZXMobENvbEF0dERldGFjaCkuVGV4dCkgVGhlbgogICAgICAgICAgICAgICAgICAgICAgICBkV2lkdGggPSB4Um93LmNoaWxkTm9kZXMobENvbEF0dERldGFjaCkuVGV4dAogICAgICAgICAgICAgICAgICAgIEVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgT24gRXJyb3IgR29UbyAwCiAgICAgICAgICAgICAgICAgICAgICAgIFdyaXRlVG9Mb2cgTG9nVHlwZXMuTG9nV2FybmluZywgIldpZHRoIHZhbHVlIGlzIG5vbiBudW1lcmljICgiICYgeFJvdy5jaGlsZE5vZGVzKGxDb2xBdHREZXRhY2gpLlRleHQgJiAiKSIKICAgICAgICAgICAgICAgICAgICAgICAgRXhpdCBTdWIKICAgICAgICAgICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgICAgICAgICBJZiBJc051bWVyaWMoeFJvdy5jaGlsZE5vZGVzKGxDb2xTZW5zaXRpdml0eSkuVGV4dCkgVGhlbgogICAgICAgICAgICAgICAgICAgICAgICBEZXRhY2hTZW5zaXRpdml0eSA9IHhSb3cuY2hpbGROb2RlcyhsQ29sU2Vuc2l0aXZpdHkpLlRleHQKICAgICAgICAgICAgICAgICAgICBFbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIE9uIEVycm9yIEdvVG8gMAogICAgICAgICAgICAgICAgICAgICAgICBXcml0ZVRvTG9nIExvZ1R5cGVzLkxvZ1dhcm5pbmcsICJEZXRhY2hTZW5zaXRpdml0eSB2YWx1ZSBpcyBub24gbnVtZXJpYyAoIiAmIHhSb3cuY2hpbGROb2RlcyhsQ29sU2Vuc2l0aXZpdHkpLlRleHQgJiAiKSIKICAgICAgICAgICAgICAgICAgICAgICAgRXhpdCBTdWIKICAgICAgICAgICAgICAgICAgICBFbmQgSWYKICAgICAgICAgICAgICAgICAgICBEZXRhY2ggPSBBdHRhY2ggKyBkV2lkdGgKICAgICAgICAgICAgICAgICAgICBsQ3VycmVudEZvdW5kID0gbEN1cnJlbnRGb3VuZCArIDEKICAgICAgICAgICAgRW5kIFNlbGVjdAogICAgICAgICAgICBJZiBsQ3VycmVudEZvdW5kID0gbWF4Um93c1RvRmluZCBUaGVuIEV4aXQgRm9yCiAgICAgICAgRW5kIElmCiAgICBOZXh0IHhSb3cKICAgIAogICAgJ0lmIGl0IHdhc24ndCBmb3VuZCwgcmV0dXJuIGZhbHNlCiAgICBpc1ZhbGlkQ2FPdXRwdXQgPSBiU3RhcnQKT24gRXJyb3IgR29UbyAwCiAgICBFeGl0IFN1YgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5HZXRUcmFkZVZhbHVlRGF0YSIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgMApFbmQgU3ViCgpQcml2YXRlIEZ1bmN0aW9uIEdldFNrZXdncmlkUm9vdFBhdGgoQnlWYWwgUXVvdGVEYXRlIEFzIERhdGUgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJ5VmFsIENhbGlicmF0aW9uTmFtZSBBcyBTdHJpbmcpCiAgICBEaW0gbFNoaWZ0ICBBcyBMb25nCiAgICBEaW0gc1BhdGggICBBcyBTdHJpbmcKICAgIERpbSBvRnNvICAgIEFzIEZpbGVTeXN0ZW1PYmplY3QKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgIElmIGRjR3JpZFBhdGhzIElzIE5vdGhpbmcgVGhlbgogICAgICAgIFNldCBkY0dyaWRQYXRocyA9IE5ldyBEaWN0aW9uYXJ5CiAgICBFbmQgSWYKICAgIAogICAgJ3N1cHJlc3MgdGhlIGVycm9yIHRoYXQgbWF5IGJlIHJldHVybmVkIGJlY2F1c2UgZm9sZGVyIGRvZXNuJ3QgZXhpc3QKICAgIElmIE5vdCBkY0dyaWRQYXRocy5FeGlzdHMoUXVvdGVEYXRlICYgIn4iICYgQ2FsaWJyYXRpb25OYW1lKSBUaGVuCk9uIEVycm9yIFJlc3VtZSBOZXh0CiAgICAgICAgc1BhdGggPSBtb2RTY2VuYXJpby5Db25maWcuUGF0aCgic2tld19ncmlkcyIsIFF1b3RlRGF0ZSkKICAgICAgICBTZXQgb0ZzbyA9IE5ldyBGaWxlU3lzdGVtT2JqZWN0CiAgICAgICAgCiAgICAgICAgSWYgc1BhdGggPSAiIiBPciBOb3Qgb0Zzby5GaWxlRXhpc3RzKG9Gc28uQnVpbGRQYXRoKHNQYXRoLCBDYWxpYnJhdGlvbk5hbWUgJiAiLnR4dCIpKSBUaGVuCiAgICAgICAgICAgIElmIHNQYXRoIDw+ICIiIFRoZW4KICAgICAgICAgICAgICAgIFdyaXRlVG9Mb2cgTG9nVHlwZXMuTG9nV2FybmluZywgIkFyY2hpdmUgZm9sZGVyIGV4aXN0cyBmb3IgIiBfCiAgICAgICAgICAgICAgICAgICAgICAgICYgRm9ybWF0KFF1b3RlRGF0ZSwgImRkLW1tbS15eSIpICYgIiwgYnV0IG5vIHNrZXcgZ3JpZHMgZm9yICIgJiBDYWxpYnJhdGlvbk5hbWUgJiAiIG9uIHBhdGggOiAiICYgb0Zzby5CdWlsZFBhdGgoc1BhdGgsIENhbGlicmF0aW9uTmFtZSAmICIudHh0IikKICAgICAgICAgICAgRW5kIElmCiAgICAKICAgICAgICAgICAgRm9yIGxTaGlmdCA9IDEgVG8gQ29uZmlnLk1heFNrZXdTaGlmdAogICAgICAgICAgICAgICAgc1BhdGggPSBtb2RTY2VuYXJpby5Db25maWcuUGF0aCgic2tld19ncmlkcyIsIFF1b3RlRGF0ZSAtIGxTaGlmdCkKICAgICAgICAgICAgICAgIElmIEVyci5OdW1iZXIgPD4gMCBUaGVuCiAgICAgICAgICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dXYXJuaW5nLCBFcnIuRGVzY3JpcHRpb24KICAgICAgICAgICAgICAgIEVsc2VJZiBOb3Qgb0Zzby5GaWxlRXhpc3RzKG9Gc28uQnVpbGRQYXRoKHNQYXRoLCBDYWxpYnJhdGlvbk5hbWUgJiAiLnR4dCIpKSBUaGVuCiAgICAgICAgICAgICAgICAgICAgV3JpdGVUb0xvZyBMb2dUeXBlcy5Mb2dXYXJuaW5nLCAiQXJjaGl2ZSBmb2xkZXIgZXhpc3RzIGZvciAiIF8KICAgICAgICAgICAgICAgICAgICAgICAgJiBGb3JtYXQoUXVvdGVEYXRlIC0gbFNoaWZ0LCAiZGQtbW1tLXl5IikgJiAiLCBidXQgbm8gc2tldyBncmlkcyBmb3IgIiAmIENhbGlicmF0aW9uTmFtZSAmICIgb24gcGF0aCA6ICIgJiBvRnNvLkJ1aWxkUGF0aChzUGF0aCwgQ2FsaWJyYXRpb25OYW1lICYgIi50eHQiKQogICAgICAgICAgICAgICAgICAgIHNQYXRoID0gIiIKICAgICAgICAgICAgICAgIEVsc2UKICAgICAgICAgICAgICAgICAgICBFeGl0IEZvcgogICAgICAgICAgICAgICAgRW5kIElmCiAgICAgICAgICAgIE5leHQgbFNoaWZ0CiAgICAgICAgRW5kIElmCiAgICAgICAgCk9uIEVycm9yIEdvVG8gR2VuRXJyCiAgICAgICAgICAgIAogICAgICAgIElmIHNQYXRoID0gIiIgVGhlbgogICAgICAgICAgICBPbiBFcnJvciBHb1RvIDAKICAgICAgICAgICAgbW9kU2NlbmFyaW8uQXBwRXJyb3JzLlJhaXNlIHRoaXNPYmplY3ROYW1lICYgIi4uR2V0U2tld2dyaWRSb290UGF0aCIgXwogICAgICAgICAgICAgICAgICAgICwgIlRoZXJlIGFyZSBubyBhcmNoaXZlZCBza2V3Z3JpZHMgaW4gZGF0ZSByYW5nZSBzdGFydCgiICYgUXVvdGVEYXRlICYgXwogICAgICAgICAgICAgICAgICAgICIpIGVuZCgiICYgUXVvdGVEYXRlIC0gQ29uZmlnLk1heFNrZXdTaGlmdCAmICIpIgogICAgICAgIEVsc2UKICAgICAgICAgICAgZGNHcmlkUGF0aHMuQWRkIFF1b3RlRGF0ZSAmICJ+IiAmIENhbGlicmF0aW9uTmFtZSwgc1BhdGgKICAgICAgICBFbmQgSWYKICAgIEVuZCBJZgogICAgICAgIAogICAgR2V0U2tld2dyaWRSb290UGF0aCA9IGRjR3JpZFBhdGhzLkl0ZW0oUXVvdGVEYXRlICYgIn4iICYgQ2FsaWJyYXRpb25OYW1lKQpPbiBFcnJvciBHb1RvIDAKICAgIEV4aXQgRnVuY3Rpb24KR2VuRXJyOgogICAgbW9kU2NlbmFyaW8uQXBwRXJyb3JzLlJhaXNlIHRoaXNPYmplY3ROYW1lICYgIi4uR2V0U2tld2dyaWRSb290UGF0aCIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgMApFbmQgRnVuY3Rpb24KCgpQcml2YXRlIEZ1bmN0aW9uIEJ1aWxkU2tld0dyaWRQYXRoKEJ5VmFsIFNrZXdHcmlkUm9vdCBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJ5VmFsIFNrZXdHcmlkUGF0dGVybiBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJ5VmFsIFBvcnRmb2xpbyBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJ5VmFsIFRlbm9yIEFzIFN0cmluZyBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgQnlWYWwgQ2FsaWJyYXRpb24gQXMgU3RyaW5nIF8KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBCeVZhbCBUcmFuY2hTdGFydCBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIE9wdGlvbmFsIEJ5VmFsIFRyYW5jaEVuZCBBcyBTdHJpbmcpIEFzIFN0cmluZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgIFNrZXdHcmlkUGF0dGVybiA9IFJlcGxhY2UoU2tld0dyaWRQYXR0ZXJuLCAiI1BvcnRmb2xpbyMiLCBQb3J0Zm9saW8pCiAgICBTa2V3R3JpZFBhdHRlcm4gPSBSZXBsYWNlKFNrZXdHcmlkUGF0dGVybiwgIiNUZW5vciMiLCBUZW5vcikKICAgIFNrZXdHcmlkUGF0dGVybiA9IFJlcGxhY2UoU2tld0dyaWRQYXR0ZXJuLCAiI0NhbGlicmF0aW9uIyIsIENhbGlicmF0aW9uKQogICAgU2tld0dyaWRQYXR0ZXJuID0gUmVwbGFjZShTa2V3R3JpZFBhdHRlcm4sICIjVHJhbmNoU3RhcnQjIiwgVHJhbmNoU3RhcnQpCiAgICBTa2V3R3JpZFBhdHRlcm4gPSBSZXBsYWNlKFNrZXdHcmlkUGF0dGVybiwgIiNUcmFuY2hFbmQjIiwgVHJhbmNoRW5kKQogICAgQnVpbGRTa2V3R3JpZFBhdGggPSBTa2V3R3JpZFJvb3QgJiAiXCIgJiBTa2V3R3JpZFBhdHRlcm4gJiAiLnR4dCIKICAgICAgICAgICAgICAgICAgICAgICAgCk9uIEVycm9yIEdvVG8gMAogICAgRXhpdCBGdW5jdGlvbgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5CdWlsZFNrZXdHcmlkUGF0aCIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgTmV4dApFbmQgRnVuY3Rpb24KJwonCidQcml2YXRlIEZ1bmN0aW9uIEdldEluZGV4Rm9yUmVnaW9uKEJ5VmFsIFJlZ2lvbiBBcyBTdHJpbmcpIEFzIFN0cmluZwonT24gRXJyb3IgR29UbyBHZW5FcnIKJyAgICBTZWxlY3QgQ2FzZSBSZWdpb24KJyAgICAgICAgQ2FzZSAiVVNEIgonICAgICAgICAgICAgR2V0SW5kZXhGb3JSZWdpb24gPSAiQ0RYIgonICAgICAgICBDYXNlICJFVVIiCicgICAgICAgICAgICBHZXRJbmRleEZvclJlZ2lvbiA9ICJpVHJheHgiCicgICAgICAgIENhc2UgRWxzZQonICAgICAgICAgICAgbW9kU2NlbmFyaW8uQXBwRXJyb3JzLlJhaXNlIHRoaXNPYmplY3ROYW1lICYgIi4uR2V0SW5kZXhGb3JSZWdpb24iIF8KJyAgICAgICAgICAgICAgICAsICJSZWdpb24gOiAiICYgUmVnaW9uICYgIiwgZG9lcyBub3QgaGF2ZSBhbiBJbmRleCB3aXRoaW4gdGhlIGNvbmZpZy4iCicgICAgRW5kIFNlbGVjdAonT24gRXJyb3IgR29UbyAwCicgICAgRXhpdCBGdW5jdGlvbgonR2VuRXJyOgonICAgIG1vZFNjZW5hcmlvLkFwcEVycm9ycy5SYWlzZSB0aGlzT2JqZWN0TmFtZSAmICIuLkdldEluZGV4Rm9yUmVnaW9uIiBfCicgICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCicgICAgUmVzdW1lIE5leHQKJ0VuZCBGdW5jdGlvbgoKClByaXZhdGUgRnVuY3Rpb24gQ29ycmVsYXRpb25EZWx0YUludGVycEZyb21Ta2V3VGFibGUoZEF0dGFjaG1lbnQsIG1hdHVyaXR5LCB2U2tld1RhYmxlLCBUZW5vcnNEYXRlcykKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgICcgZmluZCB0aGUgcGFyYW1ldGVyIGNlbGxzIGluIHRoZSB0YWJsZQogICAgRGltIG5yb3csIGksIGssIE51bVBhZ2VzLCBuUm93c1BlclBhZ2UsIG9mZnNldAogICAgRGltIGlTaCBBcyBJbnRlZ2VyCiAgICBEaW0gaURhdGUgICBBcyBJbnRlZ2VyCiAgICBEaW0gZE1hdCAgICBBcyBEYXRlCiAgICBEaW0gc01hdCAgICBBcyBTdHJpbmcKICAgIERpbSBuMSwgbjIKICAgIERpbSBiSXNSZXF1aXJlZCBBcyBCb29sZWFuCiAgICBEaW0gaUFjdHVhbCAgICAgQXMgSW50ZWdlcgogICAgCiAgICBucm93ID0gVUJvdW5kKHZTa2V3VGFibGUpCiAgICBGb3IgaSA9IDIgVG8gbnJvdwogICAgICAgIElmIE5vdCBJc051bWVyaWModlNrZXdUYWJsZShpLCAxKSkgVGhlbgogICAgICAgICAgICBuUm93c1BlclBhZ2UgPSBpIC0gMQogICAgICAgICAgICBFeGl0IEZvcgogICAgICAgIEVuZCBJZgogICAgTmV4dCBpCiAgICBJZiBuUm93c1BlclBhZ2UgPSAwIFRoZW4gblJvd3NQZXJQYWdlID0gbnJvdwogICAgTnVtUGFnZXMgPSBucm93IC8gblJvd3NQZXJQYWdlCiAgICAKICAgIFJlRGltIHNrZXdQYWdlc1BhcmFtcygxIFRvIDEpCiAgICBSZURpbSB0cmFuY2hlQm91bmRzKDEgVG8gblJvd3NQZXJQYWdlIC0gMiwgMSBUbyAxKQogICAgUmVEaW0gc2tld1ZhbHVlcygxIFRvIG5Sb3dzUGVyUGFnZSAtIDIsIDEgVG8gMSkKICAgIAogICAgRm9yIGsgPSAxIFRvIE51bVBhZ2VzCiAgICAgICAgb2Zmc2V0ID0gKGsgLSAxKSAqIG5Sb3dzUGVyUGFnZQogICAgICAgICdHZXQgdGhlIG1hdHVyaXR5IGRhdGUgZnJvbSB0ZWggc2tldyBncmlkCiAgICAgICAgbjEgPSBJblN0cih2U2tld1RhYmxlKG9mZnNldCArIDEsIDEpLCAiTUFUPSIpCiAgICAgICAgbjIgPSBJblN0cihuMSwgdlNrZXdUYWJsZShvZmZzZXQgKyAxLCAxKSwgIjoiKQogICAgICAgIHNNYXQgPSBNaWQodlNrZXdUYWJsZShvZmZzZXQgKyAxLCAxKSwgbjEgKyA0LCBuMiAtIG4xIC0gNCkKICAgICAgICAnV29yayBvdXQgaWYgdGhpcyB0ZW5vciBpcyByZXF1aXJlZAogICAgICAgIGJJc1JlcXVpcmVkID0gRmFsc2UKICAgICAgICBGb3IgaSA9IExCb3VuZChUZW5vcnNEYXRlcykgVG8gVUJvdW5kKFRlbm9yc0RhdGVzKQogICAgICAgICAgICBJZiBUZW5vcnNEYXRlcyhpKSA9IHNNYXQgVGhlbgogICAgICAgICAgICAgICAgYklzUmVxdWlyZWQgPSBUcnVlCiAgICAgICAgICAgICAgICBFeGl0IEZvcgogICAgICAgICAgICAnRWxzZQogICAgICAgICAgICAgICAgJ1N0b3AKICAgICAgICAgICAgRW5kIElmCiAgICAgICAgTmV4dCBpCiAgICAgICAgJ0lmIGl0IGlzLCBwcmVwYXJlIGZvciBwYXNzaW5nCiAgICAgICAgSWYgYklzUmVxdWlyZWQgVGhlbgogICAgICAgICAgICBpQWN0dWFsID0gaUFjdHVhbCArIDEKICAgICAgICAgICAgUmVEaW0gUHJlc2VydmUgc2tld1BhZ2VzUGFyYW1zKDEgVG8gaUFjdHVhbCkKICAgICAgICAgICAgUmVEaW0gUHJlc2VydmUgdHJhbmNoZUJvdW5kcygxIFRvIG5Sb3dzUGVyUGFnZSAtIDIsIDEgVG8gaUFjdHVhbCkKICAgICAgICAgICAgUmVEaW0gUHJlc2VydmUgc2tld1ZhbHVlcygxIFRvIG5Sb3dzUGVyUGFnZSAtIDIsIDEgVG8gaUFjdHVhbCkKICAgICAgICAgICAgc2tld1BhZ2VzUGFyYW1zKGlBY3R1YWwpID0gdlNrZXdUYWJsZShvZmZzZXQgKyAxLCAxKQogICAgICAgICAgICBGb3IgaSA9IDEgVG8gblJvd3NQZXJQYWdlIC0gMgogICAgICAgICAgICAgICAgdHJhbmNoZUJvdW5kcyhpLCBpQWN0dWFsKSA9IHZTa2V3VGFibGUob2Zmc2V0ICsgMiArIGksIDEpCiAgICAgICAgICAgICAgICBza2V3VmFsdWVzKGksIGlBY3R1YWwpID0gdlNrZXdUYWJsZShvZmZzZXQgKyAxICsgaSwgMikKICAgICAgICAgICAgTmV4dCBpCiAgICAgICAgRW5kIElmCiAgICBOZXh0IGsKICAgIENvcnJlbGF0aW9uRGVsdGFJbnRlcnBGcm9tU2tld1RhYmxlID0gQ29ycmVsYXRpb25EZWx0YUludGVycChkQXR0YWNobWVudCwgbWF0dXJpdHksIHNrZXdQYWdlc1BhcmFtcywgVHJhbnNwb3NlQXJyYXkodHJhbmNoZUJvdW5kcyksIFRyYW5zcG9zZUFycmF5KHNrZXdWYWx1ZXMpKQpPbiBFcnJvciBHb1RvIDAKICAgIEV4aXQgRnVuY3Rpb24KR2VuRXJyOgogICAgbW9kU2NlbmFyaW8uQXBwRXJyb3JzLlJhaXNlIHRoaXNPYmplY3ROYW1lICYgIi4uQ29ycmVsYXRpb25EZWx0YUludGVycEZyb21Ta2V3VGFibGUiIF8KICAgICAgICAgICAgICAgICwgRXJyLlNvdXJjZSAmICI6IiAmIEVyci5EZXNjcmlwdGlvbgogICAgUmVzdW1lIDAKRW5kIEZ1bmN0aW9uCgoKJyBnaXZlbiBhIGRldGFjaG1lbnQgYW5kIGEgbWF0dXJpdHkKJyBhbmQgZm9yIGVhY2ggc2tldyBwYWdlOgonICBwYXJhbWV0ZXJzKGNlbGwoMSwxKSkKJyAgdGhlIHNrZXcgYm91bmRhcmllcyhjZWxsKDIsMSkuLihuLDEpKQonICB0aGUgc2tldyB2YWx1ZXMgICAgKGNlbGwoMiwyKS4uKG4sMikpCicgdGhpcyB3aWxsIHJldHVybiB0aGUgZGludGVycG9sYXRlZCBza2V3IHZhbHVlCicgKGxpbmVhciBpbiBtYXR1cml0eS4gQ3ViaWMgc3BsaW5lIG5hdHVyYWwgYmMncyBpbiBhdHRhY2htZW50ClByaXZhdGUgRnVuY3Rpb24gQ29ycmVsYXRpb25EZWx0YUludGVycChkQXR0YWNobWVudCwgbWF0dXJpdHksIHNrZXdQYWdlUGFybXMsIHRyYW5jaGVCb3VuZHMsIHNrZXdWYWx1ZXMpCiAgICAnIHN0YWdlIDEgLSBleHRyYWN0IGZyb20gc2tld1BhZ2VQYXJtcyB0aGUgbWF0dXJpdHkgZGF0ZXMKICAgICcgaXMgZm91bmQgYmV0d2VlbiAiTUFUPSIgYW5kICI6IgogICAgRGltIG4gJyBubyBvZnBhZ2VzCiAgICBEaW0gaSwgbjEsIG4yLCBzRGF0CiAgICAKT24gRXJyb3IgR29UbyBHZW5FcnIKICAgIG4gPSBVQm91bmQoc2tld1BhZ2VQYXJtcykgLSBMQm91bmQoc2tld1BhZ2VQYXJtcykgKyAxCiAgICBSZURpbSBwYWdlSW5kaWNlcygxIFRvIG4pIEFzIExvbmcKICAgIFJlRGltIHBhZ2VEYXRlcygxIFRvIG4pIEFzIExvbmcKICAgIEZvciBpID0gMSBUbyBuCiAgICAgICAgbjEgPSBJblN0cihza2V3UGFnZVBhcm1zKGkpLCAiTUFUPSIpCiAgICAgICAgSWYgbjEgPD0gMCBUaGVuCiAgICAgICAgICAgIENvcnJlbGF0aW9uRGVsdGFJbnRlcnAgPSAiQ2Fubm90IGZpbmQgZGF0ZSBpbiAiICsgc2tld1BhZ2VQYXJtcyhpKQogICAgICAgICAgICBFeGl0IEZ1bmN0aW9uCiAgICAgICAgRW5kIElmCiAgICAgICAgbjIgPSBJblN0cihuMSwgc2tld1BhZ2VQYXJtcyhpKSwgIjoiKQogICAgICAgIHNEYXQgPSBNaWQoc2tld1BhZ2VQYXJtcyhpKSwgbjEgKyA0LCBuMiAtIG4xIC0gNCkKICAgICAgICBwYWdlSW5kaWNlcyhpKSA9IGkKICAgICAgICBzRGF0ID0gTGVmdChzRGF0LCAyKSArICItIiArIE1pZChzRGF0LCAzLCAzKSArICItIiArIFJpZ2h0KHNEYXQsIExlbihzRGF0KSAtIDUpCiAgICAgICAgcGFnZURhdGVzKGkpID0gQ0RhdGUoc0RhdCkKICAgIE5leHQgaQogICAgCiAgICAnIGZpbmQgb3VyIGRhdGUgaW4gdGhpcyByYW5nZQogICAgJyBvcmdhbmlzZSBpbnRlcnBvbGF0aW9uCiAgICBEaW0gZ0RhdGUsIGlEYXRlLCBmRGF0ZSwgbnMKICAgIAogICAgZ0RhdGUgPSBTaW1wbGVJbnRlcnAobWF0dXJpdHksIHBhZ2VEYXRlcywgcGFnZUluZGljZXMpCiAgICBJZiBnRGF0ZSA8IDEgVGhlbiBnRGF0ZSA9IDEKICAgIElmIGdEYXRlID4gbiBUaGVuIGdEYXRlID0gbgogICAgCiAgICBpRGF0ZSA9IEludChnRGF0ZSkKICAgIGZEYXRlID0gZ0RhdGUgLSBpRGF0ZQogICAgCiAgICAnIGJ1aWxkIGludGVycG9sYXRlZCBza2V3IGN1cnZlCiAgICBucyA9IFVCb3VuZCh0cmFuY2hlQm91bmRzLCAyKQogICAgUmVEaW0gVHJhbmNoZUJvdW5kc0xlc3NaZXJvKDEgVG8gbnMpCiAgICBSZURpbSBJbnRlcnBvbGF0ZWRTa2V3cygxIFRvIG5zKQogICAgRm9yIGkgPSAxIFRvIG5zCiAgICAgICAgVHJhbmNoZUJvdW5kc0xlc3NaZXJvKGkpID0gdHJhbmNoZUJvdW5kcygxLCBpKQogICAgICAgIElmIGZEYXRlID0gMCBUaGVuCiAgICAgICAgICAgIEludGVycG9sYXRlZFNrZXdzKGkpID0gc2tld1ZhbHVlcyhpRGF0ZSwgaSkKICAgICAgICBFbHNlCiAgICAgICAgICAgIEludGVycG9sYXRlZFNrZXdzKGkpID0gKDEgLSBmRGF0ZSkgKiBza2V3VmFsdWVzKGlEYXRlLCBpKSArIGZEYXRlICogc2tld1ZhbHVlcyhpRGF0ZSArIDEsIGkpCiAgICAgICAgRW5kIElmCiAgICBOZXh0IGkKICAgIENvcnJlbGF0aW9uRGVsdGFJbnRlcnAgPSBTcGxpbmVNZShkQXR0YWNobWVudCwgVHJhbmNoZUJvdW5kc0xlc3NaZXJvLCBJbnRlcnBvbGF0ZWRTa2V3cykKT24gRXJyb3IgR29UbyAwCiAgICBFeGl0IEZ1bmN0aW9uCkdlbkVycjoKICAgIG1vZFNjZW5hcmlvLkFwcEVycm9ycy5SYWlzZSB0aGlzT2JqZWN0TmFtZSAmICIuLkNvcnJlbGF0aW9uRGVsdGFJbnRlcnAiIF8KICAgICAgICAgICAgICAgICwgRXJyLlNvdXJjZSAmICI6IiAmIEVyci5EZXNjcmlwdGlvbgogICAgUmVzdW1lIE5leHQKRW5kIEZ1bmN0aW9uCgpQdWJsaWMgRnVuY3Rpb24gR2V0SW5kZXhNYXR1cml0eURhdGVGb3JSb2xsRGF0ZShCeVZhbCBUZW5vciBBcyBTdHJpbmcgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgT3B0aW9uYWwgQnlWYWwgUXVvdGVEYXRlIEFzIERhdGUpIEFzIERhdGUKICAgIAogICAgRGltIGxZZWFyU2hpZnQgICAgICBBcyBMb25nCiAgICBEaW0gbE1hdHVyaXR5TW9udGggIEFzIExvbmcKICAgIAogICAgbE1hdHVyaXR5TW9udGggPSBNb250aChRdW90ZURhdGUpCiAgICAKICAgIFNlbGVjdCBDYXNlIFVDYXNlKFRlbm9yKQogICAgICAgIENhc2UgIjNZUiIsICIzWSIsICIwM1kiCiAgICAgICAgICAgIGxZZWFyU2hpZnQgPSAzCiAgICAgICAgQ2FzZSAiNVlSIiwgIjVZIiwgIjA1WSIKICAgICAgICAgICAgbFllYXJTaGlmdCA9IDUKICAgICAgICBDYXNlICI3WVIiLCAiN1kiLCAiMDdZIgogICAgICAgICAgICBsWWVhclNoaWZ0ID0gNwogICAgICAgIENhc2UgIjEwWVIiLCAiMTBZIgogICAgICAgICAgICBsWWVhclNoaWZ0ID0gMTAKICAgIEVuZCBTZWxlY3QKCiAgICBHZXRJbmRleE1hdHVyaXR5RGF0ZUZvclJvbGxEYXRlID0gRGF0ZVNlcmlhbChZZWFyKFF1b3RlRGF0ZSkgKyBsWWVhclNoaWZ0LCBsTWF0dXJpdHlNb250aCArIDMsIDIwKQoKRW5kIEZ1bmN0aW9uCgoKUHVibGljIEZ1bmN0aW9uIEdldEluZGV4TWF0dXJpdHlEYXRlKEJ5VmFsIFRlbm9yIEFzIFN0cmluZyBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBPcHRpb25hbCBCeVZhbCBRdW90ZURhdGUgQXMgRGF0ZSkgQXMgRGF0ZQpPbiBFcnJvciBHb1RvIEdlbkVycgogICAgRGltIGxNYXR1cml0eU1vbnRoICBBcyBMb25nCiAgICBEaW0gbFllYXJTaGlmdCAgICAgIEFzIExvbmcKICAgIERpbSBiSXNSb2xsTW9udGggICAgQXMgQm9vbGVhbgogICAgCiAgICBJZiBRdW90ZURhdGUgPSAwIFRoZW4gUXVvdGVEYXRlID0gRGF0ZQogICAgU2VsZWN0IENhc2UgTW9udGgoUXVvdGVEYXRlKQogICAgICAgIENhc2UgSXMgPiA4CiAgICAgICAgICAgIGxNYXR1cml0eU1vbnRoID0gMTIKICAgICAgICAgICAgSWYgTW9udGgoUXVvdGVEYXRlKSA9IDkgVGhlbiBiSXNSb2xsTW9udGggPSBUcnVlCiAgICAgICAgQ2FzZSBJcyA+IDIKICAgICAgICAgICAgbE1hdHVyaXR5TW9udGggPSA2CiAgICAgICAgICAgIElmIE1vbnRoKFF1b3RlRGF0ZSkgPSAzIFRoZW4gYklzUm9sbE1vbnRoID0gVHJ1ZQogICAgICAgIENhc2UgRWxzZQogICAgICAgICAgICBsTWF0dXJpdHlNb250aCA9IDAKICAgICAgICAgICAgSWYgTW9udGgoUXVvdGVEYXRlKSA9IDEyIFRoZW4gYklzUm9sbE1vbnRoID0gVHJ1ZQogICAgRW5kIFNlbGVjdAogICAgSWYgRGF5KFF1b3RlRGF0ZSkgPCAyMCBBbmQgYklzUm9sbE1vbnRoIFRoZW4KICAgICAgICBsTWF0dXJpdHlNb250aCA9IGxNYXR1cml0eU1vbnRoIC0gNgogICAgRW5kIElmCiAgICBTZWxlY3QgQ2FzZSBVQ2FzZShUZW5vcikKICAgICAgICBDYXNlICIzWVIiLCAiM1kiLCAiMDNZIgogICAgICAgICAgICBsWWVhclNoaWZ0ID0gMwogICAgICAgIENhc2UgIjVZUiIsICI1WSIsICIwNVkiCiAgICAgICAgICAgIGxZZWFyU2hpZnQgPSA1CiAgICAgICAgQ2FzZSAiN1lSIiwgIjdZIiwgIjA3WSIKICAgICAgICAgICAgbFllYXJTaGlmdCA9IDcKICAgICAgICBDYXNlICIxMFlSIiwgIjEwWSIKICAgICAgICAgICAgbFllYXJTaGlmdCA9IDEwCiAgICBFbmQgU2VsZWN0CiAgICBHZXRJbmRleE1hdHVyaXR5RGF0ZSA9IERhdGVTZXJpYWwoWWVhcihRdW90ZURhdGUpICsgbFllYXJTaGlmdCwgbE1hdHVyaXR5TW9udGgsIDIwKQogICAgSWYgR2V0SW5kZXhNYXR1cml0eURhdGUgPSAwIFRoZW4KICAgICAgICBTdG9wCiAgICBFbmQgSWYKICAgIEV4aXQgRnVuY3Rpb24KCkdlbkVycjoKICAgIG1vZFNjZW5hcmlvLkFwcEVycm9ycy5SYWlzZSB0aGlzT2JqZWN0TmFtZSAmICIuLkNkc01hdHVyaXR5RGF0ZSIgXwogICAgICAgICAgICAgICAgLCBFcnIuRGVzY3JpcHRpb24KICAgIFJlc3VtZSBOZXh0CkVuZCBGdW5jdGlvbgoKUHJpdmF0ZSBGdW5jdGlvbiBTcGxpbmVNZSh4LCBweCwgcHkpCk9uIEVycm9yIEdvVG8gR2VuRXJyCiAgICBEaW0gdnB4LCB2cHksIG4sIG5yCiAgICBJZiBUeXBlTmFtZShweCkgPSAiUmFuZ2UiIFRoZW4KICAgICAgICBuID0gcHguQ2VsbHMuQ291bnQKICAgICAgICBuciA9IHB4LlJvd3MuQ291bnQKICAgIEVsc2UKICAgICAgICBuID0gVUJvdW5kKHB4KQogICAgICAgIG5yID0gVUJvdW5kKHB4KQogICAgRW5kIElmCiAgICBJZiB4IDw9IHB4KDEpIFRoZW4KICAgICAgICBTcGxpbmVNZSA9IHB5KDEpCiAgICBFbHNlSWYgeCA+PSBweChuKSBUaGVuCiAgICAgICAgU3BsaW5lTWUgPSBweShuKQogICAgRWxzZQogICAgICAgIERpbSBkCiAgICAgICAgSWYgbnIgPiAxIFRoZW4KICAgICAgICAgICAgU3BsaW5lTWUgPSBTcGxpbmUocHgsIHB5LCBGYWxzZSwgMCwgRmFsc2UsIDAsIHgsIEZhbHNlKQogICAgICAgIEVuZCBJZgogICAgRW5kIElmCk9uIEVycm9yIEdvVG8gMAogICAgRXhpdCBGdW5jdGlvbgpHZW5FcnI6CiAgICBtb2RTY2VuYXJpby5BcHBFcnJvcnMuUmFpc2UgdGhpc09iamVjdE5hbWUgJiAiLi5TcGxpbmVNZSIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgTmV4dApFbmQgRnVuY3Rpb24KCgpQcml2YXRlIEZ1bmN0aW9uIFNpbXBsZUludGVycChCeVZhbCB4IEFzIERvdWJsZSBfCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJ5VmFsIHB4IEFzIFZhcmlhbnQgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBCeVZhbCBweSBBcyBWYXJpYW50KQogICAgRGltIGxDb3VudCAgQXMgTG9uZwpPbiBFcnJvciBHb1RvIEdlbkVycgogICAgSWYgeCA8PSBweCgxKSBUaGVuCiAgICAgICAgU2ltcGxlSW50ZXJwID0gcHkoMSkKICAgIEVsc2VJZiB4ID49IHB4KFVCb3VuZChweSkpIFRoZW4KICAgICAgICBTaW1wbGVJbnRlcnAgPSBweShVQm91bmQocHkpKQogICAgRWxzZQogICAgICAgIEZvciBsQ291bnQgPSBMQm91bmQocHgpIFRvIFVCb3VuZChweCkgLSAxCiAgICAgICAgICAgIElmIHggPj0gcHgobENvdW50KSBBbmQgeCA8PSBweChsQ291bnQgKyAxKSBUaGVuCiAgICAgICAgICAgICAgICBTaW1wbGVJbnRlcnAgPSAocHkobENvdW50ICsgMSkgLSBweShsQ291bnQpKSAvIChweChsQ291bnQgKyAxKSAtIHB4KGxDb3VudCkpICogKHggLSBweChsQ291bnQpKSArIHB5KGxDb3VudCkKICAgICAgICAgICAgICAgIEV4aXQgRm9yCiAgICAgICAgICAgIEVuZCBJZgogICAgICAgIE5leHQgbENvdW50CiAgICBFbmQgSWYKT24gRXJyb3IgR29UbyAwCiAgICBFeGl0IEZ1bmN0aW9uCkdlbkVycjoKICAgIG1vZFNjZW5hcmlvLkFwcEVycm9ycy5SYWlzZSB0aGlzT2JqZWN0TmFtZSAmICIuLlNpbXBsZUludGVycCIgXwogICAgICAgICAgICAgICAgLCBFcnIuU291cmNlICYgIjoiICYgRXJyLkRlc2NyaXB0aW9uCiAgICBSZXN1bWUgTmV4dApFbmQgRnVuY3Rpb24KCgpGdW5jdGlvbiBUcmFuc3Bvc2VBcnJheShCeVZhbCBNeUFycmF5IEFzIFZhcmlhbnQgXwogICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBPcHRpb25hbCBCeVZhbCBUcmFuc3Bvc2VGb3JFeGNlbCBBcyBCb29sZWFuKSBBcyBWYXJpYW50CiAgICBEaW0geCBBcyBMb25nLCBZIEFzIExvbmcKICAgIERpbSB2VGVtcCAgICAgICBBcyBWYXJpYW50CiAgICBEaW0geFNoaWZ0ICAgICAgQXMgSW50ZWdlcgogICAgRGltIHlTaGlmdCAgICAgIEFzIEludGVnZXIKICAgIAogICAgSWYgSXNFbXB0eShNeUFycmF5KSBUaGVuCiAgICAgICAgRXhpdCBGdW5jdGlvbgogICAgRW5kIElmCiAgICAKICAgIElmIFRyYW5zcG9zZUZvckV4Y2VsIFRoZW4KICAgICAgICB4U2hpZnQgPSAxIC0gTEJvdW5kKE15QXJyYXksIDIpCiAgICAgICAgeVNoaWZ0ID0gMSAtIExCb3VuZChNeUFycmF5KQogICAgRW5kIElmCiAgICAKT24gRXJyb3IgR29UbyBlcnJUcmFuc3Bvc2UKICAgIFJlRGltIHZUZW1wKExCb3VuZChNeUFycmF5LCAyKSArIHhTaGlmdCBUbyBVQm91bmQoTXlBcnJheSwgMikgKyB4U2hpZnQsIF8KICAgICAgICAgICAgICAgIExCb3VuZChNeUFycmF5KSArIHlTaGlmdCBUbyBVQm91bmQoTXlBcnJheSkgKyB5U2hpZnQpCiAgICBGb3IgWSA9IExCb3VuZChNeUFycmF5KSBUbyBVQm91bmQoTXlBcnJheSkKICAgICAgICBGb3IgeCA9IExCb3VuZChNeUFycmF5LCAyKSBUbyBVQm91bmQoTXlBcnJheSwgMikKICAgICAgICAgICAgdlRlbXAoeCArIHhTaGlmdCwgWSArIHlTaGlmdCkgPSBNeUFycmF5KFksIHgpCiAgICAgICAgTmV4dCB4CiAgICBOZXh0IFkKICAgIFRyYW5zcG9zZUFycmF5ID0gdlRlbXAKT24gRXJyb3IgR29UbyAwCiAgICBFeGl0IEZ1bmN0aW9uCmVyclRyYW5zcG9zZToKICAgIG1vZFNjZW5hcmlvLkFwcEVycm9ycy5SYWlzZSAibW9kVXRpbC4uVHJhbnNwb3NlQXJyYXkiLCBfCiAgICAgICAgICAgICAgICAiRXJyb3IgVHJhbnNwb3NpbmcgYXJyYXkuIiAmIHZiTGYsIF8KICAgICAgICAgICAgICAgIEVyci5Tb3VyY2UgJiAiOiIgJiBFcnIuRGVzY3JpcHRpb24KRW5kIEZ1bmN0aW9uCgoKCgonIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCicgICBQUk9QRVJUSUVTCicjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKUHVibGljIFByb3BlcnR5IEdldCBBcHBFcnJvcnMoKSBBcyBBcHBFcnJvcgogICAgSWYgb0FwcEVycm9yT2JqZWN0IElzIE5vdGhpbmcgVGhlbgogICAgICAgIFNldCBvQXBwRXJyb3JPYmplY3QgPSBOZXcgQXBwRXJyb3IKICAgIEVuZCBJZgogICAgU2V0IEFwcEVycm9ycyA9IG9BcHBFcnJvck9iamVjdApFbmQgUHJvcGVydHkKCgpQdWJsaWMgUHJvcGVydHkgR2V0IENvbmZpZygpIEFzIENvbmZpZwogICAgSWYgb0NvbmZpZyBJcyBOb3RoaW5nIFRoZW4KICAgICAgICBTZXQgb0NvbmZpZyA9IE5ldyBDb25maWcKICAgICAgICBJZiBDb21tYW5kTGluZVBhcmFtcy5Db25maWdGaWxlUGF0aCA9ICIiIFRoZW4KICAgICAgICAgICAgU2V0IG9Db25maWcuQ29uZmlnRmlsZSA9IHhtbExvYWQoQXBwLlBhdGgsICJhcHAueG1sIikKICAgICAgICBFbHNlCiAgICAgICAgICAgIERpbSBzUGF0aCBBcyBTdHJpbmcKICAgICAgICAgICAgc1BhdGggPSBDb21tYW5kTGluZVBhcmFtcy5Db25maWdGaWxlUGF0aAogICAgICAgICAgICBTZXQgb0NvbmZpZy5Db25maWdGaWxlID0geG1sTG9hZChGU08uR2V0UGFyZW50Rm9sZGVyTmFtZShzUGF0aCksIEZTTy5HZXRGaWxlTmFtZShzUGF0aCkpCiAgICAgICAgRW5kIElmCiAgICBFbmQgSWYKICAgIFNldCBDb25maWcgPSBvQ29uZmlnCkVuZCBQcm9wZXJ0eQpQdWJsaWMgUHJvcGVydHkgU2V0IENvbmZpZyhSSFMgQXMgQ29uZmlnKQogICAgU2V0IG9Db25maWcgPSBSSFMKRW5kIFByb3BlcnR5CgoKUHVibGljIFByb3BlcnR5IEdldCBGU08oKSBBcyBGaWxlU3lzdGVtT2JqZWN0CiAgICBJZiBvRnNvIElzIE5vdGhpbmcgVGhlbgogICAgICAgIFNldCBvRnNvID0gTmV3IEZpbGVTeXN0ZW1PYmplY3QKICAgIEVuZCBJZgogICAgU2V0IEZTTyA9IE5ldyBGaWxlU3lzdGVtT2JqZWN0CkVuZCBQcm9wZXJ0eQoKClN1YiB0ZXN0KCkKICAgIE1zZ0JveCBGeE9iamVjdC5GeFNwb3RSYXRlKCI4IGFwcmlsIDIwMDYiLCAiR0JQIiwgUmVnaW9uQ3V0c0ZYLkVNRUEpCkVuZCBTdWIKUHVibGljIFByb3BlcnR5IEdldCBGeE9iamVjdCgpIEFzIEZYCiAgICBJZiBvRlggSXMgTm90aGluZyBUaGVuIFNldCBvRlggPSBOZXcgRlgKICAgIFNldCBGeE9iamVjdCA9IG9GWApFbmQgUHJvcGVydHkKCgpQdWJsaWMgUHJvcGVydHkgR2V0IFJ1bkRhdGUoKSBBcyBEYXRlCiAgICBkUXVvdGVEYXRlID0gQ29tbWFuZExpbmVQYXJhbXMuUXVvdGVEYXRlCiAgICBJZiBkUXVvdGVEYXRlID0gMCBUaGVuCiAgICAgICAgZFF1b3RlRGF0ZSA9IEFkZFdlZWtEYXkoRGF0ZSwgLTEpCiAgICBFbmQgSWYKICAgIFJ1bkRhdGUgPSBkUXVvdGVEYXRlCkVuZCBQcm9wZXJ0eQoKClB1YmxpYyBQcm9wZXJ0eSBHZXQgQ29tbWFuZExpbmVQYXJhbXMoKSBBcyBDbWRMaW5lUGFyYW1zCiAgICAnR2V0IHRoZSBxdW90ZSBkYXRlIGlmIGl0cyBiZWVuIHBhc3QgaW4gY29tbWFuZCBsaW5lLCBlbHNlIGRlZmF1bHQgdG8gcHJldmlvdXMgYnVzaW5lc3MgZGF0ZQogICAgSWYgb0NtZExpbmUgSXMgTm90aGluZyBUaGVuIFNldCBvQ21kTGluZSA9IE5ldyBDbWRMaW5lUGFyYW1zCiAgICAKICAgIFNldCBDb21tYW5kTGluZVBhcmFtcyA9IG9DbWRMaW5lCkVuZCBQcm9wZXJ0eQo=
Visual Basic.Net Compiler version 0.0.0.5914 (Mono 2.4.2 - r) Copyright (C) 2004-2008 Rolf Bjarne Kvinge. All rights reserved. /home/VAGQb5/prog.vb (1,11) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (3,12) : Error VBNC30206: 'Option' must be followed by 'Compare', 'Explicit', or 'Strict'. Error recovery not implemented yet. /home/VAGQb5/prog.vb (5,16) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (6,24) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (7,12) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (8,13) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (9,24) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (10,16) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (11,17) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (12,19) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (13,20) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (70,14) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (71,14) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (72,14) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (81,11) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (82,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (83,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (84,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (85,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (86,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (87,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (89,3) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (91,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (93,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (95,8) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (97,11) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (100,23) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (101,18) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (104,18) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (105,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (106,19) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (107,26) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (108,23) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (109,19) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (110,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (111,22) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (112,19) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (113,23) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (115,21) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (118,16) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (119,16) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (120,22) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (121,25) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (122,17) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (124,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (125,9) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (127,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (129,3) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (130,9) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (131,7) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (133,15) : Error VBNC30203: Not valid as identifier. /home/VAGQb5/prog.vb (133,15) : Error VBNC30041: Too many errors. Exception of type 'vbnc.TooManyErrorsException' was thrown. at vbnc.Report.ShowMessage (Boolean SaveIt, vbnc.Message Message) [0x00080] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Report.vb:342 at vbnc.Report.ShowMessage (Messages Message, Span Location, System.String[] Parameters) [0x00000] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Report.vb:259 at vbnc.Report.ShowMessage (Messages Message, System.String[] Parameters) [0x00054] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Report.vb:269 at vbnc.Compiler.Compile () [0x005a3] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Compiler.vb:651 at vbnc.Compiler.Compile (System.String[] CommandLine) [0x00057] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Compiler.vb:279 at vbnc.Main.Main (System.String[] CmdArgs) [0x0000f] in /var/tmp/portage/dev-lang/mono-basic-2.4.2/work/mono-basic-2.4.2/vbnc/vbnc/source/General/Main.vb:55 Failed compilation took 00:00:00.5866750
-
result: Compilation error (maybe you wish to see an example for VB.NET)



