Can you create a "seconds" timer in Google Sheets? - google-sheets

Test Timer Spreadsheet
My understanding is that it isn't possible due to the limitations of Spreadsheet Settings > Calculations. I have successfully implemented Days, Hours, and Minutes into my timer - but it would be cool to have the Seconds as well.
Formulae:
=IFERROR(DAY(AH9-NOW()),0)
=IFERROR(HOUR(AH9-NOW()),0)
=IFERROR(MINUTE(AH9-NOW()),0)
*AH9 refers to the grey date cell in the timer
The Seconds timer isn't essential, more aesthetic - but I was interested to see if it was possible or not.

I have added some script into your workbook which does run a seconds timer.
The script that I have added is subject to the limitations of Apps Script run time but I have added various triggers in which should hopefully fire up the script once it has ended. I have also added a button to start the script as well but you may want to delete this out?
The script on its own will run for 4-5 mins, the triggers should set this so that there is only a small interval when the seconds won't be working.
Please note that to make this script run it needs to add a date into a cell - if you set A1 to colour black, you will see this there. The script will add this in if you delete it out so no real need to worry about leaving it there etc.
If you need to change the cell where this is, just change the global variable in the apps script project.
Hope this helps!!
The script I used was as below. The triggers that I used were a time driven trigger based on a minute timer then set it to every minute. As each function of the script works for 15 seconds, this creates a loop for a minute, which is triggered every minute.
I did play around but unfortunately I couldn't get the maths right to make it run for any longer :)...
var CELL_RANGE = 'A1'
function updateCell() {
for (i=0; i<15; i++){
Utilities.sleep(1000);
var date = new Date();
SpreadsheetApp.getActiveSheet().getRange(CELL_RANGE).setValue(date);
SpreadsheetApp.flush();
updateCell1()
}
}
function updateCell1() {
for (i=0; i<15; i++){
Utilities.sleep(1000);
var date = new Date();
SpreadsheetApp.getActiveSheet().getRange(CELL_RANGE).setValue(date);
SpreadsheetApp.flush();
updateCell2()
}
}
function updateCell2() {
for (i=0; i<15; i++){
Utilities.sleep(1000);
var date = new Date();
SpreadsheetApp.getActiveSheet().getRange(CELL_RANGE).setValue(date);
SpreadsheetApp.flush();
updateCell3()
}
}
function updateCell3() {
for (i=0; i<15; i++){
Utilities.sleep(1000);
var date = new Date();
SpreadsheetApp.getActiveSheet().getRange(CELL_RANGE).setValue(date);
SpreadsheetApp.flush();
updateCell()
}
}

Related

Actionscript settimeout not working

The Timer always jumps right into the function instead of waiting 2000 milliseconds
stop();
var hey:Number= 2000;
function exercise(frame) {
trace("sup");
this.gotoAndStop(frame);
}
setTimeout(exercise(2),hey);
trace(hey);
The setTimeout function (ie. not a Timer) takes the following parameters:
public function setTimeout(closure:Function, delay:Number, ... arguments):uint
Try:
// Save the return value so you can clear it later, otherwise your app for leak memory
var myTimeOut:uint = setTimeout(exercise, hey, 2);
trace(hey);
// the timeout closure object will not be garage collected if you do not clear it
clearTimeout(myTimeOut);
If you are doing this over and over, consider creating a Timer and setting/reseting the repeat count to 1 and then you can just restart the timer when need.

Moving data from one BlockingCollection to the other

