functions/Invoke-PSQuiz.ps1

#load a quiz from a json file
function Invoke-PSQuiz {
    [CmdletBinding(DefaultParameterSetName = 'path')]
    [OutputType('pzQuizResult')]
    [alias('Start-PSQuiz')]
    param(
        [Parameter(
            Position = 0,
            Mandatory,
            ValueFromPipelineByPropertyName,
            HelpMessage = 'Enter the full path to the quiz file',
            ParameterSetName = 'path'
        )]
        [ValidateScript({Test-Path -path $_},ErrorMessage = "Failed to find or validate {0}.")]
        [String]$Path,

        [Parameter(
            ParameterSetName = 'name',
            HelpMessage = 'Specify the quiz name.'
        )]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({Get-PSQuiz -Name $_},ErrorMessage = "Can't find a quiz called {0} in `$PSQuizPath.")]
        [String]$Name
    )
    begin {
        Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Starting $($MyInvocation.MyCommand)"
        Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN ] Running under PowerShell version $($PSVersionTable.PSVersion)"
    } #begin

    process {
        #6 July 2026 Do not run quiz in the VSCode Integrated console since it doesn't display images properly.
        if ($Host.Name -eq 'Visual Studio Code Host') {
            Write-Warning "Running a PSQuiz is not supported in the integrated VS Code terminal."
            return
        }
        if ($PSCmdlet.ParameterSetName -eq 'Name') {
            Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Getting path to $Name quiz"
            $Path = (Get-PSQuiz -Name $Name).path
        }
        Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Loading test from $Path"
        Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Test Details:"

        $in = Get-Content -Path $path | ConvertFrom-Json
        Write-Verbose "`n$(($in.metadata | Out-String).Trim())"
        #29 June 2026 Get protection setting from the metadata

       # $title = '{0} [[v{1}]]' -f $in.metadata.name, $in.metadata.version
       # $title = $in.metadata.name

       #align the title to the center of the image
       $logo = ($in.Logo -AND (Test-Path $in.Logo)) ? $in.Logo : $global:PSQuizTheme.defaultLogo

       $titlePad = ((Get-SpectreImage -ImagePath $logo -MaxWidth 10) | Get-SpectreRenderableSize).height/2 -1
        $title = "[{0}]{1}[/]" -f $psQuizTheme.Title,$in.metadata.name | Format-SpectrePadded -top $titlePad -Bottom 0 -Left 1 -Right 0
        $version = $in.metadata.version
        $QuestionCount = 0
        $CorrectCount = 0
        #randomize the questions
        $AllQuestions = $in.questions | Get-Random -Count $in.questions.count
        #$AllCount is used in the private Invoke-QuizQuestion function
        $AllCount = $AllQuestions.count

        #capture the quiz start time
        $StartTime = Get-Date
        foreach ($question in $AllQuestions) {
            $data = @((Get-SpectreImage -ImagePath $logo -MaxWidth 10),$title) |
            Format-SpectreColumns |
            Format-SpectrePadded -Top 1 -Left 1 -Right 0 -Bottom 1
            $width = ($data | Get-SpectreRenderableSize).Width + 5
            write-information $data
            $data | Format-SpectrePanel -Color $psQuizTheme.BorderColor -Header "v$Version" -Width $width |
            Out-SpectreHost

            $QuestionCount++
            $answer = $question | Invoke-QuizQuestion -title $title -version $version -Protected:$in.metadata.protected
            Write-Verbose "Answer = $answer"
            if ($answer -is [Int]) {
                Write-Verbose 'Ending the quiz.'
                #decrease the question count since the last one didn't technically get an answer
                $QuestionCount--
                break
            }
            elseif ($answer) {
                $CorrectCount++
            }
            #Pause
            Read-SpectrePause
        }

        #capture the stop time
        $StopTime = Get-Date
        #This is the output from this function
        #19 June 2026 Update to include GPA
        [PSCustomObject]@{
            PSTypeName     = 'psQuizResult'
            Test           = $in.metadata.Name
            TestVersion    = $in.metadata.version -as [Version]
            TotalQuestions = $QuestionCount
            TotalCorrect   = $CorrectCount
            GPA            = (Get-GPA -Correct $CorrectCount -Possible $QuestionCount).Grade
            Date           = (Get-Date)
            TestTime       = New-TimeSpan -Start $StartTime -End $StopTime
            Path           = Convert-Path $Path
        }
    } #process
    end {
        Write-Verbose "[$((Get-Date).TimeOfDay) END ] Ending $($MyInvocation.MyCommand)"
    } #end
}