This is based on code and data in golf simulation.r and material in GHIN Cap org 2014 version 2021 update.xlsm The workbook has 2014 handicap data for about 40 HRYCC guys and some categories based on other research on MidAm results for 300 plus contestants. These results provide the ‘probabilities’ of scoring for the various handicap categories.

The first objective here is to show and document the calculations from ‘golf simution.r’

There are a few lints that are not explained but seem to be ‘scratch pad’ stuff as follows

Next there is code to build a scoring matrix relative to par and also for two different stableford scoring schemes. Changes have been made to the original to improve clarity

  toPar<-c(-3,-2,-1,0,1,2,3) #relative to par score
 
 
 scores<-c("dblEag","eagle","birdie","par","boggie","dbl","other")
 stableford<-c(5,4,3,2,1,0,0)
 mod_stableford<-c(12,6,4,2,1,0,0)
 pointMat<-data.frame(scores,toPar,stableford,mod_stableford)
 print(pointMat)

Next is par for the Golden Marsh Course in 2014. Looks like we didn’t get to RR par yet.

gmPar=c(4,5,4,3,4,4,4,3,5,4,3,4,5,3,5,4,4,4)
print(gmPar)
 [1] 4 5 4 3 4 4 4 3 5 4 3 4 5 3 5 4 4 4

Sunday April 4 Recalculated the odds of scoring in excel and have the following


par_and_under =c(0,0.0088,0.1901,0.6667,0.1345,0.0000,  0.0000)

plus1_5 = c(0,0.0036,   0.1047, 0.6368, 0.2251, 0.0249, 0.0050)

plus6_10 =c(0,0.0009,   0.0703, 0.5341, 0.3087, 0.0694, 0.0166)
plus11_15 = c(0,0.0000, 0.0385, 0.4203, 0.3880, 0.1192, 0.0341)

plus16_and_over = c(0,0.0000,   0.0299, 0.3226, 0.3889, 0.1774, 0.0812)
rev_Probs = data.frame (scores,par_and_under,plus1_5,plus6_10,plus11_15, plus16_and_over)
rev_Probs

Just to understand what sample does here is one with and without probability weights This shows the par_and_under golfer had 4 birds, 1 boggie and the rest pars with the weighting compared to the unweighted sample with an 1 double eagle,1 eagle, 4 birds,1 par, 3 boggies,5 doubles and 4 tripples

sample(toPar,size=18,prob=par_and_under,replace=TRUE)
 [1] -1 -1  0  0  0  0  0  1  0  0  0  0  0 -1  0  0 -1  0
sample(toPar,size=18,replace=TRUE)
 [1] -3 -1  1  0  2 -1 -1  3  1  3  2  3  3 -1 -2  1  2  2

Now going back we also created variables with par for River Ridge and Golden Marsh and a function to return the handicaps for each as follows

HRGMCap<-c( 7,11,3,15,1,13,9,17,5,4,18,14,12,16,2,8,10,6)
HRRRCap<-c(9,15,5,1,11,7,17,3,13,12,6,18,8,16,2,10,4,14)

#we can use an ifelse test to get the strokes by handicap
getStrokes<-function(HRcaps,IndCap){
  strokes<-    ifelse(HRcaps<=IndCap,-1,0)
}  

cap = getStrokes(HRGMCap,7)
print(cap)
 [1] -1  0 -1  0 -1  0  0  0 -1 -1  0  0  0  0 -1  0  0 -1

We can then get the scores on each hole add the par and the strokes if any and get the net scores.

Netscores=function(prob1,par,nbrballsCount,Course_Strokes){
   p1name <- deparse(substitute(prob1))
  
   v=rep(0,nbrballsCount)
    # cat ("Par    ", par, "\n")
   for (i in 1:nbrballsCount){

       res<-sample(toPar,size=18,prob=prob1,replace=TRUE) #rp is relative to par score
       gross = res + par
      
       # cat ("Gross  ", gross,"\n")
       # cat ("Stroke ", Course_Strokes, "\n")
       res<-res + par + Course_Strokes
       net = res
       # cat ("Net    ", res, "\n")
       # cat ("    ","\n")
       #print (paste((res),"Total=",sum(res)))
        #cat(res,"total=",sum(res),"\n")
    
      v[i]=sum(res)
    #   if (i==nbr){
    #       cat("Results for ",p1name, " with ", nbr, " Balls counting", "\n")
    #       cat("Net scores ", v, "\n")
    #       cat("Total ", sum(v),"\n")
    #       cat("Low ",min(v), "\n")
    #       cat("High ",max(v),"\n" )
    #       cat("Avg ", mean(v),"\n")
    #       cat("StdDev",sd(v),"\n")
    #       cat("                  ","\n")
    # 
    # 
    # 
    # }
   }
   return(v)
   }