I have a code, that copies integers to buffer1, then from buffer1 to buffer2 and then consumes all data from buffer2.
It processes 1000 values in 15 seconds, which is a lot of time compared to size of input. When I remove the " Task.Delay(1).Wait() " from the second task t2, it completes quite fast.
Now, my question is: is the slowdown because of two threads competing for the lock or is my code somehow faulty?
var source = Enumerable.Range(0, 1000).ToList();
var buffer1 = new BlockingCollection<int>(100);
var buffer2 = new BlockingCollection<int>(100);
var t1 = Task.Run
(
delegate
{
foreach (var i in source)
{
buffer1.Add(i);
}
buffer1.CompleteAdding();
}
).ConfigureAwait(false);
var t2 = Task.Run
(
delegate
{
foreach (var i in buffer1.GetConsumingEnumerable())
{
buffer2.Add(i);
//Task.Delay(1).Wait();
}
buffer2.CompleteAdding();
}
).ConfigureAwait(false);
CollectionAssert.AreEqual(source.ToList(), buffer2.GetConsumingEnumerable().ToList());
An update: this is just a demo code, I am blocking for 1 milisecond just to simulate some computations that take place in my real code. I put 1 milisecond there because it's such a small amount. I cannot believe that removing it makes the code complete almost immediately.
The clock has ~15ms resolution. 1ms is rounded up to 15. That's why 1000 items take ~15 seconds. (Actually, I'm surprised. On average each wait should take about 7.5ms. Anyway.)
Simulating work with sleep is a common mistake.

Update iOS Cordova WebView when app is in brackground

I'm building an app for iOS and Android. The app has a JavaScript counter, which updates the time every seconds. When I press the home button in Android and the I come back, the counter is right, it updates when the app is on background, but the iOS doesn't.
Is there a way to make the iOS update the WebView on background?
Sample JS code to update the counter:
setInterval(){
$('#div').html(counter);
counter -= 1;
}, 1000);
I'm afraid tt's not really possible to this in background mode on iOS.
As #Hanh-le mentioned iOS will stop (pause) your app in about 10 seconds from the moment you send it to the background.
Only some native functionality (service) can keep it running (like music playing, bluetooth running in the background, etc).
This services can actually call javascript otherwise Javascript will be stopped.
EDIT (added your function of setinterval) if you set up your interval like this:
window.localStorage.setItem(
'counterInterval',
setInterval({
$('#div').html(counter);
counter -= 1;
}, 1000);
);
You could save the timestamp on the onPause() event and also clear your interval
function onPause() {
clearInterval(window.localStorage.getItem('counterInterval');
window.localStorage.setItem('pauseTime', new Date());
}
and then check for the elapsed time on onResume() event and then update your counter:
function onResume() {
var resumeTime = new Date(),
pauseTime = window.localStorage.getItem('pauseTime'),
elapsedTime = (resumeTime.getTime() - pauseTime.getTime()) / 1000;
//you can round elapsedTime if you'd like
elapsedTime = Math.round(elapsedTime);
//correct the counter
$('#div').html(counter);
counter -= elapsedTime;
//set interval again until the next `Pause` event
window.localStorage.setItem(
'counterInterval',
setInterval({
$('#div').html(counter);
counter -= 1;
}, 1000);
);
}
This would save resources on background mode anyway...

How to make a timer keep running even if game enters background in cocos2d-x c++ game in ios

I am using a timer in my cocos2d-x game (c++) ios. I am using cocos2d-x 2.2 version.
My function for time is as follows
in my init
this->schedule(schedule_selector(HelloWorld::UpdateTimer), 1);
I have defined the function as follows.
void HelloWorld::UpdateTimer(float dt)
{
if(seconds<=0)
{
CCLOG("clock stopped");
CCString *str=CCString::createWithFormat("%d",seconds);
timer->setString(str->getCString());
this->unschedule(schedule_selector(HelloWorld::UpdateTimer));
}
else
{
CCString *str=CCString::createWithFormat("%d",seconds);
timer->setString(str->getCString());
seconds--;
}
}
Everythings is working fine. But i have this timer to keep running even if the game enters background state. I have tried commenting the body of didEnter Background in appdelegate but not successfull. Any help will be appreciated
Thanks
If the app gets in the background, apart from some special background threads, no other thread gets executed.
Best way for you would be to save the unix timestamp in a variable during didEnterBackground, and when app resumes, fetch the current unix timestamp and compare the delta, to get the total time passed and update your timer accordingly.
In my AppDelegate.cpp I wrote the following code in applicationDidEnterBackground function. Here I took a value of time in seconds whenever the app goes background and store it in a CCUserdefault key. And when the app comes to foreground I again took the local system time and subtracted that from the time I stored in the key. Following is my code
void AppDelegate::applicationDidEnterBackground()
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
CCLog("year------->%04d",timeinfo->tm_year+1900);
CCLog("month------->%02d",timeinfo->tm_mon+1);
CCLog("day------->%02d",timeinfo->tm_mday);
CCLog("hour------->%02d",timeinfo->tm_hour);
CCLog("minutes------->%02d",timeinfo->tm_min);
CCLog("seconds------->%02d",timeinfo->tm_sec);
int time_in_seconds=(timeinfo->tm_hour*60)+(timeinfo->tm_min*60)+timeinfo->tm_sec;
CCLOG("time in seconds is %d",time_in_seconds);
CCUserDefault *def=CCUserDefault::sharedUserDefault();
def->setIntegerForKey("time_from_background", time_in_seconds);
CCDirector::sharedDirector()->stopAnimation();
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}
void AppDelegate::applicationWillEnterForeground()
{
CCUserDefault *def=CCUserDefault::sharedUserDefault();
int time1=def->getIntegerForKey("time_from_background");
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime (&rawtime);
CCLog("year------->%04d",timeinfo->tm_year+1900);
CCLog("month------->%02d",timeinfo->tm_mon+1);
CCLog("day------->%02d",timeinfo->tm_mday);
CCLog("hour------->%02d",timeinfo->tm_hour);
CCLog("mintus------->%02d",timeinfo->tm_min);
CCLog("seconds------->%02d",timeinfo->tm_sec);
int time_in_seconds=(timeinfo->tm_hour*60)+(timeinfo->tm_min*60)+timeinfo->tm_sec;
int resume_seconds= time_in_seconds-time1;
CCLOG("app after seconds == %d", resume_seconds);
CCDirector::sharedDirector()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}
You can see and calculate the time the app remained in background.

