• Coord timed events

    From Andrew Poulos@21:1/5 to All on Thu Jun 17 10:49:55 2021
    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    One way I though to handle them was to: put the timings into an array,
    sort the array (from lowest to highest), loop over the array and call setTimeout on each one.

    I was wondering if there's a better way like maybe creating a counter
    that runs until the largest/last timing is triggered? In this way I have
    only one thing to control should the user navigate to a different page component.

    Or maybe a countdown type timer that counts up to the largest timing?

    regards
    Andrew Poulos

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Andrew Poulos on Thu Jun 17 02:06:55 2021
    Andrew Poulos <ap_prog@hotmail.com> writes:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    One way I though to handle them was to: put the timings into an array,
    sort the array (from lowest to highest), loop over the array and call setTimeout on each one.

    Hmm... Why not just call setTimeout without sorting them? I must be
    missing some key part of the problem...

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrew Poulos@21:1/5 to Ben Bacarisse on Thu Jun 17 13:17:29 2021
    On 17/06/2021 11:06 am, Ben Bacarisse wrote:
    Andrew Poulos <ap_prog@hotmail.com> writes:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    One way I though to handle them was to: put the timings into an array,
    sort the array (from lowest to highest), loop over the array and call
    setTimeout on each one.

    Hmm... Why not just call setTimeout without sorting them? I must be
    missing some key part of the problem...

    If I have 12 setTimeout waiting to happen and the user gives focus to a different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple
    setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd
    rather not have lots of setTimeout running at the same time.

    Andrew Poulos

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Andrew Poulos on Thu Jun 17 11:20:49 2021
    Andrew Poulos <ap_prog@hotmail.com> writes:

    On 17/06/2021 11:06 am, Ben Bacarisse wrote:
    Andrew Poulos <ap_prog@hotmail.com> writes:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    One way I though to handle them was to: put the timings into an array,
    sort the array (from lowest to highest), loop over the array and call
    setTimeout on each one.
    Hmm... Why not just call setTimeout without sorting them? I must be
    missing some key part of the problem...

    If I have 12 setTimeout waiting to happen and the user gives focus to
    a different "component" I'll need to clear all the setTimeout.

    There's no way someone could know that from your original question!
    That's why I said I must be missing something. You have other
    constraints -- either imposed by previous design decisions or just from
    how you want to do things -- that make the obvious solution
    unattractive.

    If you could list the constraints, or at least say what it is you are
    actually doing, you might get some helpful suggestions.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Sauyet@21:1/5 to Andrew Poulos on Thu Jun 17 13:21:58 2021
    Andrew Poulos wrote:
    (response from Ben Bacarisse elided)
    Andrew Poulos wrote:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    If I have 12 setTimeout waiting to happen and the user gives focus to a different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd rather not have lots of setTimeout running at the same time.

    Dozens, hundreds, probably even thousands of `setTimeout` calls will
    probably not slow down modern browsers. But it would feel ... uncleanly.

    It would be easy enough to run a single `getInterval` timer that when it
    runs checks the remaining actions and runs all those whose time is at hand.
    You would need to choose a run-time interval short enough to capture the
    likely timing differences between your events but long enough not to clog
    up the event queue. For events measured in seconds, up to 300, I would
    think running every 250 milliseconds might be reasonable.

    Here's an implementation:

    ```
    const handler = (periodInMilliseconds) => (events) => {
    const start = Date .now ()
    let toProcess = events .map (
    ([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
    )
    const interval = setInterval (
    () => {
    const now = Date .now ()
    toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ())
    toProcess = toProcess .filter (e => e .runTime > now)
    },
    periodInMilliseconds
    )
    return {
    stop: (after = () => {}) => {clearInterval (interval); after ()}
    }
    }
    ```

    which might be used like this:

    ```
    const {stop} = handler (250) ([
    [() => console .log ('A'), 4],
    [() => console .log ('B'), 2],
    [() => console .log ('C'), 15],
    [() => console .log ('D'), 7],
    [() => console .log ('E'), 1],
    ])

    setTimeout (() => stop (() => console.log ('completed')), 10000)
    ```

    You call handler passing the period (250ms) and an array of arrays,
    each containing a function to run and the delay in seconds. You get
    back a `stop` function which will terminate the running (and call
    an optional callback afterward if you like.)

    At the start, the functions are paired with the time they should run.

    At each interval, we calculate the current time and, if checks each
    function. If it is now due, we run the function and remove it from
    the `toProcess` list.

    The example above would log `E` after one second, `B` after two
    seconds, `A` after four seconds, `D` after seven seconds. But
    because we call `stop` after ten seconds, the events are stopped
    before we reach `C`. Note that our optional callback will log
    `completed` at that time.

    This is a fairly naive version. We might want to improve it to clear
    the interval when the queue is empty. We might want to add an explicit
    `start` parallel to `stop`, to start the queue when we choose. Or we
    might want to specify the `stop` callback initially with the period.
    And many other improvements are certainly possible. But it's a decent
    start at the problem.
    .

    -- Scott

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrew Poulos@21:1/5 to Scott Sauyet on Fri Jun 18 11:03:49 2021
    On 18/06/2021 6:21 am, Scott Sauyet wrote:
    Andrew Poulos wrote:
    (response from Ben Bacarisse elided)
    Andrew Poulos wrote:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    If I have 12 setTimeout waiting to happen and the user gives focus to a
    different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple
    setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd
    rather not have lots of setTimeout running at the same time.

    Dozens, hundreds, probably even thousands of `setTimeout` calls will
    probably not slow down modern browsers. But it would feel ... uncleanly.

    It would be easy enough to run a single `getInterval` timer that when it
    runs checks the remaining actions and runs all those whose time is at hand. You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog
    up the event queue. For events measured in seconds, up to 300, I would
    think running every 250 milliseconds might be reasonable.

    Here's an implementation:

    ```
    const handler = (periodInMilliseconds) => (events) => {
    const start = Date .now ()
    let toProcess = events .map (
    ([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
    )
    const interval = setInterval (
    () => {
    const now = Date .now ()
    toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ())
    toProcess = toProcess .filter (e => e .runTime > now)
    },
    periodInMilliseconds
    )
    return {
    stop: (after = () => {}) => {clearInterval (interval); after ()}
    }
    }
    ```

    which might be used like this:

    ```
    const {stop} = handler (250) ([
    [() => console .log ('A'), 4],
    [() => console .log ('B'), 2],
    [() => console .log ('C'), 15],
    [() => console .log ('D'), 7],
    [() => console .log ('E'), 1],
    ])

    setTimeout (() => stop (() => console.log ('completed')), 10000)
    ```

    You call handler passing the period (250ms) and an array of arrays,
    each containing a function to run and the delay in seconds. You get
    back a `stop` function which will terminate the running (and call
    an optional callback afterward if you like.)

    At the start, the functions are paired with the time they should run.

    At each interval, we calculate the current time and, if checks each
    function. If it is now due, we run the function and remove it from
    the `toProcess` list.

    The example above would log `E` after one second, `B` after two
    seconds, `A` after four seconds, `D` after seven seconds. But
    because we call `stop` after ten seconds, the events are stopped
    before we reach `C`. Note that our optional callback will log
    `completed` at that time.

    This is a fairly naive version. We might want to improve it to clear
    the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we
    might want to specify the `stop` callback initially with the period.
    And many other improvements are certainly possible. But it's a decent
    start at the problem.

    Thanks. It's given me something I can work with.

    Andrew Poulos

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Sun Jun 20 23:48:40 2021
    måndag 21 juni 2021 kl. 08:40:37 UTC+2 skrev Jonas Thörnvall:
    fredag 18 juni 2021 kl. 03:04:02 UTC+2 skrev Andrew Poulos:
    On 18/06/2021 6:21 am, Scott Sauyet wrote:
    Andrew Poulos wrote:
    (response from Ben Bacarisse elided)
    Andrew Poulos wrote:

    I need to trigger up to 12 "events" with timings a user sets. The >>>> timings (in seconds) could be anything from 0 to, say, 300.

    If I have 12 setTimeout waiting to happen and the user gives focus to a >> different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple
    setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd
    rather not have lots of setTimeout running at the same time.

    Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.

    It would be easy enough to run a single `getInterval` timer that when it runs checks the remaining actions and runs all those whose time is at hand.
    You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog
    up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.

    Here's an implementation:

    ```
    const handler = (periodInMilliseconds) => (events) => {
    const start = Date .now ()
    let toProcess = events .map (
    ([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
    )
    const interval = setInterval (
    () => {
    const now = Date .now ()
    toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
    },
    periodInMilliseconds
    )
    return {
    stop: (after = () => {}) => {clearInterval (interval); after ()}
    }
    }
    ```

    which might be used like this:

    ```
    const {stop} = handler (250) ([
    [() => console .log ('A'), 4],
    [() => console .log ('B'), 2],
    [() => console .log ('C'), 15],
    [() => console .log ('D'), 7],
    [() => console .log ('E'), 1],
    ])

    setTimeout (() => stop (() => console.log ('completed')), 10000)
    ```

    You call handler passing the period (250ms) and an array of arrays,
    each containing a function to run and the delay in seconds. You get
    back a `stop` function which will terminate the running (and call
    an optional callback afterward if you like.)

    At the start, the functions are paired with the time they should run.

    At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
    the `toProcess` list.

    The example above would log `E` after one second, `B` after two
    seconds, `A` after four seconds, `D` after seven seconds. But
    because we call `stop` after ten seconds, the events are stopped
    before we reach `C`. Note that our optional callback will log `completed` at that time.

    This is a fairly naive version. We might want to improve it to clear
    the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we might want to specify the `stop` callback initially with the period.
    And many other improvements are certainly possible. But it's a decent start at the problem.
    Thanks. It's given me something I can work with.

    Andrew Poulos
    Here is how i shedule timed events.


    function startIT(){
    playPos=0;
    stopRec=setInterval(doIT,5);
    }

    function doIT(){
    //Play end is set in scrollbar
    REALTIME=performance.now()-browserLoadTIME;
    while(REALTIME>schedTime){
    //Do something
    schedTime=copyEv[playPos]+schedTime;
    playPos++;
    }
    }

    As you can see my timings rest in copyEV and are relative copyEV timings.
    If the copyEV timings are relative zero.....

    Then you of course have some event performed at do something....

    function startIT(){
    playPos=0;
    stopRec=setInterval(doIT,5);
    }

    function doIT(){
    //Play end is set in scrollbar
    REALTIME=performance.now()-browserLoadTIME;
    while(REALTIME>schedTime){
    //Do something
    schedTime=copyEv[playPos];
    playPos++;
    }
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Sun Jun 20 23:40:32 2021
    fredag 18 juni 2021 kl. 03:04:02 UTC+2 skrev Andrew Poulos:
    On 18/06/2021 6:21 am, Scott Sauyet wrote:
    Andrew Poulos wrote:
    (response from Ben Bacarisse elided)
    Andrew Poulos wrote:

    I need to trigger up to 12 "events" with timings a user sets. The
    timings (in seconds) could be anything from 0 to, say, 300.

    If I have 12 setTimeout waiting to happen and the user gives focus to a
    different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple
    setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd >> rather not have lots of setTimeout running at the same time.

    Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.

    It would be easy enough to run a single `getInterval` timer that when it runs checks the remaining actions and runs all those whose time is at hand. You would need to choose a run-time interval short enough to capture the likely timing differences between your events but long enough not to clog up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.

    Here's an implementation:

    ```
    const handler = (periodInMilliseconds) => (events) => {
    const start = Date .now ()
    let toProcess = events .map (
    ([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
    )
    const interval = setInterval (
    () => {
    const now = Date .now ()
    toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
    },
    periodInMilliseconds
    )
    return {
    stop: (after = () => {}) => {clearInterval (interval); after ()}
    }
    }
    ```

    which might be used like this:

    ```
    const {stop} = handler (250) ([
    [() => console .log ('A'), 4],
    [() => console .log ('B'), 2],
    [() => console .log ('C'), 15],
    [() => console .log ('D'), 7],
    [() => console .log ('E'), 1],
    ])

    setTimeout (() => stop (() => console.log ('completed')), 10000)
    ```

    You call handler passing the period (250ms) and an array of arrays,
    each containing a function to run and the delay in seconds. You get
    back a `stop` function which will terminate the running (and call
    an optional callback afterward if you like.)

    At the start, the functions are paired with the time they should run.

    At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
    the `toProcess` list.

    The example above would log `E` after one second, `B` after two
    seconds, `A` after four seconds, `D` after seven seconds. But
    because we call `stop` after ten seconds, the events are stopped
    before we reach `C`. Note that our optional callback will log
    `completed` at that time.

    This is a fairly naive version. We might want to improve it to clear
    the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we
    might want to specify the `stop` callback initially with the period.
    And many other improvements are certainly possible. But it's a decent
    start at the problem.
    Thanks. It's given me something I can work with.

    Andrew Poulos

    Here is how i shedule timed events.


    function startIT(){
    playPos=0;
    stopRec=setInterval(doIT,5);
    }

    function doIT(){
    //Play end is set in scrollbar
    REALTIME=performance.now()-browserLoadTIME;
    while(REALTIME>schedTime){
    //Do something
    schedTime=copyEv[playPos]+schedTime;
    playPos++;
    }
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Wed Jun 23 12:11:53 2021
    måndag 21 juni 2021 kl. 08:48:45 UTC+2 skrev Jonas Thörnvall:
    måndag 21 juni 2021 kl. 08:40:37 UTC+2 skrev Jonas Thörnvall:
    fredag 18 juni 2021 kl. 03:04:02 UTC+2 skrev Andrew Poulos:
    On 18/06/2021 6:21 am, Scott Sauyet wrote:
    Andrew Poulos wrote:
    (response from Ben Bacarisse elided)
    Andrew Poulos wrote:

    I need to trigger up to 12 "events" with timings a user sets. The >>>> timings (in seconds) could be anything from 0 to, say, 300.

    If I have 12 setTimeout waiting to happen and the user gives focus to a
    different "component" I'll need to clear all the setTimeout. I was
    looking for a single point to control all of them without multiple
    setTimeout.

    At some later stage the client might ask for "unlimited" timings and I'd
    rather not have lots of setTimeout running at the same time.

    Dozens, hundreds, probably even thousands of `setTimeout` calls will probably not slow down modern browsers. But it would feel ... uncleanly.

    It would be easy enough to run a single `getInterval` timer that when it
    runs checks the remaining actions and runs all those whose time is at hand.
    You would need to choose a run-time interval short enough to capture the
    likely timing differences between your events but long enough not to clog
    up the event queue. For events measured in seconds, up to 300, I would think running every 250 milliseconds might be reasonable.

    Here's an implementation:

    ```
    const handler = (periodInMilliseconds) => (events) => {
    const start = Date .now ()
    let toProcess = events .map (
    ([fn, delayInSecs]) => ({fn, runTime: start + 1000 * delayInSecs})
    )
    const interval = setInterval (
    () => {
    const now = Date .now ()
    toProcess .filter (e => e .runTime <= now) .forEach (e => e .fn ()) toProcess = toProcess .filter (e => e .runTime > now)
    },
    periodInMilliseconds
    )
    return {
    stop: (after = () => {}) => {clearInterval (interval); after ()}
    }
    }
    ```

    which might be used like this:

    ```
    const {stop} = handler (250) ([
    [() => console .log ('A'), 4],
    [() => console .log ('B'), 2],
    [() => console .log ('C'), 15],
    [() => console .log ('D'), 7],
    [() => console .log ('E'), 1],
    ])

    setTimeout (() => stop (() => console.log ('completed')), 10000)
    ```

    You call handler passing the period (250ms) and an array of arrays, each containing a function to run and the delay in seconds. You get back a `stop` function which will terminate the running (and call
    an optional callback afterward if you like.)

    At the start, the functions are paired with the time they should run.

    At each interval, we calculate the current time and, if checks each function. If it is now due, we run the function and remove it from
    the `toProcess` list.

    The example above would log `E` after one second, `B` after two seconds, `A` after four seconds, `D` after seven seconds. But
    because we call `stop` after ten seconds, the events are stopped before we reach `C`. Note that our optional callback will log `completed` at that time.

    This is a fairly naive version. We might want to improve it to clear the interval when the queue is empty. We might want to add an explicit `start` parallel to `stop`, to start the queue when we choose. Or we might want to specify the `stop` callback initially with the period. And many other improvements are certainly possible. But it's a decent start at the problem.
    Thanks. It's given me something I can work with.

    Andrew Poulos
    Here is how i shedule timed events.


    function startIT(){
    playPos=0;
    stopRec=setInterval(doIT,5);
    }

    function doIT(){
    //Play end is set in scrollbar
    REALTIME=performance.now()-browserLoadTIME;
    while(REALTIME>schedTime){
    //Do something
    schedTime=copyEv[playPos]+schedTime;
    playPos++;
    }
    }
    As you can see my timings rest in copyEV and are relative copyEV timings.
    If the copyEV timings are relative zero.....

    Then you of course have some event performed at do something....
    function startIT(){
    playPos=0;
    stopRec=setInterval(doIT,5);
    }

    function doIT(){
    //Play end is set in scrollbar
    REALTIME=performance.now()-browserLoadTIME;
    while(REALTIME>schedTime){
    //Do something
    schedTime=copyEv[playPos];
    playPos++;
    }
    }
    Well you should init with.
    REALTIME=performance.now()-browserLoadTIME;
    shedTime=copyEv[0]
    And end with
    if(copyEv[copyEv.length]<REALTIME){clearInterval (stopRec); }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)