Now run NetScores for the plus1_5 with a handicap of 3

t1 <- Netscores(plus1_5 ,gmPar,4,getStrokes(HRGMCap,3))
Par     4 5 4 3 4 4 4 3 5 4 3 4 5 3 5 4 4 4 
Gross   3 5 4 4 4 4 6 3 5 5 2 3 5 3 5 4 4 5 
Stroke  0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 
Net     3 5 3 4 3 4 6 3 5 5 2 3 5 3 4 4 4 5 
     
Gross   4 5 4 2 4 3 5 3 5 4 3 4 6 2 5 4 4 4 
Stroke  0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 
Net     4 5 3 2 3 3 5 3 5 4 3 4 6 2 4 4 4 4 
     
Gross   4 6 4 4 4 5 7 3 6 6 4 4 5 3 6 4 5 4 
Stroke  0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 
Net     4 6 3 4 3 5 7 3 6 6 4 4 5 3 5 4 5 4 
     
Gross   4 5 4 3 4 5 4 3 5 4 2 3 4 3 6 4 4 5 
Stroke  0 0 -1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 
Net     4 5 3 3 3 5 4 3 5 4 2 3 4 3 5 4 4 5 
     
t1
[1] 71 68 81 69

Now the higher cap players - use 13

t2 = Netscores(plus11_15 ,gmPar,4,getStrokes(HRGMCap,13))
Par     4 5 4 3 4 4 4 3 5 4 3 4 5 3 5 4 4 4 
Gross   5 5 5 5 5 6 4 4 5 4 4 5 5 3 6 4 4 4 
Stroke  -1 -1 -1 0 -1 -1 -1 0 -1 -1 0 0 -1 0 -1 -1 -1 -1 
Net     4 4 4 5 4 5 3 4 4 3 4 5 4 3 5 3 3 3 
     
Gross   5 6 4 4 4 4 5 5 8 4 3 5 6 3 6 4 5 4 
Stroke  -1 -1 -1 0 -1 -1 -1 0 -1 -1 0 0 -1 0 -1 -1 -1 -1 
Net     4 5 3 4 3 3 4 5 7 3 3 5 5 3 5 3 4 3 
     
Gross   5 5 4 4 6 4 4 4 6 4 6 4 7 3 6 6 5 5 
Stroke  -1 -1 -1 0 -1 -1 -1 0 -1 -1 0 0 -1 0 -1 -1 -1 -1 
Net     4 4 3 4 5 3 3 4 5 3 6 4 6 3 5 5 4 4 
     
Gross   4 6 5 4 6 5 6 3 5 5 4 4 6 4 6 4 4 6 
Stroke  -1 -1 -1 0 -1 -1 -1 0 -1 -1 0 0 -1 0 -1 -1 -1 -1 
Net     3 5 4 4 5 4 5 3 4 4 4 4 5 4 5 3 3 5 
     
t2
[1] 70 72 75 74

combined scoring function

do Netscores for two different handicap groups and track which team or group wins

track the number of wins and loses by team

come back and get birdies or better - gross and net

RunNetScores = function(plus1_5,plus11_15, par,cnt_Nbr_balls,nbrTrials,Team1Cap,Team2Cap){
   #prob1 and prob2 are values like plus11_15 or plus1_5
   #par is the var like gmPar
   #cnt_Nmb_balls - how many of the team of 4 will count - 
   #nbrTrails - how many matches are to be simulated eg 100, 20,000
   # 
   Team1name <- deparse(substitute(plus1_5))
   Team2name <- deparse(substitute(plus11_15))
     v=rep("NA",nbrTrials) # holder for results
     cntTeam1 = 0
     cntTeam2 = 0
     tied = 0
     for (i in 1:nbrTrials){
#       # use 4 as all balls count - change later if needed
       team1_Res = Netscores(plus1_5,par,cnt_Nbr_balls,getStrokes(HRGMCap,Team1Cap))
       team2_Res = Netscores(plus11_15,par,cnt_Nbr_balls,getStrokes(HRGMCap,Team2Cap))
          t1Sum = sum( team1_Res)
          t2Sum = sum(team2_Res )
          res =  t1Sum - t2Sum
          #cat (i ," Team Net Diff is ", res, "\n")
       if (res < 0 ){
       winner = paste (i," ",Team1name , t1Sum , " vs " , t2Sum , "\n")
       cntTeam1 = cntTeam1 + 1
       
       }

       if (res > 0 ){
          winner = paste (i," ",Team2name , t2Sum , " vs " , t1Sum , "\n")
          cntTeam2 = cntTeam2 + 1
         }
      if (res == 0 ){
          winner = paste (i," ","Tied " , t2Sum , " vs " , t1Sum , "\n")
          tied = tied +1
         }
         
     v[i]=winner     
    }
     cat ("Final Results for ",nbrTrials," trials with Low cap of : ",Team1Cap, "vs High Cap of " , Team2Cap, "\n")
      # cat(  v, "\n")
      cat (Team1name, " wins =", cntTeam1,"\n"  )
      cat (Team2name, " wins =", cntTeam2 ,"\n" )
      cat ("Ties = " ,tied ,"\n")
      
}   

