Does flatMapMerge cache flows? - function

I wonder how flatMapMerge works in this code:
fun requestFlow(i: Int): Flow<String> = flow {
emit("$i: First")
delay(500) // wait 500 ms
emit("$i: Second")
}
fun main() = runBlocking<Unit> {
val startTime = System.currentTimeMillis() // remember the start time
(1..3).asFlow().onEach { delay(100) } // a number every 100 ms
.flatMapMerge { requestFlow(it) }
.collect { value -> // collect and print
println("$value at ${System.currentTimeMillis() - startTime} ms from start")
}
}
1: First at 136 ms from start
2: First at 231 ms from start
3: First at 333 ms from start
1: Second at 639 ms from start
2: Second at 732 ms from start
3: Second at 833 ms from start
After requestFlow sleeps for 500 ms, it continues with emit("$i: **Second**"). Looking at the output, I am confused. My questions are
Has flatMapMerge invoked asFlow on (1..3) again. Or
Does it cache the flow of 1..3 somewhere for later use because requestFlow has told it, ' I'm not done yet'

The entire sequence is like this:
1 is emitted from original flow and passed to requestFlow which creates a new flow builder which prints "1: First at..." and then suspends for 500ms.
2 is emitted from original flow and passed to requestFlow which creates a new flow builder which prints "2: First at..." and then suspends for 500ms. (here we have two suspended functions in memory).
3 is emitted from original flow and passed to requestFlow which creates a new flow builder which prints "3: First at..." and then suspends for 500ms. (here we have three suspended functions in memory).
After 500ms from 1st emission, the first suspended function resumes and prints "1: Second at ..."
After 100ms, the second function resumes and prints "2: Second at ..."
After another 100ms, the last suspended function resumes and prints "3: Second at ..."
flatternMapMerge just applies the transformation you provide and returns a Flow<String>. Note that this is not a suspend function and so returns immediately.
Answering your two questions,
No, the asFlow function is not invoked again.
It's not caching the flow, just suspending the functions for 500ms, doing other stuff till then, and resuming from where it left off after the delay is over.

Related

how du model setuptime for diffrent agent in service block

i have used a service block for my machine. i want to implement my setup time in it. So the setup time and the processing time will be a common time.
I would like to write a function for my delay time in the service block. How can I write the function that it gives me the following output:
If the predecessor is agent A and then agent B comes then XX delay time.
If the predecessor is agent A and then agent C comes then XX delay time.... and so on.
You need to store the predecessor somewhere and use it accordingly:
create a variable v_Predecessor next to the Service block, type should be your agent type flowing through the blocks (say MyAgent)
create a function f_getDuration that takes 2 arguments of type MyAgent: first is currentAgent and 2nd is predecessor. Function returns a double.
Call this function in your service block delay code section using f_getDuration(agent, v_Predecessor)
In the on-exit code block of the service block, update v_Predecessor = agent;
The code in f_getDuration will look something like:
if (currentAgent.myType == "A" && predecessor.myType == "B") {
return 12.;
} else if (currentAgent.myType == "A" && predecessor.myType == "C") {
return 13.;
} else if ... // add your logic

A function I created can only be called once, second time it shows an error

I created a function to draw a bargraph with turtle. The first call works fine but fails when calling it for the second time:
"File "C:\Users\NTC\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 1292, in _incrementudc raise Terminator turtle.Terminator"
only thing i tried is using t.terminator at the end, same results
def bar_chart():
t = turtle.Turtle()
screen = turtle.Screen()
##snip # lines detailing the lines drawing
for value in range(1,11): # the upper limit has to be more thanhighest value in the "count"
t.forward(20)
t.write((" " + str(value)), align="left",font=("Arial", 8, "normal"))
screen.exitonclick()
just expect it to be called multiple times in a looped program.
The screen.exitonclick() function has no business being in a function that you plan to call multiple times. It's logically the last thing you do in your program. You also shouldn't keep allocating turtles to do the same thing, allocate one and reuse it. Something like:
from turtle import Screen, Turtle
def bar_chart(t):
for value in range(1, 11): # the upper limit has to be more than highest value in the "count"
t.forward(20)
t.write((" " + str(value)), align="left", font=("Arial", 8, "normal"))
screen = Screen()
turtle = Turtle()
bar_chart(turtle)
screen.exitonclick()

