I've started to play with Ruby on Rails to make some plugins for Siri Proxy Server.
I am inexperienced with Ruby but have manage the basics.
what I have done:
################ Commands
listen_for (/show a demo to (.*)/i) do |name|
show_demo
request_completed
end
################ Actions
def show_demo(name)
say "Hi #{name}, let me do a quick demo for You."
say "For example if You tell me 'Turn on sidelight' I will turn the sidelights in Living room like now..."
system "/usr/local/bin/tdtool --on 2"
say "That was the sidelights, and now if like I can turn on the gallery for You, just tell me 'turn on gallery' like so... "
system "/usr/local/bin/tdtool --on 3"
say "This only part of things I can do after mod."
say "Now I will turn all devices off..."
system "/usr/local/bin/tdtool --off 3"
system "/usr/local/bin/tdtool --off 2"
say " Thank You #{name}, and goodbye."
end
The problem is when I'll start the demo all the actionssystem "..." are executed before Siri start to say anything .
How can I delay above action to put them in right place in time to execute them right after words I want?
Thank You in advance.
The problem is that say won't wait for Siri to actually say the words, it just sends a packet over to your iDevice and then goes on. The simplest approach i can think of would be to wait a few seconds, depending on how long the text is. So first we need a method that gives us the duration to wait (in seconds). I tried with the OSX built-in say command and got the following results:
$ time say "For example if You tell me 'Turn on sidelight' I will turn the sidelights in Living room like now..."
say 0,17s user 0,05s system 3% cpu 6,290 total
$ time say "That was the sidelights, and now if like I can turn on the gallery for You, just tell me 'turn on gallery' like so... "
say 0,17s user 0,06s system 2% cpu 8,055 total
$ time say "This only part of things I can do after mod."
say 0,13s user 0,04s system 5% cpu 2,996 total
So this means we have the following data:
# Characters w/o whitespace | Seconds to execute
------------------------------+---------------------
77 | 6.290
87 | 8.055
34 | 2.996
This leaves us with an average of about 0.0875 seconds per character. You may need to evaluate the average time for your scenario yourself and with more samples. This function will wrap say and then wait until the text was spoken out by Siri:
def say_and_wait text, seconds_per_char=0.0875
say text
num_speakable_chars = text.gsub(/[^\w]/,'').size
sleep num_speakable_chars * seconds_per_char
end
where gsub(/[^\w]/,'') will remove any non-word characters from the string. Now you can use this to simply say something and wait for it to be spoken out:
say_and_wait "This is a test, just checking if 0.875 seconds per character are a good fit."
Or you can also override the duration in special cases:
say_and_wait "I will wait for ten seconds here...", 10
Let me know if it works for you.
Related
I want to use message box as good morning message at 8:00 everyday but I couldnt assign the time interval. Can anyone help me to assign specicif time in uipath for message box
A couple of options:
While Loop
Rather than a delay you could use a while loop to check the time.
So your sequence would be
While Date.Now.Hour <> 8
End While
Message Box "Good Morning"
Obviously doing this you won't be able to do anything while the loop is running so isn't really going to work properly
While Loop in Parallel
The benefit this has over the above solution is that it can run while something else is running too
Parallel
While True
If Date.Now.Hour = 8
Message Box "Good Morning"
End If
End While
End Parallel
(Warning: I'm relatively new to Ruby.)
I'm writing a simple math script that will help my kids learn their addition facts. I want to show a countdown that they need to beat with their answers. So, for instance, while they're watching a countdown go from 5 to 0, they need to press '6 + enter' in order to correctly answer 3 + 3 = ?. The '6 + enter' should stop the countdown and advance them to the next question.
Currently, this is the code for my countdown:
5.downto(0) do |i|
print "\r00:00:#{'%02d' % i}"
sleep 1
end
This works, as far as it goes. It gives me the countdown that I want. The problem is that I need to solicit an answer from the user that will interrupt this countdown -- while the countdown process is still running. As it stands, I could put a
answer = gets.chomp
after the countdown, but that's obviously not going to help me very much.
Any ideas? I've tried to read up on how to run simultaneous processes, but the explanations have been a bit difficult to follow, and none of the ones that I read about seemed to allow the kind of user interaction I'm after.
Thanks in advance for your help.!
Threading is the answer. Here's what I did. It isn't perfect, but it gets the job done.
student_answer = nil
timer = Thread.new do
5.downto(0) do |i|
puts "\r00:00:#{'%02d' % i}"
sleep 1
end
puts 'Time is up'
end
answer = Thread.new do
puts 'What is your answer?'
student_answer = gets.chomp
end
answer.join(5)
timer.join
if $answer.nil?
puts 'No Answer'
else
puts "Your answer is #{student_answer }"
end
This code will produce the following output
What is your answer?
00:00:05
00:00:04
00:00:03
00:00:02
00:00:01
00:00:00
Time is up
No Answer
Of course, you can enter your answer at anytime, but the answer thread is killed about 5 seconds, and you can no longer enter any answer.
Unfortunately, I can not figure out how to kill the timer thread once an answer is inputted. If anyone have any ideas, please let me know.
I am getting into ruby and have been using threads for a little while now with out fully understanding them. I notice that when adding a thread to an array and if I add a sleep() command as the first command the thread does not run until I do a join which is mostly what I want. So I have 2 questions.
1.Is that suppose to happen?
2.Is there a better way to do that other then the way I'm doing it. Here is a sample code that I have to show what I'm talking about.
job = Array.new
10.times do |n|
job << Thread.new do
sleep 0.001
puts "done #{n}"
end
end
#job.each do |t|
#t.join
#end
puts "End of script"
Output is
End of script
If I remove the comments output is
done 1
done 0
done 7
done 6
done 5
done 4
done 3
done 2
done 9
done 8
End of script
So I use this now but I don't understand why it does that. Sometimes I notice even doing something like `echo hi` instead of sleep does the trick.
Thanks in advance.
Timing of threads isn't a defined behavior. Once you put them to sleep, they will be put in a queue to be run later. You can't ever expect it to run one way or another.
Your main program doesn't take very long to run, so it is likely to happen to finish before your other threads get picked back up to run again. Really, when you think about it, 0.001 seconds is quite a long time to computer, so spinning off 10 threads in that time is likely to happen -- but even if it takes longer, there is no guarantee the thread will resume immediately after .001 seconds. Often there's really no guarantee it won't start before .001 seconds, either, but sleep calls usually don't end early.
When you add the join calls, you are introducing additional time into your main thread which allows the other threads time to run, so this behavior is expected.
I'm using celluloid's every method to execute a block every microsecond however it seems to always call the block every second even when I specify a decimal.
interval = 1.0 / 2.0
every interval do
puts "*"*80
puts "Time: #{Time.now}"
puts "*"*80
end
I would expect this to be called every 0.5 seconds. But it is called every one second.
Any suggestions?
You can get fractional second resolution with Celluloid.
Celluloid uses the Timers gem to manage the every, which does good floating point time math and ruby's sleep which has reasonable sub-second resolution.
The following code works perfectly:
class Bob
include Celluloid
def fred
every 0.5 do
puts Time.now.strftime "%M:%S.%N"
end
end
end
Bob.new.fred
And it produces the following output:
22:51.299923000
22:51.801311000
22:52.302229000
22:52.803512000
22:53.304800000
22:53.805759000
22:54.307003000
22:54.808279000
22:55.309358000
22:55.810017000
As you can see, it is not perfect, but close enough for most purposes.
If you are seeing different results, it is likely because of how long your code takes in the block you have given to every or other timers running and starving that particular one. I would approach it by simplifying the situation as much as possible and slowly adding parts back in to determine where the slowdown is occurring.
As for microsecond resolution, I don't think you can hope to get that far down reliably with any non-trivial code.
The trivial example:
def bob
puts Time.now.strftime "%M:%S.%N"
sleep 1.0e-6
puts Time.now.strftime "%M:%S.%N"
end
Produces:
31:07.373858000
31:07.373936000
31:08.430110000
31:08.430183000
31:09.062000000
31:09.062079000
31:09.638078000
31:09.638156000
So as you can see, even just a base ruby version on my machine running nothing but a simple IO line doesn't reliably give me microsecond speeds.
I'm using the Selenium WebDriver and Ruby to perform some automation and I ran into a problem of a captcha around step 3 of a 5 step process.
I'm throwing all the automation in a rake script so I'm wondering is there a command to pause or break the script running temporarily until I enter data into the captcha and then continue running on the next page.
To build on seleniumnewbie's answer and assuming that you have access to the console the script is running on:
print "Enter Captcha"
captchaTxt = gets.chomp
yourCaptchaInputWebdriverElement.send_keys captchaTxt
If you just want to pause and enter the captcha in your browser, you can just have it prompt at the console to do that very thing and it'll just sit there.
print "Enter the captcha in your browser"
gets
You could also set the implicit wait to decently long period of time so that Selenium would automatically see the next page and move out. However, this would leave the important Captcha step (for documenting / processes sake) out of your test unless you're pretty anal with your commenting.
Since this is an actively participating test requiring user input I would say that making the tester press "enter" on the console is the way to go.
Since you are writing the test in a script, all you need to do is add a sleep in your test i.e. 'sleep 100' for example.
However, it is bad to add arbitrary sleeps in tests. You can also do something like "Wait for title 'foo'" where 'foo' is the title of the page in Step 4. It need not be title, it can be anything, but you get the idea. Wait for something semantic which indicates that step 3 is done and step 4 is ready to start.
This way, its more targeted wait.
This has been implemented in JAVA, but similar technique.Your solution could be found here