Test the function

testRes = RunNetScores(plus1_5,plus11_15,par = gmPar,cnt_Nbr_balls = 4,nbrTrials = 1000,Team1Cap = 3,Team2Cap = 11)
Final Results for  1000  trials with Low cap of :  3 vs High Cap of  11 
plus1_5  wins = 721 
plus11_15  wins = 251 
Ties =  28 

Look at the combinations of the plus1_5 from 1 to 5 versus the plus11_15 from 11 to 14 (caps are maxed at 14)

lowcaps = c(1,2,3,4,5)
highcaps = c(11,12,13,14)
for (i in 1:length(lowcaps)){
   for (j in 1:length(highcaps)){
   #cat ("lowcaps =", lowcaps[i], " highcaps = ", highcaps[j],"\n" ) 
      
   RunNetScores(plus1_5,plus11_15,par = gmPar,cnt_Nbr_balls = 4,nbrTrials = 1000,Team1Cap = lowcaps[i],Team2Cap = highcaps[j])
     cat("  ","\n")
   }
}
Final Results for  1000  trials with Low cap of :  1 vs High Cap of  11 
plus1_5  wins = 322 
plus11_15  wins = 637 
Ties =  41 
   
Final Results for  1000  trials with Low cap of :  1 vs High Cap of  12 
plus1_5  wins = 204 
plus11_15  wins = 763 
Ties =  33 
   
Final Results for  1000  trials with Low cap of :  1 vs High Cap of  13 
plus1_5  wins = 105 
plus11_15  wins = 869 
Ties =  26 
   
Final Results for  1000  trials with Low cap of :  1 vs High Cap of  14 
plus1_5  wins = 41 
plus11_15  wins = 946 
Ties =  13 
   
Final Results for  1000  trials with Low cap of :  2 vs High Cap of  11 
plus1_5  wins = 502 
plus11_15  wins = 453 
Ties =  45 
   
Final Results for  1000  trials with Low cap of :  2 vs High Cap of  12 
plus1_5  wins = 370 
plus11_15  wins = 590 
Ties =  40 
   
Final Results for  1000  trials with Low cap of :  2 vs High Cap of  13 
plus1_5  wins = 198 
plus11_15  wins = 772 
Ties =  30 
   
Final Results for  1000  trials with Low cap of :  2 vs High Cap of  14 
plus1_5  wins = 119 
plus11_15  wins = 860 
Ties =  21 
   
Final Results for  1000  trials with Low cap of :  3 vs High Cap of  11 
plus1_5  wins = 680 
plus11_15  wins = 289 
Ties =  31 
   
Final Results for  1000  trials with Low cap of :  3 vs High Cap of  12 
plus1_5  wins = 551 
plus11_15  wins = 414 
Ties =  35 
   
Final Results for  1000  trials with Low cap of :  3 vs High Cap of  13 
plus1_5  wins = 339 
plus11_15  wins = 620 
Ties =  41 
   
Final Results for  1000  trials with Low cap of :  3 vs High Cap of  14 
plus1_5  wins = 205 
plus11_15  wins = 765 
Ties =  30 
   
Final Results for  1000  trials with Low cap of :  4 vs High Cap of  11 
plus1_5  wins = 805 
plus11_15  wins = 160 
Ties =  35 
   
Final Results for  1000  trials with Low cap of :  4 vs High Cap of  12 
plus1_5  wins = 670 
plus11_15  wins = 305 
Ties =  25 
   
Final Results for  1000  trials with Low cap of :  4 vs High Cap of  13 
plus1_5  wins = 513 
plus11_15  wins = 442 
Ties =  45 
   
Final Results for  1000  trials with Low cap of :  4 vs High Cap of  14 
plus1_5  wins = 343 
plus11_15  wins = 610 
Ties =  47 
   
