Reputation: 187
I have a working Powershell function that uses the System.Speech to read-out a random line from a text file, using the Get-Random cmdlet.
Unfortunately, the randomizer cmdlet doesn't seem to be doing such a good job by itself, as it repeats the same lines way too many times.
My text file contains just sentences.
function suggestion{
$suggestion=(Get-Random -InputObject (get-content C:\Tools\linesoftext.txt))
Add-Type -AssemblyName System.Speech
$synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$synth.Speak($suggestion)
}
I'm not sure if I can modify what I have, or rethink the way I'm trying to randomize the output--maybe by keeping track of what has been already played and loop? (I'm a bit stumped).
Upvotes: 2
Views: 2525
Reputation: 36297
I like Mathias's suggestion of shuffling the lines at launch, but if you want to keep in the motif of randomly selecting a line, but just don't want to hear the same lines over and over again set a threshold that it won't repeat at and store that many items in a global variable, and then add the last spoken line to it, and remove the first item whenever you have it speak a line. Something like:
function suggestion{
$lines = get-content C:\Tools\linesoftext.txt
$suggestion= Get-Random -InputObject ($lines | Where{$_ -notin $global:RecentSuggestions})
[array]$global:RecentSuggestions += $suggestion
If($global:RecentSuggestions.count -gt 20){$global:RecentSuggestions = $global:RecentSuggestions | Select -Skip 1}
Add-Type -AssemblyName System.Speech
$synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$synth.Speak($suggestion)
}
That'll keep track of up to 20 lines, and exclude those from the list of lines to randomly select from.
Upvotes: 2
Reputation: 174515
I'm loading it to my $profile and calling it from a Powershell command prompt.
In this case you could use your profile to read the lines into memory and then randomly shuffle them, this way the same line won't repeat. To advance through the list, you could employ a ScriptProperty
, like so:
Add-Type -AssemblyName System.Speech -ErrorAction SilentlyContinue
# One synthesizer on per shell should be enough
$__synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
# Read lines of text into memory, shuffle their order
$__lines = Get-Content C:\Tools\linesoftext.txt |Sort-Object {Get-Random}
# Add a script property to the $__lines variable that always returns the next sentence
$ScriptProperty = @{
Name = 'NextSentence'
MemberType = 'ScriptProperty'
Value = {
return $this[++$global:__idx % @($this).Count]
}
}
Add-Member @ScriptProperty -InputObject $__lines
# Speak the next sentence
function Get-Suggestion {
$global:__synth.Speak($global:__lines.NextSentence)
}
# Define alias `suggestion -> Get-Suggestion`
Set-Alias suggestion Get-Suggestion
Upvotes: 1