Jooq batchInsert().execute()

My process looks like:
select some data 50 rows per select,
do sth with data (set some values)
transform row to object of another table
call batchInsert(myListOfRecords).execute()
My problem is how to set up when data should be inserted ? In my current setup data is only inserted at the end of my loop. This is some kind of problem for me because i want process much more data then i do in my tests. So if i will agree with this then my proccess will end with exception (OutOfMemory). Where i should define max amount of data in batch to call instert?
The important thing here is to not fetch all the rows you want to process into memory in one go. When using jOOQ, this is done using ResultQuery.fetchLazy() (possibly along with ResultQuery.fetchSize(int)). You can then fetch the next 50 rows using Cursor.fetchNext(50) and proceed with your insertion as follows:
try (Cursor<?> cursor = ctx
.select(...)
.from(...)
.fetchSize(50)
.fetchLazy()) {
Result<?> batch;
for (;;) {
batch = cursor.fetchNext(50);
if (batch.isEmpty())
break;
// Do your stuff here
// Do your insertion here
ctx.batchInsert(...);
}
}

Aurelia repeat.for calling function multiple times

In an attempt to discover some performance issues we are running into with Aurelia on IE 11, I tried to just log a timer in order to track progress made. While doing so, I noticed odd behavior during a repeat.for iteration.
<div repeat.for="i of 100">
<div if.bind="lastElement(item, $last)">${$index}</div>
</div>
with the function and scope
var count = 0;
lastElement(item, last){
count++;
if(last === true){
console.log('Last Item: ' + JSON.stringify(item));
console.log(count);
};
return true;
};
...and with the following result:
Last Item: 99
100
Last Item: 99
169
To me the result should have been:
Last Item: 99
100
For some reason there is multiple iterations or checking on this function. Can somebody explain to me what is going on here?
UPDATE: I was able to find a external file by jdanyho and create a Gist to demonstrate. However, now I'm getting 150 instead of 169. Hmmmm...
The function lastElement its call more times that the number of itens, because you do a bind with function, and in this case aurelia binding system do a dirty checking (has a timer to call the function to see if the value has changed).
To avoid dirty checking you can using the decorator #computedFrom.
In this case for using decorator i think that you cannot performing your function logic based in parameter last, must be doing based in properties.
There are many blog about this topic, but you can read the official post:
http://blog.aurelia.io/2015/04/03/aurelia-adaptive-binding/

How to wait, then do something, in the GameScene

