; KiXtart Golf
;
;
Break on

; standard KiXgolf variables
Dim $sGolfScoreUDF, $bGolfScore, $sKiXgolfUDF, $sKiXGolfUDF, $sOutputFile
Dim $sTitle, $iRC, $sKiXGolfScrEngVer
Dim $sStartTimeDate, $sEndTimeDate, $sRunTime
Dim $iKiXGolfScore[3], $sOutput, $sResult
Dim $cpuTime,$ProcessorTimeSpent,$ConsColor

; specific variables
Dim $asTests, $sOutput, $sINIFile, $sTestResult, $sTest
Dim $iTests, $iPass, $iFail, $asInput

; set required options
$sTitle='Fragmentation'
$iRC=SetTitle('KiXtart Golf: '+$sTitle)
$iRC=SetOption('Explicit','on')
$iRC=SetOption('NoVarsInStrings','on')
$iRC=SetOption('WrapAtEOL','on')
$iRC=SetOption('CaseSensitivity','on')

CLS
$ConsColor = @COLOR

$sGolfScoreUDF=@scriptdir+'\'+'kixgolf3.udf'
If Exist($sGolfScoreUDF)
  Call $sGolfScoreUDF
  $bGolfScore=1
Else
  $bGolfScore=0
EndIf
$sKiXGolfScrEngVer = '3.0.3'

; this is the actual KiXgolf UDF
$sKiXGolfUDF=@scriptdir+'\kixgolf_fragmentation.udf'
Call $sKiXGolfUDF

; initialize official KiXtart Golf Score results file
$sOutputFile=@scriptdir+'\'+Left(@scriptname,InStrRev(@scriptname,'.'))+'txt'
$iRC=RedirectOutput($sOutputFile,1)
? '[code]'
$iRC=RedirectOutput('')

; load the test file
$sINIFile=@scriptdir+'\'+Left(@scriptname,InStrRev(@scriptname,'.'))+'ini'
$asTests=Split(ReadProfileString($sINIFile,'',''),Chr(10))
$iTests=Ubound($asTests)
ReDim preserve $asTests[$iTests-1]
$iPass=0
$iFail=0

; this is the start of the main loop
$sStartTimeDate=@DATE+' '+@TIME+'.'+Right('000'+@MSECS,3)
$cpuTime = processorTime()
;test each data set
For Each $sTest in $asTests
  $asInput=Split(ReadProfileString($sINIFile,$sTest,'In'),',')
  $sOutput=''+ReadProfileString($sINIFile,$sTest,'Out')
  ? $sTest "   "
  $sTestResult=''+F($asInput)
  If $sTestResult=$sOutput
   "passed"   
   $iPass=$iPass+1
  Else
   Color R/N
   "FAILED "
   Color $ConsColor
   "(should be:" $sOutput ", but was: " $sTestResult ")"
   $iFail=$iFail+1
  EndIf
Next

; this is the end of the main loop
$sEndTimeDate=@DATE+' '+@TIME+'.'+Right('000'+@MSECS,3)
$ProcessorTimeSpent = processorTime(,,$cpuTime)
$sRunTime=datetimediff($sStartTimeDate, $sEndTimeDate)
; this is the end of main loop


; generate KiXtart Golf Score
If $bGolfScore
  $iKiXGolfScore=KiXGolf($sKiXGolfUDF)
Else
  $iKixGolfScore=''
EndIf