Final Results for  1000  trials with Low cap of :  5 vs High Cap of  11 
plus1_5  wins = 889 
plus11_15  wins = 92 
Ties =  19 
   
Final Results for  1000  trials with Low cap of :  5 vs High Cap of  12 
plus1_5  wins = 818 
plus11_15  wins = 159 
Ties =  23 
   
Final Results for  1000  trials with Low cap of :  5 vs High Cap of  13 
plus1_5  wins = 663 
plus11_15  wins = 302 
Ties =  35 
   
Final Results for  1000  trials with Low cap of :  5 vs High Cap of  14 
plus1_5  wins = 541 
plus11_15  wins = 421 
Ties =  38 
   

Now look at the same Simultion as above but use 2 and 3 balls counted since the previous run counted all 4 balls MAY HAVE TO CHANGE THE LOGIC TO COUNT THE LOWEST 2 OR 3 BALLS PER HOLE

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIk5vdGVib29rIGV4cGxvcmluZyAyMDE0IGdvbGZzaW11bGF0aW9uICINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQpUaGlzIGlzIGJhc2VkIG9uIGNvZGUgYW5kIGRhdGEgaW4gZ29sZiBzaW11bGF0aW9uLnIgYW5kIG1hdGVyaWFsIGluIEdISU4gQ2FwIG9yZyAyMDE0IHZlcnNpb24gMjAyMSB1cGRhdGUueGxzbQ0KVGhlIHdvcmtib29rIGhhcyAyMDE0IGhhbmRpY2FwIGRhdGEgZm9yIGFib3V0IDQwIEhSWUNDIGd1eXMgYW5kIHNvbWUgY2F0ZWdvcmllcyBiYXNlZCBvbiBvdGhlciByZXNlYXJjaCANCm9uIE1pZEFtIHJlc3VsdHMgZm9yIDMwMCBwbHVzIGNvbnRlc3RhbnRzLiBUaGVzZSByZXN1bHRzIHByb3ZpZGUgdGhlICdwcm9iYWJpbGl0aWVzJyBvZiBzY29yaW5nIGZvciB0aGUNCnZhcmlvdXMgaGFuZGljYXAgY2F0ZWdvcmllcy4NCg0KVGhlIGZpcnN0IG9iamVjdGl2ZSBoZXJlIGlzIHRvIHNob3cgYW5kIGRvY3VtZW50IHRoZSBjYWxjdWxhdGlvbnMgZnJvbSAnZ29sZiBzaW11dGlvbi5yJyANCg0KVGhlcmUgYXJlIGEgZmV3IGxpbnRzIHRoYXQgYXJlIG5vdCBleHBsYWluZWQgYnV0IHNlZW0gdG8gYmUgJ3NjcmF0Y2ggcGFkJyBzdHVmZiBhcyBmb2xsb3dzDQoNCg0KDQoNCg0KTmV4dCB0aGVyZSBpcyBjb2RlIHRvIGJ1aWxkIGEgc2NvcmluZyBtYXRyaXggcmVsYXRpdmUgdG8gcGFyIGFuZCBhbHNvIGZvciB0d28gZGlmZmVyZW50IHN0YWJsZWZvcmQgc2NvcmluZyBzY2hlbWVzLiBDaGFuZ2VzIGhhdmUgYmVlbiBtYWRlIHRvIHRoZSBvcmlnaW5hbCB0byBpbXByb3ZlIGNsYXJpdHkNCmBgYHtyfQ0KICB0b1BhcjwtYygtMywtMiwtMSwwLDEsMiwzKSAjcmVsYXRpdmUgdG8gcGFyIHNjb3JlDQogDQogDQogc2NvcmVzPC1jKCJkYmxFYWciLCJlYWdsZSIsImJpcmRpZSIsInBhciIsImJvZ2dpZSIsImRibCIsIm90aGVyIikNCiBzdGFibGVmb3JkPC1jKDUsNCwzLDIsMSwwLDApDQogbW9kX3N0YWJsZWZvcmQ8LWMoMTIsNiw0LDIsMSwwLDApDQogcG9pbnRNYXQ8LWRhdGEuZnJhbWUoc2NvcmVzLHRvUGFyLHN0YWJsZWZvcmQsbW9kX3N0YWJsZWZvcmQpDQogcHJpbnQocG9pbnRNYXQpDQpgYGANCk5leHQgaXMgcGFyIGZvciB0aGUgR29sZGVuIE1hcnNoIENvdXJzZSBpbiAyMDE0LiBMb29rcyBsaWtlIHdlIGRpZG4ndCBnZXQgdG8gUlIgcGFyIHlldC4NCmBgYHtyfQ0KZ21QYXI9Yyg0LDUsNCwzLDQsNCw0LDMsNSw0LDMsNCw1LDMsNSw0LDQsNCkNCnByaW50KGdtUGFyKQ0KYGBgDQpTdW5kYXkgQXByaWwgNCANClJlY2FsY3VsYXRlZCB0aGUgb2RkcyBvZiBzY29yaW5nIGluIGV4Y2VsIGFuZCBoYXZlIHRoZSBmb2xsb3dpbmcgIA0KYGBge3J9DQoNCnBhcl9hbmRfdW5kZXIgPWMoMCwwLjAwODgsMC4xOTAxLDAuNjY2NywwLjEzNDUsMC4wMDAwLAkwLjAwMDApDQoNCnBsdXMxXzUgPSBjKDAsMC4wMDM2LAkwLjEwNDcsCTAuNjM2OCwJMC4yMjUxLAkwLjAyNDksCTAuMDA1MCkNCg0KcGx1czZfMTAgPWMoMCwwLjAwMDksCTAuMDcwMywJMC41MzQxLAkwLjMwODcsCTAuMDY5NCwJMC4wMTY2KQ0KcGx1czExXzE1ID0gYygwLDAuMDAwMCwJMC4wMzg1LAkwLjQyMDMsCTAuMzg4MCwJMC4xMTkyLAkwLjAzNDEpDQoNCnBsdXMxNl9hbmRfb3ZlciA9IGMoMCwwLjAwMDAsCTAuMDI5OSwJMC4zMjI2LAkwLjM4ODksCTAuMTc3NCwJMC4wODEyKQ0KcmV2X1Byb2JzID0gZGF0YS5mcmFtZSAoc2NvcmVzLHBhcl9hbmRfdW5kZXIscGx1czFfNSxwbHVzNl8xMCxwbHVzMTFfMTUsIHBsdXMxNl9hbmRfb3ZlcikNCnJldl9Qcm9icw0KYGBgDQoNCkp1c3QgdG8gdW5kZXJzdGFuZCB3aGF0IHNhbXBsZSBkb2VzIGhlcmUgaXMgb25lIHdpdGggYW5kIHdpdGhvdXQgcHJvYmFiaWxpdHkgd2VpZ2h0cw0KVGhpcyBzaG93cyB0aGUgcGFyX2FuZF91bmRlciBnb2xmZXIgaGFkIDQgYmlyZHMsIDEgYm9nZ2llIGFuZCB0aGUgcmVzdCBwYXJzIHdpdGgNCnRoZSB3ZWlnaHRpbmcgY29tcGFyZWQgdG8gdGhlIHVud2VpZ2h0ZWQgc2FtcGxlIHdpdGggYW4gMSBkb3VibGUgZWFnbGUsMSBlYWdsZSwgNCBiaXJkcywxIHBhciwgMyBib2dnaWVzLDUgZG91YmxlcyBhbmQgNCB0cmlwcGxlcw0KYGBge3J9DQpzYW1wbGUodG9QYXIsc2l6ZT0xOCxwcm9iPXBhcl9hbmRfdW5kZXIscmVwbGFjZT1UUlVFKQ0Kc2FtcGxlKHRvUGFyLHNpemU9MTgscmVwbGFjZT1UUlVFKQ0KDQoNCmBgYA0KDQpOb3cgZ29pbmcgYmFjayB3ZSBhbHNvIGNyZWF0ZWQgdmFyaWFibGVzIHdpdGggcGFyIGZvciBSaXZlciBSaWRnZSBhbmQgR29sZGVuIE1hcnNoDQphbmQgYSBmdW5jdGlvbiB0byByZXR1cm4gdGhlIGhhbmRpY2FwcyBmb3IgZWFjaCBhcyBmb2xsb3dzDQoNCmBgYHtyfQ0KSFJHTUNhcDwtYyggNywxMSwzLDE1LDEsMTMsOSwxNyw1LDQsMTgsMTQsMTIsMTYsMiw4LDEwLDYpDQpIUlJSQ2FwPC1jKDksMTUsNSwxLDExLDcsMTcsMywxMywxMiw2LDE4LDgsMTYsMiwxMCw0LDE0KQ0KDQojd2UgY2FuIHVzZSBhbiBpZmVsc2UgdGVzdCB0byBnZXQgdGhlIHN0cm9rZXMgYnkgaGFuZGljYXANCmdldFN0cm9rZXM8LWZ1bmN0aW9uKEhSY2FwcyxJbmRDYXApew0KICBzdHJva2VzPC0gICAgaWZlbHNlKEhSY2Fwczw9SW5kQ2FwLC0xLDApDQp9ICANCg0KY2FwID0gZ2V0U3Ryb2tlcyhIUkdNQ2FwLDcpDQpwcmludChjYXApDQpgYGANCldlIGNhbiB0aGVuIGdldCB0aGUgc2NvcmVzIG9uIGVhY2ggaG9sZSBhZGQgdGhlIHBhciBhbmQgdGhlIHN0cm9rZXMgaWYgYW55IGFuZCBnZXQgdGhlIA0KbmV0IHNjb3Jlcy4NCg0KYGBge3J9DQpOZXRzY29yZXM9ZnVuY3Rpb24ocHJvYjEscGFyLG5icmJhbGxzQ291bnQsQ291cnNlX1N0cm9rZXMpew0KICAgcDFuYW1lIDwtIGRlcGFyc2Uoc3Vic3RpdHV0ZShwcm9iMSkpDQogIA0KICAgdj1yZXAoMCxuYnJiYWxsc0NvdW50KQ0KICAgICMgY2F0ICgiUGFyICAgICIsIHBhciwgIlxuIikNCiAgIGZvciAoaSBpbiAxOm5icmJhbGxzQ291bnQpew0KDQogICAgICAgcmVzPC1zYW1wbGUodG9QYXIsc2l6ZT0xOCxwcm9iPXByb2IxLHJlcGxhY2U9VFJVRSkgI3JwIGlzIHJlbGF0aXZlIHRvIHBhciBzY29yZQ0KICAgICAgIGdyb3NzID0gcmVzICsgcGFyDQogICAgICANCiAgICAgICAjIGNhdCAoIkdyb3NzICAiLCBncm9zcywiXG4iKQ0KICAgICAgICMgY2F0ICgiU3Ryb2tlICIsIENvdXJzZV9TdHJva2VzLCAiXG4iKQ0KICAgICAgIHJlczwtcmVzICsgcGFyICsgQ291cnNlX1N0cm9rZXMNCiAgICAgICBuZXQgPSByZXMNCiAgICAgICAjIGNhdCAoIk5ldCAgICAiLCByZXMsICJcbiIpDQogICAgICAgIyBjYXQgKCIgICAgIiwiXG4iKQ0KICAgICAgICNwcmludCAocGFzdGUoKHJlcyksIlRvdGFsPSIsc3VtKHJlcykpKQ0KICAgICAgICAjY2F0KHJlcywidG90YWw9IixzdW0ocmVzKSwiXG4iKQ0KICAgIA0KICAgICAgdltpXT1zdW0ocmVzKQ0KICAgICMgICBpZiAoaT09bmJyKXsNCiAgICAjICAgICAgIGNhdCgiUmVzdWx0cyBmb3IgIixwMW5hbWUsICIgd2l0aCAiLCBuYnIsICIgQmFsbHMgY291bnRpbmciLCAiXG4iKQ0KICAgICMgICAgICAgY2F0KCJOZXQgc2NvcmVzICIsIHYsICJcbiIpDQogICAgIyAgICAgICBjYXQoIlRvdGFsICIsIHN1bSh2KSwiXG4iKQ0KICAgICMgICAgICAgY2F0KCJMb3cgIixtaW4odiksICJcbiIpDQogICAgIyAgICAgICBjYXQoIkhpZ2ggIixtYXgodiksIlxuIiApDQogICAgIyAgICAgICBjYXQoIkF2ZyAiLCBtZWFuKHYpLCJcbiIpDQogICAgIyAgICAgICBjYXQoIlN0ZERldiIsc2QodiksIlxuIikNCiAgICAjICAgICAgIGNhdCgiICAgICAgICAgICAgICAgICAgIiwiXG4iKQ0KICAgICMgDQogICAgIyANCiAgICAjIA0KICAgICMgfQ0KICAgfQ0KICAgcmV0dXJuKHYpDQogICB9DQoNCg0KYGBgDQoNCk5vdyBydW4gTmV0U2NvcmVzIGZvciB0aGUgcGx1czFfNSB3aXRoIGEgaGFuZGljYXAgb2YgMw0KDQpgYGB7cn0NCnQxIDwtIE5ldHNjb3JlcyhwbHVzMV81ICxnbVBhciw0LGdldFN0cm9rZXMoSFJHTUNhcCwzKSkNCnQxDQoNCg0KYGBgDQpOb3cgdGhlIGhpZ2hlciBjYXAgcGxheWVycyAtIHVzZSAxMw0KDQpgYGB7cn0NCnQyID0gTmV0c2NvcmVzKHBsdXMxMV8xNSAsZ21QYXIsNCxnZXRTdHJva2VzKEhSR01DYXAsMTMpKQ0KdDINCmBgYA0KDQoNCiMgY29tYmluZWQgc2NvcmluZyBmdW5jdGlvbiANCiMgZG8gTmV0c2NvcmVzIGZvciB0d28gZGlmZmVyZW50IGhhbmRpY2FwIGdyb3VwcyBhbmQgdHJhY2sgd2hpY2ggdGVhbSBvciBncm91cCB3aW5zDQojIHRyYWNrIHRoZSBudW1iZXIgb2Ygd2lucyBhbmQgbG9zZXMgYnkgdGVhbQ0KIyBjb21lIGJhY2sgYW5kIGdldCBiaXJkaWVzIG9yIGJldHRlciAtIGdyb3NzIGFuZCBuZXQNCg0KYGBge3J9DQpSdW5OZXRTY29yZXMgPSBmdW5jdGlvbihwbHVzMV81LHBsdXMxMV8xNSwgcGFyLGNudF9OYnJfYmFsbHMsbmJyVHJpYWxzLFRlYW0xQ2FwLFRlYW0yQ2FwKXsNCiAgICNwcm9iMSBhbmQgcHJvYjIgYXJlIHZhbHVlcyBsaWtlIHBsdXMxMV8xNSBvciBwbHVzMV81DQogICAjcGFyIGlzIHRoZSB2YXIgbGlrZSBnbVBhcg0KICAgI2NudF9ObWJfYmFsbHMgLSBob3cgbWFueSBvZiB0aGUgdGVhbSBvZiA0IHdpbGwgY291bnQgLSANCiAgICNuYnJUcmFpbHMgLSBob3cgbWFueSBtYXRjaGVzIGFyZSB0byBiZSBzaW11bGF0ZWQgZWcgMTAwLCAyMCwwMDANCiAgICMgDQogICBUZWFtMW5hbWUgPC0gZGVwYXJzZShzdWJzdGl0dXRlKHBsdXMxXzUpKQ0KICAgVGVhbTJuYW1lIDwtIGRlcGFyc2Uoc3Vic3RpdHV0ZShwbHVzMTFfMTUpKQ0KICAgICB2PXJlcCgiTkEiLG5iclRyaWFscykgIyBob2xkZXIgZm9yIHJlc3VsdHMNCiAgICAgY250VGVhbTEgPSAwDQogICAgIGNudFRlYW0yID0gMA0KICAgICB0aWVkID0gMA0KICAgICBmb3IgKGkgaW4gMTpuYnJUcmlhbHMpew0KIyAgICAgICAjIHVzZSA0IGFzIGFsbCBiYWxscyBjb3VudCAtIGNoYW5nZSBsYXRlciBpZiBuZWVkZWQNCiAgICAgICB0ZWFtMV9SZXMgPSBOZXRzY29yZXMocGx1czFfNSxwYXIsY250X05icl9iYWxscyxnZXRTdHJva2VzKEhSR01DYXAsVGVhbTFDYXApKQ0KICAgICAgIHRlYW0yX1JlcyA9IE5ldHNjb3JlcyhwbHVzMTFfMTUscGFyLGNudF9OYnJfYmFsbHMsZ2V0U3Ryb2tlcyhIUkdNQ2FwLFRlYW0yQ2FwKSkNCiAgICAgICAgICB0MVN1bSA9IHN1bSggdGVhbTFfUmVzKQ0KICAgICAgICAgIHQyU3VtID0gc3VtKHRlYW0yX1JlcyApDQogICAgICAgICAgcmVzID0gIHQxU3VtIC0gdDJTdW0NCiAgICAgICAgICAjY2F0IChpICwiIFRlYW0gTmV0IERpZmYgaXMgIiwgcmVzLCAiXG4iKQ0KICAgICAgIGlmIChyZXMgPCAwICl7DQogICAgICAgd2lubmVyID0gcGFzdGUgKGksIiAiLFRlYW0xbmFtZSAsIHQxU3VtICwgIiB2cyAiICwgdDJTdW0gLCAiXG4iKQ0KICAgICAgIGNudFRlYW0xID0gY250VGVhbTEgKyAxDQogICAgICAgDQogICAgICAgfQ0KDQogICAgICAgaWYgKHJlcyA+IDAgKXsNCiAgICAgICAgICB3aW5uZXIgPSBwYXN0ZSAoaSwiICIsVGVhbTJuYW1lICwgdDJTdW0gLCAiIHZzICIgLCB0MVN1bSAsICJcbiIpDQogICAgICAgICAgY250VGVhbTIgPSBjbnRUZWFtMiArIDENCiAgICAgICAgIH0NCiAgICAgIGlmIChyZXMgPT0gMCApew0KICAgICAgICAgIHdpbm5lciA9IHBhc3RlIChpLCIgIiwiVGllZCAiICwgdDJTdW0gLCAiIHZzICIgLCB0MVN1bSAsICJcbiIpDQogICAgICAgICAgdGllZCA9IHRpZWQgKzENCiAgICAgICAgIH0NCiAgICAgICAgIA0KICAgICB2W2ldPXdpbm5lciAgICAgDQogICAgfQ0KICAgICBjYXQgKCJGaW5hbCBSZXN1bHRzIGZvciAiLG5iclRyaWFscywiIHRyaWFscyB3aXRoIExvdyBjYXAgb2YgOiAiLFRlYW0xQ2FwLCAidnMgSGlnaCBDYXAgb2YgIiAsIFRlYW0yQ2FwLCAiXG4iKQ0KICAgICAgIyBjYXQoICB2LCAiXG4iKQ0KICAgICAgY2F0IChUZWFtMW5hbWUsICIgd2lucyA9IiwgY250VGVhbTEsIlxuIiAgKQ0KICAgICAgY2F0IChUZWFtMm5hbWUsICIgd2lucyA9IiwgY250VGVhbTIgLCJcbiIgKQ0KICAgICAgY2F0ICgiVGllcyA9ICIgLHRpZWQgLCJcbiIpDQogICAgICANCn0gICANCmBgYA0KDQpUZXN0IHRoZSBmdW5jdGlvbg0KYGBge3J9DQp0ZXN0UmVzID0gUnVuTmV0U2NvcmVzKHBsdXMxXzUscGx1czExXzE1LHBhciA9IGdtUGFyLGNudF9OYnJfYmFsbHMgPSA0LG5iclRyaWFscyA9IDEwMDAsVGVhbTFDYXAgPSAzLFRlYW0yQ2FwID0gMTEpDQpgYGANCkxvb2sgYXQgdGhlIGNvbWJpbmF0aW9ucyBvZiB0aGUgcGx1czFfNSBmcm9tIDEgdG8gIDUgdmVyc3VzIHRoZSBwbHVzMTFfMTUgZnJvbQ0KMTEgdG8gMTQgKGNhcHMgYXJlIG1heGVkIGF0IDE0KQ0KDQpgYGB7cn0NCmxvd2NhcHMgPSBjKDEsMiwzLDQsNSkNCmhpZ2hjYXBzID0gYygxMSwxMiwxMywxNCkNCmZvciAoaSBpbiAxOmxlbmd0aChsb3djYXBzKSl7DQogICBmb3IgKGogaW4gMTpsZW5ndGgoaGlnaGNhcHMpKXsNCiAgICNjYXQgKCJsb3djYXBzID0iLCBsb3djYXBzW2ldLCAiIGhpZ2hjYXBzID0gIiwgaGlnaGNhcHNbal0sIlxuIiApIA0KICAgICAgDQogICBSdW5OZXRTY29yZXMocGx1czFfNSxwbHVzMTFfMTUscGFyID0gZ21QYXIsY250X05icl9iYWxscyA9IDQsbmJyVHJpYWxzID0gMTAwMCxUZWFtMUNhcCA9IGxvd2NhcHNbaV0sVGVhbTJDYXAgPSBoaWdoY2Fwc1tqXSkNCiAgICAgY2F0KCIgICIsIlxuIikNCiAgIH0NCn0NCg0KYGBgDQpOb3cgbG9vayBhdCB0aGUgc2FtZSBTaW11bHRpb24gYXMgYWJvdmUgYnV0IHVzZSAyIGFuZCAzIGJhbGxzIGNvdW50ZWQgc2luY2UgdGhlIHByZXZpb3VzIHJ1biBjb3VudGVkIGFsbCA0IGJhbGxzIE1BWSBIQVZFIFRPIENIQU5HRSBUSEUgTE9HSUMgVE8gQ09VTlQgVEhFIExPV0VTVCAyIE9SIDMgQkFMTFMgUEVSIEhPTEUNCg0KDQoNCg0KDQoNCg0KICAgDQogICANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4NCg0KV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuDQoNClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4NCg==