Monitor the Scripting Games 2013 leaderboard

Last year for my first participation in the Scripting Games, I used a brilliant script Watch-SG2011LeaderBoard written by Bartek Bielawski, the winner in the 2011 advanced category. I just fixed the URL of the 2012 scripting games and a few more things that I cannot remember. This script allowed me to see the top users and my own score.

But this year, the leaderboard isn’t hosted on, there are only 6 events and everybody can vote and comment scripts.
I decided to write a function from scratch that will get the leaderboard of a given category, that can include your username and score whatever your position and can refresh the top users list every 10 minutes by default.

Let’s see the ScriptingWife‘s rank for event 1 in the Beginner category

Get-PSH2013Learder -Track Beginner -Event 1 -User "ScriptingWife"

Let’s see the top 5 users in the Advanced category

Get-PSH2013Learder -Category Advanced -EventNumber 1 -TopUsers 5|            
Select Rank,Name,Score | ft -AutoSize

Now let’s see how much I (failed?|got appreciated?) 😦

Get-PSH2013Learder -Cat Advanced -Event 1 -User "_Emin_" -EveryMinutes 60 -Repeat

Enjoy the following code 😎 and if you really do, don’t forget to vote for me on event 1 πŸ˜‰ using this link:

#Requires -Version 3            
Function Get-PSH2013Learder {            
        Get the Scripting Games 2013 leaderboard of a given category
        Just for fun.
    .PARAMETER Category 
        The full name of the category you're looking for.
    .PARAMETER EventNumber
        Integer that represents the event number.        
    .PARAMETER Repeat
        Switch to go in an infinite loop.

    .PARAMETER EveryMinutes
        When executed in loop mode, it allows you to set how often the display is "refreshed".
        By default, it refreshes every 10 minutes.
    .PARAMETER UserName
        Your full user name. It will be added to the Top users list and show your rank and how much you scored.
    .PARAMETER TopUsers
        Integer that allows you how many top users are included in the output.
        Get-PSH2013Learder -Category Beginner -EventNumber 1 -UserName "ScriptingWife"
        Retrieve the top 10 users in the Beginner category for Event 1 and include ScriptingWife regardless her current position
        Get-PSH2013Learder -Category Advanced -EventNumber 1 -TopUsers 5| Select Rank,Name,Score | ft -AutoSize
        Retrieve the top 5 users in the Advanced category

        Get-PSH2013Learder -Category Advanced -EventNumber 1 -UserName "_Emin_" -EveryMinutes 60 -Repeat
        Retrieve the Top 10 users in the Advanced category, include my username and refresh the list every hour
    [Int]$TopUsers = 10            
    # Get the page             
    try {            
        $URI = ''            
        $page = (Invoke-WebRequest -Uri $URI -ErrorAction Stop).AllElements[0].OuterText -split "`n"            
    } catch {            
        Write-Warning "Failed to read the web page"            
    # Calculate the line number where the caterory keyword is located            
    $StartingLine = ($page | Select-String -Pattern "^$($Category)\s[$EventNumber]").LineNumber            
    Write-Verbose "Found category $Category at line $StartingLine"            
Process {            
    if ($PSCmdlet.ParameterSetName -eq 'Loop') {            
        Write-Verbose -Message ('Execution time: {0}' -f (Get-Date).ToLongTimeString()) -Verbose            
        # Call the function once, i.e., without the EveryMinutes parameters            
        $PSBoundParameters.Remove('EveryMinutes') | Out-Null            
        $PSBoundParameters.Remove('Repeat') | Out-Null            
        Get-PSH2013Learder @PSBoundParameters            
        # Wait            
        Write-Verbose -Message ('Waiting {0} minutes, next refresh at {1}' -f $EveryMinutes,(Get-Date).AddMinutes($EveryMinutes).ToLongTimeString()) -Verbose            
        Start-Sleep -Seconds ($EveryMinutes*60)            
        # Call the function recursively             
        Get-PSH2013Learder @PSBoundParameters -Repeat:$true -EveryMinutes $EveryMinutes            
    } else {            
        $i = 1            
        @($page)[$StartingLine..($StartingLine+$TopUsers-1)] | ForEach-Object -Process {            
            New-Object -TypeName PSObject -Property @{            
                Rank = $i            
                Name =  (($_ -split ",")[0] -replace ([char]8226),"").Trim()            
                Score = ($_ -split ", scoring")[1].Trim()            
        if ($UserName) {            
            try {            
                 $UserLine = ($page | Select-String -Pattern "^$([char]8226)\s$($UserName),\sscoring" -ErrorAction Stop)            
            } catch {            
                Write-Warning "Failed to find username $UserName, type the full username"            
            if ($UserLine) {            
                $UseratLine = ($UserLine).LineNumber            
                New-Object -TypeName PSObject -Property @{            
                    Rank = $UseratLine - $StartingLine            
                    Name =  $UserName            
                    Score = (($page | Select-String -Pattern "^$([char]8226)\s$($UserName),\sscoring").Line -split ", scoring")[1].Trim()            
            } else {            
                Write-Warning "Exact Username $UserName not found"            
End {}            

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s