; generating official KiXGolf Score
$sOutput=''
$sOutput=$sOutput+@CRLF+'KiXtart Engine'
$sOutput=$sOutput+@CRLF+'KiXtart Version     = '+@KIX+' (' + @SCRIPTEXE + ')'
$sOutput=$sOutput+@CRLF+'KiXGolf Script      = '+@SCRIPTNAME
$sOutput=$sOutput+@CRLF+' '
$sOutput=$sOutput+@CRLF+'Computer'
$sOutput=$sOutput+@CRLF+'OS                  = '+@PRODUCTTYPE
$sOutput=$sOutput+@CRLF+'CPU                 = '+@CPU
$sOutput=$sOutput+@CRLF+'Speed               = '+@MHZ+' MHz'
$sOutput=$sOutput+@CRLF+'Memory              = '+(Round(Cdbl(MemorySize(0))/2)*2)+' MB'
$sOutput=$sOutput+@CRLF+' '
$sOutput=$sOutput+@CRLF+'KiXGolf Scoring Engine'
$sOutput=$sOutput+@CRLF+'Scoring Engine      = '+$sKiXGolfScrEngVer
$sOutput=$sOutput+@CRLF+' '
$sOutput=$sOutput+@CRLF+'KiXGolf Score'
$sOutput=$sOutput+@CRLF+'Tournament          = '+$sTitle
$sOutput=$sOutput+@CRLF+'Processing Start    = '+$sStartTimeDate
$sOutput=$sOutput+@CRLF+'Processing End      = '+$sEndTimeDate
$sOutput=$sOutput+@CRLF+'Duration            = '+$sRunTime
$sOutput=$sOutput+@CRLF+'Used Processor Time = '+serialtime($ProcessorTimeSpent)
$sOutput=$sOutput+@CRLF+'# Tests Run         = '+$iTests
$sOutput=$sOutput+@CRLF+'# Tests Passed      = '+$iPass
$sOutput=$sOutput+@CRLF+'# Tests Failed      = '+$iFail
$sOutput=$sOutput+@CRLF+'Result              = '+IIf($iPass = $iTests,'passed','FAILED')
$sOutput=$sOutput+@CRLF+'KiXGolf Score       = '+$iKiXGolfScore
$sOutput=$sOutput+@CRLF+' '
$sOutput=$sOutput+@CRLF+'Thank you for participating in KiXtart Golf!'

; saving and displaying official KiXtart Golf Score
$iRC=RedirectOutput($sOutputFile,0)
? $sOutput+@CRLF+'[/code]'
$iRC=RedirectOutput('')
? $sOutput

; display score when using WKIX32
If @SCRIPTEXE='WKIX32.EXE'
  ? 'Press any key to continue...'
  Get $iRC
EndIf

Exit 0

; any modifications below this line will result in immediate disqualification
;support UDFs for date/time calculations
;FUNCTION      DateTimeDiff
;
;ACTION        Calculates the time difference between two date-times-groups
;
;AUTHOR        Jens Meyer (sealeopard@usa.net)
;
;VERSION       1.1
;
;KIXTART       4.20
;
;SYNTAX        DATETIMEDIFF(DTG1 [,DTG2])
;
;PARAMETYERS   DTG1
;              Required string as a date-time-group (DTG) in one of the following formats:
;              "YYYY/MM/DD HH:MM[:SS.MSECS]"
;              "YYYY/MM/DD" which assumes that HH:MM[:SS.MSECS] = 00:00:00.000
;              "HH:MM[:SS.MSECS]" which assumes that "YYY/MM/DD" = @DATE
;
;              DTG2
;              Optional string as date-time-group (DTG) in one of the following formats:
;              "YYYY/MM/DD HH:MM[:SS.MSECS]"
;              "YYYY/MM/DD" which assumes that HH:MM[:SS.MSECS] = @TIME
;              "HH:MM[:SS.MSECS]" which assumes that "YYY/MM/DD" = @DATE
;              DTG2 will default to the current date and time if not provided in the form of
;              @DATE+' ' +@TIME+'.'+@MSECS
;
;
;
;RETURNS       Returns difference DTG2-DTG1 as "YYYY/MM/DD HH:MM[:SS.MSECS]"
;
;REMARKS       none
;
;DEPENDENCIES  SERIALTIME() @ http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000039
;              SERIALDATE() @ http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000089
;
;EXAMPLE       $rc=DATETIMEDIFF('23:20:33','01:01:01.245')
;
;KIXTART BBS   http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000374
;
Function datetimediff($time1,$time2)
  Dim $date1, $date2, $datediff, $timediff

  $datetimediff=''

  If Not InStr($time1,' ')
    Select
    Case InStr($time1,'/')
      $time1=$time1+' 00:00:00.000'
    Case InStr($time1,':')
      $time1=@DATE+' '+$time1
    Case 1
      Exit 87
    EndSelect
  EndIf

  If Not InStr($time2,' ')
    Select
    Case InStr($time2,'/')
      $time2=$time2+' '+@TIME+'.'+Right('000'+@MSECS,3)
    Case InStr($time2,':')
      $time2=@DATE+' '+$time2
    Case 1
      $time2=@DATE+' '+@TIME+'.'+Right('000'+@MSECS,3)
    EndSelect
  EndIf

  $time1=Split($time1,' ')
  $date1=$time1[0]
  $time1=$time1[1]
  $time2=Split($time2,' ')
  $date2=$time2[0]
  $time2=$time2[1]

  $datediff=serialdate($date2)-serialdate($date1)
  $timediff=serialtime($time2)-serialtime($time1)
  If $timediff=>86400
    $timediff=$timediff-86400
    $datediff=$datediff+1
  EndIf
  $datediff=serialdate(serialdate('0000/00/00')+$datediff-1)
  $timediff=serialtime($timediff)

  $datetimediff=$datediff+' '+$timediff
  Exit 0