Possible to fire a weekly trigger immediately then on a weekly basis?

I am wondering if it is possible to use weekly trigger to fire once and then go to a weekly schedule
Trigger trigger = TriggerUtils.MakeWeeklyTrigger(
"TriggerName",
dayOfweek,
timeOfDay.Hours,
timeOfDay.Minutes);
So I basically want when my service first starts my trigger to fire and run it's job. After that I want it to work on a weekly basis based on user settings(So maybe after first run a user set it to Monday 5:00am).
You can have multiple triggers associated with one job. One would fire immediately and only once and the other will fire weekly:
var jobDetail = new JobDetail("MyJob", "MyGroup", typeof(T));
// run in ten seconds, only once.
var once = new SimpleTrigger("Once",
null,
DateTime.UtcNow.AddSeconds(10),
null,
0,
TimeSpan.Zero);
// run weekly, start in 5 minutes to give 'once' trigger some time to run
Trigger weekly = TriggerUtils.MakeWeeklyTrigger(
"Weekly",
dayOfweek,
timeOfDay.Hours,
timeOfDay.Minutes);
weekly.StartTimeUtc = DateTime.UtcNow.Add(TimeSpan.FromMinutes(5));
once.JobName = jobDetail.Name;
weekly.JobGroup = jobDetail.Group;
once.JobName = jobDetail.Name;
weekly.JobGroup = jobDetail.Group;
_quartzScheduler.ScheduleJob(jobDetail, once);
_quartzScheduler.ScheduleJob(weekly);
Or you can schedule immediate trigger and when it fires reschedule to weekly:
private static volatile Boolean firstRun = false;
public void Execute(JobExecutionContext context) {
if(firstRun) {
Trigger weekly = TriggerUtils.MakeWeeklyTrigger(
"Weekly",
dayOfweek,
timeOfDay.Hours,
timeOfDay.Minutes);
context.Scheduler.RescheduleJob("Once", "MyGroup", weekly);
firstRun = false;
}
}
Another option is to just run your code on start up without involving Quartz. Just use ThreadPool. And then let Quartz handle weekly schedule only. This is possible if your code does not depend on Quartz which might be a good idea in general.

Resources