SKAction has waiting for duration abilities, for a period of time on a node. And seems to perform actions on nodes. Like moveTo, etc.
If I don't want that, rather I'd prefer to call functions within GameScene after a period of time, how do I do that with SpriteKit in the GameScene, not on a Sprite or other Node?
Are SKActions the way to do this? The only way to do this?
Yes. This question IS that ridiculously simple. I lack the heuristics and terminology to find an answer. Just keep looping around on how SKAction waits are calls on SKSprites for things like scale, rotation, etc, after time. Which isn't want I want/need.
Update:
Desired outcome, inside GameScene
doSetupStuff() // does some stuff...
waitForAWhile() // somehow wait, perhaps do somethings in here, while waiting
doSomethingElse() // does this after the waitForAWhile has waited
UPDATE 2:
What I think happens, again, inside didMove(to view...)
func wait(){
let timeToPause = SKAction.wait(forDuration: 3)
run(timeToPause)
}
let wontwait = SKAction.wait(forDuration: 3)
run(wontwait)
thisFunction(willnot: WAIT"it starts immediately")
wait()
thisFunction(forcedToWait: "for wait()'s nested action to complete")
UPDATE 3:
Found a way to get the delay without using SKActions. It's a little crude and brutal, but makes more sense to me than SKActions, so far:
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
print("I waited ten seconds before printing this!")
}
An option, as you cited, is to manage this externally. The way I typically manage this sort of thing is to have an externally run update cycle. One that
To drive this updater, you could use either CADisplayLink (which is what I use right now with my OpenGL renderer) or a dispatch source timer (which I have used with my SpriteKit engine). When you use an updated, you want to calculate the delta time. The tick handler could look something like:
func tickHandler() {
let currTime = NSDate().timeIntervalSince1970
let dt = lastTime - currTime // lastTime is a data member of the class
// Call all updaters here, pretend "updater" is a known updater class
updater.update(dt)
}
And updater's update method would look something like:
func update(deltaTime:NSTimeInterval) {
// Do your magic
}
I typically have a main overall updater running independent of what people are calling scenes. Example usage would be something like having an attract mode like in old school arcade games. There they show title screen, sample game play, high scores, rinse and repeat. Scenes would be title, game play, high score. Here you can your main updater manage the time and coordinate the construction/destruction/switching of the scenes. Note this implies having an overall scene manager (which is actually quite handy to have).
For your case, you could use this updater to drive the GameScene updater. It's updater could look something like:
func update(deltaTime:NSTimeInterval) {
switch state {
case .SetupState:
// noop?
println("I'm in setup") // Shown just so you can see there is a setup state
case .WaitState:
waitTime += deltaTime
if waitTime >= kWaitTime {
// Do whats you gots to do
doSomethingElse()
state = .NextState
}
case .NextState:
// blah blah blah blah
}
}
So the flow to do this call path from your driver (CADisplayLink or dispatch source) would be something like:
tickHandler -> master updater -> game scene updater
Some will def find this is perhaps a little heavy handed. I, on the other hand, find this very helpful. While there is obviously some time management and the loss of being able to fire and forget, it can help provide more control for orchestrating pieces, as well as arbitrarily changing state without having to worry about killing already queued actions. There is also nothing that says you still cannot mix SKAction. When I did use SpriteKit, I did all my updating this way along with some dispatched items. I only used SKAction to update hierarchy. Keep in mind that I used my own animation and physics system. So at least for me I had a lot less dependency on SpriteKit (it effectively was just a renderer for me).
Note you have to have your own means to handle pause and coming to foreground where your timer will need to be resynced (you only need to worry about tickHandler). Breakpoints also will cause time jumps.
You can use below function
#define ANIM_TIME 2
SKAction *customACtion = [SKAction customActionWithDuration: ANIM_TIME actionBlock:^(SKNode *node, CGFloat elapsedTime) {
// Do Something Here
}];
Another way to make something happen after a certain period of time is to make use of the 'current time' parm passed to update(). The following code will spawn a boss at intervals ranging from 20 to 30 seconds.
In your property definitions:
var timeOfLastBoss: CFTimeInterval = -1 //Indicate no boss yet
var timePerBoss = CFTimeInterval()
.
.
.
didMoveToView() {
...
timePerBoss = CFTimeInterval(Int.random(20...30))
'''
}
.
.
.
func update(currentTime: CFTimeInterval) {
...
spawnBossForUpdate(currentTime)
...
}
'
'
'
func spawnBossForUpdate(currentTime : CFTimeInterval) {
if ( timeOfLastBoss == -1 ) {timeOfLastBoss = currentTime}
if (currentTime - timeOfLastBoss < timePerBoss) {return}
// Rest of 'spawnBoss code
self.timePerBoss = CFTimeInterval(Int.random(20...30))
self.timeOfLastBoss = currentTime
}
One way, using SKActions, in Swift 3.0, looks like this:
DEFINE: aPatientlyWaitingFunction() at the top level of
GameScene class.
To cause a delay to happen before calling the above function, inside
didMove(to view...)
three ways I've found to do this using Actions:
All three ways seem to accomplish the exact same thing:
let timeToWait: TimeInterval = 3 // is seconds in SKAction thinking time
let waitSomeTime = SKAction.wait(forDuration: timeToWait)
// 1st way __________________________________________
// with a completion handler, the function can be called after Action
run(waitSomeTime) {self.aPatientlyWaitingFunction()}
// 2nd way __________________________________________
// as a completion to be done after action, in the run invocation:
run(waitSomeTime, completion: aPatientlyWaitingFunction)
// 3rd way __________________________________________
// alternatively, as part of a sequence of actions...
// Create a sequence, by making a run action from waitSomeTime and...
let thenDoThis = SKAction.run(aPatientlyWaitingFunction)
// then activate sequence, which does one action, then the next
run(SKAction.sequence([waitSomeTime, thenDoThis]))
// OR... for something different ____________________
////////////////////////////////////////////////////////
DispatchQueue.main.asyncAfter(deadline: .now() + timeToWait) {
self.aPatientlyWaitingFunction()
print("DispatchQueue waited for 3 seconds")
}