EndFunction

;FUNCTION      SerialDate
;
;ACTION        Convert dates to numbers (and back) for the purpose of performing date math
;
;AUTHOR        ScriptLogic (http://www.scriptlogic.com)
;
;CONTRIBUTOR   Jens Meyer (sealeopard@usa.net)
;
;VERSION       1.1
;
;SYNTAX        SERIALDATE(DATE)
;
;PARAMETERS    DATE or NUMBER
;              if a date is used, it must be in the form of "YYYY/MM/DD"
;              if a number is used, it must be a number previously derived from this function.
;
;RETURNS       If a date is passed to this function, the function returns a number. If a number is
;              passed to this function, a date "YYYY/MM/DD" is returned
;
;REMARKS       This function was developed as a core routine for the DateMath( ) function. In
;              normal usage, you would most like just use the DateMath( ) function which depends
;              on this function.
;              Algorithms used in the development of this routine were obtained from:
;              http://www.capecod.net/~pbaum/date/date0.htm
;
;              Fixed a couple of inconsistencies in the returned values and formatting
;
;DEPENDENCIES  none
;
;EXAMPLE       $rc=serialdate('2001/07/01')
;
;KIXTART BBS   http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000089
;
Function serialdate($ExpD)
  Dim $z,$h,$a,$b,$c,$y,$m,$d
  If InStr($ExpD,'/')
    $ExpD=Split($ExpD,'/')
    $y=Val($ExpD[0])
    $m=Val($ExpD[1])
    $d=Val($ExpD[2])
    If $m<3
      $m=$m+12
      $y=$y-1
    EndIf
    $SerialDate=$d+(153*$m-457)/5+365*$y+$y/4-$y/100+$y/400-306
  Else
    $z=0+$ExpD+306
    $h=100*$z-25
    $a=$h/3652425
    $b=$a-$a/4
    $y=(100*$b+$h)/36525
    $c=$b+$z-365*$y-$y/4
    $m=(5*$c+456)/153
    $d=$c-(153*$m-457)/5
    If $m>12
      $y=$y+1
      $m=$m-12
    EndIf
    $SerialDate=Right('0000'+$y,4)+'/'+Right('00'+$m,2)+'/'+Right('00'+$d,2)
  EndIf
EndFunction

;FUNCTION      SerialTime
;
;AUTHOR        Jens Meyer (sealeopard@usa.net)
;
;ACTION        Convert time to numbers (and back) for the purpose of performing time math
;
;VERSION       1.1
;
;KIXTART       4.20
;
;SYNTAX        SERIALTIME(STRTIME)
;
;PARAMETERS    STRTIME
;              Reqired string containing either a time "HH:MM[:SS.MSECS]" or an integer greater
;              than zero and less than 86400 representing seconds and fractions
;              e.g 20.040 for 20 seconds and 40 milliseconds
;
;RETURNS       If supplied a time, returns seconds since midnight. If supplied seconds since
;              midnight, returns time.
;
;REMARKS       Reworked function based on the ScriptLogic UDF but without dependencies and adapted for milliseconds
;              The original ScriptLogic UDF at
;              http://www.scriptlogic.com/kixtart/FunctionLibrary_ViewFunction.aspx?ID=SerialTime
;              cannot manage milliseconds and relies on three dependencies.
;
;DEPENDENCIES  none
;
;EXAMPLE       $rc=SERIALTIME('02:20:33.187')
;
;KIXTART BBS   http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000039
;
Function serialtime($strtime)
  Dim $hours, $minutes, $seconds, $milliseconds

  If InStr($strtime,':')
    $strtime=Split($strtime,':')

    Select
    Case Ubound($strtime)<3
      ReDim preserve $strtime[3]
      If InStr($strtime[2],'.')
        $strtime[3]=Right($strtime[2],Len($strtime[2])-InStr($strtime[2],'.'))
        $strtime[2]=Left($strtime[2],InStr($strtime[2],'.')-1)
      Else
        $strtime[3]=0
      EndIf
    Case Ubound($strtime)>3
      $serialtime=-1
      Exit 87
    EndSelect

    $hours=Val($strtime[0])
    If $hours<0 Or $hours>23
      $serialtime=-1
      Exit 87
    EndIf
    $minutes=Val($strtime[1])
    If $minutes<0 Or $minutes>59
      $serialtime=-1
      Exit 87
    EndIf
    $seconds=Val($strtime[2])
    If $seconds<0 Or $seconds>59
      $serialtime=-1
      Exit 87
    EndIf
    $milliseconds=Cdbl($strtime[3])
    If $milliseconds<0 Or $milliseconds>999
      $serialtime=-1
      Exit 87
    EndIf
    $serialtime=0.0+($hours*3600)+($minutes*60)+($seconds)+($milliseconds/1000)
  Else
    $strtime=Val(Cdbl($strtime)*1000)
    If $strtime<=86400000 And $strtime>=0
      $hours=$strtime/3600/1000
      $strtime=$strtime-($hours*3600*1000)
      $hours=Right('00'+$hours,2)
      $minutes=$strtime/60/1000
      $strtime=$strtime-($minutes*60*1000)
      $minutes=Right('00'+$minutes,2)
      $seconds=$strtime/1000
      $strtime=$strtime-($seconds*1000)
      $seconds=Right('00'+$seconds,2)
      $milliseconds=Left($strtime,3)
      $milliseconds=Right('000'+$milliseconds,3)
      $serialtime=$hours+':'+$minutes+':'+$seconds+'.'+$milliseconds
    Else
      $serialtime='-1'
      Exit 87
    EndIf
  EndIf
EndFunction

; this is a replacement for the formatnumber() function that seems to be buggy
Function numberformat($number,$digits)
  Dim $comma

  $comma=ReadValue('HKEY_CURRENT_USER\Control Panel\International','sDecimal')
  $digits=Val($digits)
  If $digits<0
    $digits=0
  EndIf
  $number=''+Round(Cdbl($number),$digits)
  If Not InStr($number,$comma)
    $number=$number+$comma
  EndIf
  $number=Split($number,$comma)
  If $digits=0
    $numberformat=$number[0]
    Return
  EndIf
  While Len($number[1])<$digits
    $number[1]=$number[1]+'0'
  Loop
  $number=Join($number,$comma)
  $numberformat=$number
EndFunction

;   ProcessorTime()
; 
;AUTHOR 
;   Lonkero
; 
;ACTION 
;   Returns Processor Time and optionally calculates spent time
; 
;VERSION 
;   1.0
; 
;VERSION HISTORY 
;   1.0 
;   22th july 2005
;   Initial public version.
; 
;SYNTAX 
;   ProcessorTime( [pid] , [machine] , [differ]) 
; 
;PARAMETERS 
;   PID - OPTIONAL
;      the Process who's processor time is to be retrieved.
;      Default is current process.
;   MACHINE - OPTIONAL
;      the machine, against which the query is to be performed.
;      Defaults to local
;   DIFFER - OPTIONAL
;      calculate the difference between current processor time and
;      the one given in arg.
; 
;RETURNS
;   ProcessorTime in seconds and the fragments
; 
;REMARKS 
;   well, was thinking about some way to write KiXflop() and came up with
;   this stuff :p
; 
;DEPENDENCIES 
;   none that I know of
;
;EXAMPLES
;   "current process processor time: "
;      $pt = ProcessorTime()
;      $pt ?
;   "current process processor time: " ProcessorTime(@pid,".",) ?
;   "processor time of 'processor time' query: " ProcessorTime(,,ProcessorTime(,,)) ?
;   "processor time spent on all these examples: " ProcessorTime(,,$pt) ?
;
;SOURCE
Function ProcessorTime(optional $pid, $machine, $differ)
Dim $objItem
 If VarType($pid) = 0 $pid = @pid EndIf
 If VarType($machine) = 0 $machine = "." EndIf
 For Each $objItem in GetObject("winmgmts:\\" + $machine + "\root\cimv2").ExecQuery("Select * from Win32_Process where processID = " + $pid,,48)
  $processorTime = (0.0 + $objItem.KernelModeTime + $objItem.UserModeTime)/10000000
 Next
 If VarType($differ) $processorTime = $processorTime - $differ EndIf
EndFunction

;FUNCTION      ATrim
;
;ACTION        Strips leading and trailing spaces from an input string or array and returns the result
;
;AUTHOR        Jens Meyer (sealeopard@usa.net)
;
;VERSION       1.3
;
;KIXTART       4.20
;
;SYNTAX        ATRIM(STRING)
;
;PARAMETERS    STRING
;              Required string or array from which to strip leading and trailing spaces
;
;RETURNS       Input string/array without leading and trailing spaces
;
;REMARKS       Function converts an array with a maximum of 26 dimensions
;
;DEPENDENCIES  none
;
;EXAMPLE       $array[0]=' String1'
;              $array[1]=' String2 '
;              $rc=atrim($array)
;
;KIXTART BBS   http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000031
;
Function atrim($array)
  Dim $element, $maxelements, $arraydim, $rc, $a

  Select
  Case Ubound($array,1)=-1
    $array=Trim($array)
  Case Ubound($array,2)=-1
    $maxelements=Val(Ubound($array))
    For $element=0 to $maxelements
      $array[$element]=Trim($array[$element])
    Next
  Case Ubound($array,27)=-1
    $arraydim=0
    Do
      $arraydim=$arraydim+1
    Until Ubound($array,$arraydim)=-1
    $arraydim=$arraydim-1
    If $arraydim<=26
      Dim $cmd, $vars
      $vars='$sub_a'
      For $a=2 to $arraydim
        $vars=$vars+', $sub_'+Chr($a+96)
      Next
      $cmd='dim '+$vars+@CRLF
      For $a=1 to $arraydim
        $cmd=$cmd+'for $sub_'+Chr($a+96)+'=0 to ubound($array,'+$a+')'+@CRLF
      Next
        $cmd=$cmd+'$array['+$vars+']=trim($array['+$vars+'])'+@CRLF
      For $a=1 to $arraydim
        $cmd=$cmd+'next'+@CRLF
      Next
      $rc=Execute($cmd)
    EndIf
  Case 1
  EndSelect

  $atrim=$array
EndFunction