Check if agent connected to an agent is on the wait block - anylogic - simulation

Direct question: how to check if an agent is waiting in the wait block?
More details? below, thank you.
I was following Mr. Felipe's answer to a similar question (this one: Anylogic - Combined multiple items back to original owner )
On step number 4 of his answer, he said " On the passengerWait, on the onEnter action you will check if all the bags connected to the passenger are on the bagWait block... if they are... then you will free (wait.free(agent)) the passenger and the bags "
Do you know how to check this? I have the same problem between single patient and single drug.

To avoid going into the details of your model and naming of blocks, I will provide you with something generic that should help you achieve what you need.
The first step is to know how to iterate through the agents inside the wait block. To do that, you need a for loop with the syntax shown in the code below. (Replace Agent with the agent type of agents in the wait block, replace waitBlock with you wait block's name.)
The character a now refers to the agent in the wait block being evaluated in each iteration.
Now, you just add your condition where you check if any of the agents in the wait block match your condition which is whether they are equal to whichever connected agent to the one going through the wait block.
Agent x = null;
for( Agent a : waitBlock ) {
if( a.equals(agent.agentLink.getConnectedAgent()) ) {
x = a ;
break;
}
}
if( x != null ) {
waitBlock.free( x );
}
Another simplified code would be:
Agent x = findFirst( waitBlock , a -> a.equals(agent.agentLink.getConnectedAgent()) );
if( x != null ) {
waitBlock.free(x);
}

I figured out how to do that:
Make a new variable in the Passenger agent and call it
variable_IsWaitingForBag
Make a new variable in the Bag agent and call it variable_IsWaitingForPassenger
In onEnter of passengerWait, use the following:
if(agent.agentLink_myBag.getConnectedAgent().variable_IsWaitingForPassenger)
{
passengerWait.free(agent);
bagWait.free(agent.agentLink_myPassenger.getConnectedAgent());
}
agent.variable_IsWaitingForBag=true;
Do the opposite in onEnter of the bagWait block

Related

agent cannot be resolved to a variable in function body but works in other blocks

I currently have a function that gets checked at certain time intervals. I want a hold to unblock upon satisfaction of the condition in the function body. However, agent can never be resolved to a variable, even though this convention of referring to the agent works in other process blocks. The agent that is present in the (((Patient)agent) is the agent that cannot be resolved to a variable. Patient is an agent type and has the variable isMorning that gets set to true or false upstream in the model. Below is the code in the function block, and the parameters are set to Just action (returns nothing). The (((Patient)agent) would be in a queue block prior to the hold.
if (((Patient)agent).isMorning == true && SurgeonMorning.idle() > 0){
hold.unblock();}
else if (((Patient)agent).isMorning == false && SurgeonAfternoon.idle() == 0){
hold.unblock();}
If this is code in a function, you need to provide a function argument and use that instead of agent.
In the properties of the function under arguments, add an entry myPatient and specify the type as Patient (right side from the dropdown).
Then, you can use the code as
if (myPatient.isMorning == true && SurgeonMorning.idle() > 0){
hold.unblock();}
else if (myPatient.isMorning == false && SurgeonAfternoon.idle() == 0){
hold.unblock();}
Check the help to understand functions more. And this article to understand when (and when not) you can use these little keywords like agent: https://www.benjamin-schumann.com/blog/2016/2/4/the-magic-lightbulb-and-how-it-can-help-your-anylogic-modelling

RuntimeException: Cannot put: [0][0][0] is occupied in Anylogic

I have RackStore block to store agents where the cells are chosen explicitly with the help of a function. I am getting this error when I run the simulation. Here,cells were assigned to all four agents that entered the block, but I think it throws this error when resources arrive for an agent.
I can't understand the reason for this error as all the agents that entered the block were already assigned to cells and it's not trying to put anything again. I have tried the simulation with various no. of agents (5-150 agents), the error always appears after all the agents arrive at rackStore block and an agent is trying to exit.
My rackStore properties are: rackStore property_part_1, rackStore property_part_2
The getCell(double weight, Carrier carrier) function is defined below. It returns an integer array of size 3.
//Iterate through rows
int lev=0;
int row=0;
for (int r=0; r<=1; ++r) {
// Iterate through positions
for(int p=0; p<=9; ++p){
//Check which level it belongs to as per weight
lev=getLevel(weight);
//Check if cell is free
if(carrier==Truck){
if (palletRack4.isFree(r,p,lev)== true ){
int[] arr={r,p,lev};
//traceln("truck pos: "+ arr);
if(arr==null){traceln("truckPos NULL");}
return arr; }
else {continue;}}
else{
if (palletRack5.isFree(r,p,lev)== true ){
int[] arr={r,p,lev};
//traceln("train pos: "+ arr);
if(arr==null){traceln("trainPos NULL");}
return arr; }
else {continue;}}
}
}
if(carrier==Truck){
PalletRackLocation ploc=palletRack4.getFreeCell(true);
//traceln("Carrier: " + carrier);
//traceln("Free cell from P4: "+ ploc);
int[] arr1={ploc.row,ploc.position,ploc.level};
if(arr1==null){traceln("randTruckPos NULL");}
return arr1;}
else{
PalletRackLocation ploc=palletRack5.getFreeCell(true);
//traceln("Carrier: " + carrier);
//traceln("Free cell from P5: "+ ploc);
int[] arr1={ploc.row,ploc.position,ploc.level};
if(arr1==null){traceln("randTrainPos NULL");}
return arr1;}
You're not setting up your RackStore block properly. As the properties state, you have to specify expressions for the row, position and level when you choose "The cell is specified explicitly". But you are trying to use 'internal' pallet rack put functions to do this (inside your "on enter" actions for the block) and leaving those expressions blank. So likely the blank settings means it tries to add agents to location (0,0,0) after having already added them somewhere else (and thus subsequent agents will try to get added there giving you the error shown).
If the block's "on enter" actions occur before those row, position and level expressions are evaluated (do some traceln statements to check; I imagine they are but this is really an internal block sequencing detail that can't be explicitly 'knowable' a priori) you can then keep your on-enter code as-is (but remove the put calls) and then specify the row, position and level from the agent parameters you just set up.
(P.S. The error trace shows that the error is in the rack storage stage—it's occurring inside the onEnter method of the RackStore block—not when an agent tries to leave the rack. It's probable at a Java level that the block performs the user-specified on-enter action code and then the cell allocation and pallet rack 'put' inside the onEnter method that the error trace shows— presumably in that order, but you should check that as mentioned.)

I am thinking of easy account security Developers

If there is "FreezeToken" in the wallet, freeze the wallet.
And if there is "ThawToken" in the wallet, it cancels the freeze.
This code is an example of failure.
let FreezeToken = base58'GwmXnsF3Z5tANgHwmDW7Lf4SwyYNEp4S3QZM3aBFLHwS'
let ThawToken = base58'GK7ZV8xFbh1Qz14Cnr6mLkV93svaZGrurVuaBZocwLZZ'
match tx {
case m : ExchangeTransaction. =>
if (assetBalance(e.sender,ThawToken) >= 1 ) then{true}
else if (assetBalance(e.sender,ThawToken) >= 1 ) then{false}
else true
case _ => false
}
TransferTransaction succeeded but ExchangeTransaction failed.
How do I change this code? please tell me.
I am guessing you are creating a smart account?
From what I see in the code, is that you used 2 times ThawToken, one time this results to true and another time to false. My guess is that you want one from the 2 be replaced by FreezeToken
Also in your example you have "ExchangeTransaction.", this dot doesn't seem needed here from what I can understand from your code.
Also according to the examples it seems that your whole second if structure should be included into {}. Example: https://github.com/wavesplatform/ride-examples/blob/bc8db2342f53fe1554a10dc5aaa211b1542a5ca1/smart-assets/HotPotatoToken.ride#L41
However I think this issue could be solved with a && statement, and as following the second if-then-else is not needed anymore.
What I propose is a check that does following:
Check if ThawToken not in wallet and if that is the case, check if freezetoken is in wallet.
If ThawToken is and FreezeToken is also => wallet free since ThawToken frees it.
If ThawToken is not and FreezeToken is 1 or more => wallet locked since only FreezeToken.
If ThawToken is not and FreezeToken is not => wallet free since no FreezeToken
if (assetBalance(e.sender,ThawToken) == 0 &&
assetBalance(e.sender,FreezeToken) >= 1 ) then{
false
}else{
true
}
Also to block all transactions and indeed freeze the wallet, you would need to filter on another type, for all types use: Transaction, be careful this also disables the option to change the script in case you locked your account.
To block transfer transaction use: TransferTransaction.
All types can be found here:
https://docs.wavesplatform.com/en/smart-contracts/ride-language/standard-library.html

CQ Workflow- Comment not transferring between participant with a process step in between

When there is a process step between two participant steps, the comments is not passing between participants. My Workflow is like this-
ParticipantA ---> Process step X (ecma script) ----> Process step Y (ecma script) -----> ParticipantB
When I add some comment at ParticipantA step it does not carry forward to ParticipantB. Seems OOB functionality has limitations on this.
As a workaround, I am trying to get it at "Process step X" and passing on to Process step Y. I am able to get it but not able to set it for next step.
Below is my code-
log.info("Noop process called for: " + workItem.getWorkflowData().getPayload());
var comment = workItem.getMetaDataMap().get("comment");
log.info("Comment in approval process-----------" + comment);
var workflowData = workItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") {
log.info("setting comment in meta data----------------");
workflowData.getMetaDataMap().put("comment", comment);
}
Can you help on how to set comment for next step?
Thanks in advance.
Regards,
Vivek
You would need to actually store your comment within a workflow Metadata Map. This
should help.
Once you have successfully stored your comment, you can access it later.
Hope this helps
I guess it is a session change within the workflow. The WorkflowData instance will be newly set. You can easily check it in the debugger of your ide. You have to iterate over the HistoryItems as illustrated here:
final List<HistoryItem> history = workflowSession.getHistory(workItem.getWorkflow());
final List<String> comments = new ArrayList<>();
if (history.size() > 0) {
HistoryItem current = history.get(history.size() - 1);
do {
comments.add(current.getComment());
current = current.getPreviousHistoryItem();
} while (current != null);
}
Comments are empty strings, if not set - if i'm not mistaken.

Tasks behaving incorrectly in round-robin schedule

I have FreeRTOS running on a STM32F4DISCOVERY board, and I have this code:
xTaskCreate( vTask1, "Task 1", 200, NULL, 1, NULL );
xTaskCreate( vTask2, "Task 2", 200, NULL, 1, NULL );
vTaskStartScheduler();
where vTask1 is this function:
void vTask1( void *pvParameters )
{
volatile unsigned long ul;
for( ;; )
{
LED_On(0);
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
}
LED_On(2);
LED_Off(0);
}
}
vTask2 has nearly the same code:
void vTask2( void *pvParameters )
{
const char *pcTaskName = "Task 2 is running\n";
volatile unsigned long ul;
for( ;; )
{
LED_On(3);
LED_Off(2);
for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
{
}
LED_Off(3);
}
}
When I run the program, I see that LED0 and LED3 are always on (their switching is too fast for my eye, which is fine), and that LED2, the "shared resource", is blinking very fast.
The problem is this: when I reverse the order of the xTaskCreate calls, I get the same situation with a different blinking behavior of LED2, which is much slower.
Why would this happen, since the tasks should have equal priority and therefore follow a round-robin schedule? Shouldn't they get the same amount of time? Why is their behavior changing after only having created them in different order?
Thanks in advance.
The rtos does not try to round robin through the tasks and you should not expect them to execute in any specific order. Neither of the tasks you have created have a delay in them as iama pointed out in their comment. instead of creating a delay by burning through no-ops in a for loop, use the delay function. this will allow the code in your while(1) loop to execute then yield back to the rtos so that the processor can run other tasks until the wait time has elapsed. If you need to synchronize work you may want to just keep it in a single task. If you have one task that is dependent on something done in another, you may want to use semaphores, queues, or other cross thread communication method.
Your code reminds me of when I was transitioning from using a while(1) loop in main to an rtos. If your new to using an rtos, this guide from ST looks like it would be a good introduction https://www.st.com/resource/en/user_manual/dm00105262-developing-applications-on-stm32cube-with-rtos-stmicroelectronics.pdf
Also, do not rely on the delay function for fine grain timing; use a timer driven interrupt instead. The link above should give you a better understanding of why then I could manage in this post.
ST should also have example projects somewhere, which would be good to reference or use as a start for your own project.