PSChristmasFunctions.ps1
#import data from json $xmasData = Get-Content $PSScriptRoot\data.json | ConvertFrom-Json #region Private helper functions for the PSChristmas class-based module Function PlayTune { [cmdletbinding()] [outputtype("none")] Param() Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" <# The first number is the reciprocal of the duration and the rest is the note and octave (which we use for getting the frequency). For example, 4A4 is a quarter A note #> #first verse only $notes = Write-Output 4A4 4A4 2A4 4A4 4A4 2A4 4A4 4C4 4F3 8G3 1A4 ` 4Bb4 4Bb4 4Bb4 8Bb4 4Bb4 4A4 4A4 8A4 8A4 4A4 4G3 4G3 4A4 2G3 2C4 ` 4A4 4A4 2A4 4A4 4A4 2A4 4A4 4C4 4F3 4G3 1A4 4Bb4 4Bb4 4Bb4 4Bb4 ` 4Bb4 4A4 4A4 8A4 8A4 4C4 4C4 4Bb4 4G3 1F3 function Play([int] $freq, [int] $duration) { [console]::Beep($freq, $duration) } function GetNoteFreq([string]$note) { # n is the number of half steps from the fixed note. $note -match '([A-G#]{1,2})(\d+)' | Out-Null $octave = ([int] $matches[2]) - 4 $n = $octave * 12 + ( GetHalfStepsFromA $matches[1] ) $freq = $f0 * [math]::Pow($a, $n) return $freq } function GetHalfStepsFromA([string] $note) { switch ($note) { 'A' { 0 } 'A#' { 1 } 'Bb' { 1 } 'B' { 2 } 'C' { 3 } 'C#' { 4 } 'Db' { 4 } 'D' { 5 } 'D#' { 6 } 'Eb' { 6 } 'E' { 7 } 'F' { 8 } 'F#' { 9 } 'Gb' { 9 } 'G' { 10 } 'G#' { 11 } 'Ab' { 11 } } } # # Note is given by fn=f0 * (a)^n # a is the twelth root of 2 # n is the number of half steps from f0, positive or negative. # f0 used here is A4 at 440 Hz # $f0 = 440; $a = [math]::pow(2, (1 / 12)) # Twelth root of 2 $StandardDuration = 1000 foreach ($note in $notes) { $note -match '(\d)(.+)' | Out-Null $duration = $StandardDuration / ([int] $matches[1]) $playNote = $matches[2] $freq = GetNoteFreq $playNote Play $freq $duration Start-Sleep -milli 50 } Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } Function ShowGraphic { [cmdletbinding()] [outputtype("none")] Param() # Clear-Host Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" $Msg1 = @" .:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:. . * . . /.\ Merry Christmas . . /..'\ from all of us . . /'.'\ in PowerShell . . /.''.'\ . . /.'.'.\ . . /'.''.'.\ . . ^^^[_]^^^ . . . . . . . .:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:._.:*~*:. "@ $Msg2 = @" _... o_.-"` `\ .--. _ `'-._.-'""-; _ .' \`_\_ {_.-a"a-} _ / \ _/ .-' '. {c-._o_.){\|` | (@`-._ / \{ ^ } \\ _/ `~\ '-._ /'. } \} .-. |>:< '-.__/ '._,} \_/ / ()) | >:< `'---. ____'-.|(`"` \ >:< \\_\\_\ | ; \ \\-{}-\/ \ \ '._\\' /) '. /( `-._ _____ _ _____ __.'\ \ / \ / \ / \ \ \ _.'/^\'._.'/^\'._.'/^\'.__) \ ,==' `---` '---' '---' ) `"""""""""""""""""""""""""""""""` "@ $msg3 = @" ___ /` `'. / _..---; | /__..._/ .--.-. |.' e e | ___\_|/____ (_)'--.o.--| | | | .-( `-' = `-|____| |____| / ( |____ ____| | ( |_ | | __| | '-.--';/'/__ | | ( `| | '. \ )"";--`\ / \ ; |--' `;.-' |`-.__ ..-'--'`;..--'` "@ $msg4 = @" * , _/^\_ < > * /.-.\ * * `/&\` * ,@.*;@, /_o.I %_\ * * (`'--:o(_@; /`;--.,__ `') * ;@`o % O,*`'`&\ * (`'--)_@ ;o %'()\ * /`;--._`''--._O'@; /&*,()~o`;-.,_ `""`) * /`,@ ;+& () o*`;-';\ (`""--.,_0 +% @' &()\ /-.,_ ``''--....-'`) * * /@%;o`:;'--,.__ __.'\ ;*,&(); @ % &^;~`"`o;@(); * /(); o^~; & ().o@*&`;&%O\ `"="==""==,,,.,="=="==="` __.----.(\-''#####---...___...-----._ '` \)_`"""""` .--' ') o( )_-\ `"""` ` "@ $msg5 = @" .--------. * . |________| . * | __|/\ * .-'======\_\o/. /___________<>__\ |||||| / (o) (o) \ |||||| | _ O _ | . . |||||| | (_) (_) | |||||| \ '---' / * \====/ [~~~~~~~~~] \\// _/~||~`|~~~~~\_ _||-'`/ || | \`'-._ * * .-` )| ; || |) ; '. / `--.| || | | `\ | \ |||||) |-, \ . \ .; _ ; |_, | `'''||` ,\ (_) /, `.__/ ||.` '. .' `. * * || ` ' ' ` \ || ; . * || | . || | * || | .__.-""-.__.-"""|| ;.-"""-.__.-""-.__. || / ||'. .' || '-._ _ _ _ _.-' `""` "@ $msg6 = @" _ .-(_) / _/ .-' \ / '. ,-~--~-~-~-~-, {__.._...__..._} ,888, ,888, /\##" 6 6 "##/\ ,88' `88, ,88' '88,__ |(\` (__) `/)| __,88' `88 ,88' .8(_ \_____\_ '----' _/_____/ _)8. 8' 88 (___)\ \ '-.__ __.-' / /(___) 88 (___)88 | '--' | 88(___) 8' (__)88,___/ \___,88(__) __`88,_/__________________\_,88`__ / `88, |88| ,88' \ / `88, |88| ,88' \ /____________`88,_\88/_,88`____________\ /88888888888888888;8888;88888888888888888\ /^^^^^^^^^^^^^^^^^^`/88\\^^^^^^^^^^^^^^^^^^\ / |88| \============, \ /_ __ __ __ _ __ |88|_|^ MERRY | _ ___\ |;:. |88| | CHRISTMAS! | | |;;:. |88| '============' | |;;:. |88| | |::. |88| | |;;:' |88| | |:;, |88| | '---------------------""""---------------------' "@ $i = Get-Random -Minimum 1 -Maximum 6 $selected = ($msg1, $msg2, $msg3, $msg4, $msg5, $msg6 | Get-Random) If ([bool]!($i % 2)) { Write-Host -ForegroundColor Green -Object $selected } else { Write-Host -ForegroundColor Red -Object $selected } Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #endregion #region Class Enum ListStatus { Naughty Nice } Class PSChristmas { #class properties [string]$Greeting [string]$ElfName [ListStatus]$List [string]$ChristmasDay [int32]$DaysRemaining [string]$CountDown #class methods [void]Refresh() { Write-Verbose "[CLASS] Invoking Refresh()" #calculate christmas for the current year that should be culture aware $Christmas = [datetime]::new( (Get-Date).Year, 12, 25) Write-Verbose "[CLASS] Christmas this year is $Christmas" $this.ChristmasDay = $Christmas.DayOfWeek $span = $Christmas - (Get-Date) $this.DaysRemaining = $span.totalDays #strip off milliseconds $timestring = $span.ToString() $this.CountDown = $timestring.Substring(0, $timestring.LastIndexOf(".")) Write-Verbose "[CLASS] Getting new greeting" $this.Greeting = New-PSChristmasGreeting } [void]Play() { Write-Verbose "[CLASS] Invoking Play()" PlayTune } [void]Show() { Write-Verbose "[CLASS] Invoking Show()" ShowGraphic } #class constructor PSChristmas() { Write-Verbose "[CLASS] Invoking Constructor" $this.ElfName = New-ElfName if ( (Get-Date).Second % 2) { $this.List = [ListStatus]::Naughty } else { $this.List = [ListStatus]::Nice } #set the rest of the properties by invoking the defined #Refresh() method $this.Refresh() } } #close class definition #endregion #region Public functions # it appears that this function needs to be in the same file as the # class definition so that the typename can be discovered. Function New-PSChristmas { [cmdletbinding()] [OutputType("PSChristmas")] Param() Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" #New-Object -TypeName PSChristmas [PSChristmas]::New() Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } Function New-ElfName { [cmdletbinding()] [outputtype([string])] [alias("elfme")] Param() Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Try { [void](Get-Variable xmasData -ErrorAction Stop) $name = "{0} {1}{2}" -f (Get-Random $xmasData.FirstNames), (Get-Random $xmasData.Modifiers), (Get-Random $xmasData.LastNames) Write-Verbose "[PROCESS] Created name $name" #return the result $name } Catch { Write-Warning "Failed to find the `xmasdata` variable from the PSChristmas module." } Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } Function New-PSChristmasGreeting { [cmdletbinding()] [OutputType([string])] Param() Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" } Process { Try { [void](Get-Variable xmasData -ErrorAction Stop) $xmasData.Greeting | Get-Random -count 1 } Catch { Write-Warning "Failed to find the `xmasdata` variable from the PSChristmas module." } } End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } } Function Get-PSChristmasPresent { [cmdletbinding()] [OutputType([string])] Param( [ValidateRange(1, 10)] [ValidateScript( { if ($_ -gt 10) { Throw "Do you want to get on the the naughty list? There is a 10 present limit." $false } else { $True } })] [int]$Count = 1 ) Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[PROCESS] Getting $count presents" $presents = $xmasData.Presents | Get-Random -count $Count $presents Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } Function Invoke-Jingle { [cmdletbinding()] [OutputType("none")] [alias("jingle")] Param( [Parameter(Position = 0, ValueFromPipeline)] [PSChristmas]$Christmas = $(New-PSChristmas) ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" } #begin Process { Write-Verbose "[PROCESS] Using Christmas object for $($christmas.elfname)" Write-Festive "$($christmas.greeting), $($Christmas.elfname)" $Christmas.Play() } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } Function Show-PSChristmasMessage { [cmdletbinding()] [OutputType("none")] Param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [PSChristmas]$Christmas ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" } #begin Process { Write-Verbose "[PROCESS] Using Christmas object for $($christmas.elfname)" $Christmas.Show() } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } Function Write-Festive { [cmdletbinding()] [OutputType("None")] [alias("wf")] Param( [Parameter(Position = 0, Mandatory, HelpMessage = "Enter a text message", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$Text ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" $colors = ([enum]::GetNames([System.ConsoleColor])).Where( { $_ -ne $host.ui.RawUI.BackgroundColor }) } #begin Process { $Text.ToCharArray() | ForEach-Object -begin { #define a hashtable of parameters to splat to Write-Host $paramHash = @{NoNewLine = $True; } } -process { #use a color if not a space if ($_ -notmatch "\s") { $paramhash.ForegroundColor = (Get-Random -inputobject $colors -count 1) $paramhash.BackgroundColor = do { #get a background color that is different than the #foregroundcolor Get-Random -InputObject $colors -Count 1 } until($_ -ne $paramhash.ForegroundColor) } #if not whitespace else { #clear colors $paramhash.Remove("ForegroundColor") $paramhash.Remove("BackgroundColor") } #write each character to the host $_ | Write-Host @paramhash } -end { "`n" } } #Process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } } #endregion |