Question

All topics on coding 4Dscript in Enterprise Dynamics.
Post Reply
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Question

Post by enterprisedynamics »

Hello,

I'm trying to model a situation where a certain server receives products from two different queues. Whenever the server receives a product from the first queue, this product will have a label named Match with a certain value. Furthermore, there will be a product in the second queue (i.e. in(2,c)) that has a label named 'Match' with the same value. So both products will have a label named 'Match' with value 21 for example. Now I want to enter code in the trigger on entry field of the server (so this is the current atom c) which scans through the second queue until it finds the product which has the same value for the label Match as the product it is currently about to serve. When it has found this product in the second queue, it will check whether another label of this product named 'Finished' has the value 0 or 1. Depending on this value, it will give the product that the server is about to serve a label named 'Type' a value of 2 or 3, which will be used to determine the service time of this product. Furthermore, the product in the second queue which had the same value for the label 'Match' as the product about to be served has to be moved to a Sink. It can also be that the product with the same value for 'Match' as the product about to be served is being served by a Server2, then this product has to be removed from Server2. I came up with the following code:

Do(

var([x],vbAtom,First(In(2,c)))
,

If(Label([Match],First(c))=Label([Match],First(AtomByName([Server2]))),
Do(
MoveAtom(First(AtomByName([Server2])),First(In(2,c))),
OpenAllIc(AtomByName([Server2]))
)
)
,

While(
Label([Match],First(c))<>Label([Match],x),
x:=prev(x))
,

If(Label([Finished],x)=1,
Do(Label([Type],First(c)):=2, MoveAtom(x,AtomByName([Sink3]))),
Do(Label([Type],First(c)):=3, MoveAtom(x,AtomByName([Sink3]))))

)

Since I'm quite new to 4d script, I was wondering whether this code achieves what I want it to. I hope I explained the situation clearly enough.
marlies
Posts: 301
Joined: Monday 17 January, 2011 - 09:28

Re: Question

Post by marlies »

Hi,

I think that most of your code is ok, but you'll need a few changes:
- using openallic for the server2 is not necessary, it will be done by the server automatically when you move the product out.
- however you need to destroy the server events that have been prepared for the product.
- the search with the while loop should not be executed when you found the product in the server, therefore I placed it within the if statement.
- when you want to move from the first product in the queue to the next one, you should use next and not prev.

Code: Select all

Do( 
 var([x],vbAtom,First(In(2,c))),

 If(
  Label([Match],First(c))=Label([Match],First(AtomByName([Server2]))),
  Do(
   DestroyEventsOfAtom(AtomByName([Server2])),
   MoveAtom(First(AtomByName([Server2])),First(In(2,c))){,
   OpenAllIc(AtomByName([Server2]))}
  ),
  Do(
   { execute this code only when the matching product wasn't found in the server
     therefore placed within the if statement. }
   While(
    Label([Match],First(c)) <> Label([Match],x),
    x:=next(x)
    {x:=prev(x)}
   ),
  
   If(
    Label([Finished],x) = 1,
    Do(Label([Type],First(c)):=2, MoveAtom(x,AtomByName([Sink3]))),
    Do(Label([Type],First(c)):=3, MoveAtom(x,AtomByName([Sink3])))
   ) 
  )
 )
)
regards, Marlies
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Re: Question

Post by enterprisedynamics »

Thank you so much!
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Re: Question

Post by enterprisedynamics »

Hello again,

I've updated this code to make it suitable for my model, this is what I got:

Code: Select all

If(
 Label([Type], i) = 1,
 Do( 
  var([x],vbAtom,First(In(2,c))),

  If(
   Label([Match],First(c))=Label([Match],First(AtomByName([DoordeweeksPreAlerts]))),
   Do(
    DestroyEventsOfAtom(AtomByName([DoordeweeksPreAlerts])),
    MoveAtom(First(AtomByName([DoordeweeksPreAlerts])),Out(2,c)),
    Label([Type],First(c)):=4
   ),
   If(
    Label([Match],First(c))=Label([Match],First(AtomByName([Weekend]))),
    Do(
     DestroyEventsOfAtom(AtomByName([Weekend])),
     MoveAtom(First(AtomByName([Weekend])),Out(2,c)),
     Label([Type],First(c)):=4
    ),
 
    Do(
     While(
      Label([Match],First(c)) <> Label([Match],x),
      x:=next(x)
     ),
     If(
      Label([Finished],x) = 1,
      Do(Label([Type],First(c)):=3, MoveAtom(x,Out(2,c))),
      Do(Label([Type],First(c)):=4, MoveAtom(x,Out(2,c)))
     )
    )
   )
  )
 )
)
However, when I run my simulation using this, I'm getting an endless stream of error messages. I believe it's these two over and over again:

115 Called 'First' on invalid atom
116 Time: 145458.717879015 Atom: DoordeweeksInspecties (ID=129), OnEntered>No atom currently selected: First()

Do you have any idea what is causing this?
marlies
Posts: 301
Joined: Monday 17 January, 2011 - 09:28

Re: Question

Post by marlies »

Hi,

The error says that you refer to an atom that does not exist. In that case you refer to a first() in some atom, but it's not there. Most likely you refer to an atom that is empty.

You'll have to check your model:
- Maybe the content of (in(2,c)) is 0 at the time this trigger is executed?
- Or the content of the atom doordeweeksprealerts is 0?

A solution could be to chek the content of an atom before using the command first(), for example like this:

Code: Select all

If(
 And(
    content(atombyname([doordeweeksprealerts], model)) > 0,
    Label([Match],First(c))=Label([Match],First(AtomByName([DoordeweeksPreAlerts])))
 ),Do(
  { your code }
 )
)


Regards, Marlies
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Re: Question

Post by enterprisedynamics »

Hello again,

I think this is working, I also avoided the use of AtomByName which seemed to help. I now however have another problem. I've attached my model to explain this better. The code as I am using it can also be found in the 'on entry' fields of the servers.

Products that arrive at a server from the second queue get a label to indicate that they are finished and then they have to be sent back to the queue they came from. This way, when a product from the first queue arrives, a product with a label named match with the same value as the product from the first queue will be in the second queue. I've tried to accomplish this by using an if statement in the 'send to' field of the servers, but when I try to run the model it gets stuck. Is there a way around this?
marlies
Posts: 301
Joined: Monday 17 January, 2011 - 09:28

Re: Question

Post by marlies »

Hi,

The code in your sendto statement is ok. I think that the problem is the fact that you send it back into the same queue it came from and this queue will immediately send the product to the server again. So, a product keeps looping through the queue-server-queue-server etc.

I assume that you want to keep the products in the queue once they've got the label finished. You could solve this in different ways:
- Send the finished pre alerts to a different queue (with no output channels) for finished pre alerst. When the matching product arrives, you'll have to search in that queue.
- You could also choose to change the sendto statement of the prealerts buffer: when the label finished equals 1, send the product to channel 0 (as a result it will stay in the queue). You should also change the queue discipline of the queue prealerts: the products having label finished = 0, should be put in front (otherwise they will get blocked by the finished products).

See attached for a slightly changed model.

Good that you removed the atombyname references, this is slow code and often leads to errors. To make the code better readable it would be a good idea to make more use of variables. Something like a variable [atmInspectiesKlaar] instead of out(2,c), the same as you already did with x as the first product.

Regards, Marlies
Attachments
2000prealert_edit.mod
(47.18 KiB) Downloaded 299 times
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Re: Question

Post by enterprisedynamics »

Thank you for your suggestions! I still have a few problems unfortunately. When I run your edited model one of two possible things happens:

- I get the same error as before (I think, the errors pile up really fast and ED crashes). I believe that I'm checking the content of every atom before I start using First() on these atoms.

- The model runs okay, but no products enter the second sink. Atoms should be entering this sink, because I'm using the MoveAtom command in the On Entry fields of the servers.

Do you have any ideas what's causing this? Sorry if I'm asking too much, but I'm really at a loss here..
marlies
Posts: 301
Joined: Monday 17 January, 2011 - 09:28

Re: Question

Post by marlies »

Hi,

I think that you should change your if statements. For example this part:

Code: Select all

If(
   content(In(3,c)) > 0,
   If(   
    Label([Match],First(c))=Label([Match],First(In(3,c))),
    Do(
     DestroyEventsOfAtom(In(3,c)),
     MoveAtom(First(In(3,c)),Out(2,c)),
     Label([Type],First(c)):=4
    ) 
   ),
  { else check in(4,c) etc.}
)
Will result in nothing when the content of in(3,c) > 0, but the label match is not ok. You should change this in someting like:

Code: Select all

If(
   And(
    content(In(3,c)) > 0,
    Label([Match],First(c))=Label([Match],First(In(3,c)))
   ),
   Do(
     DestroyEventsOfAtom(In(3,c)),
     MoveAtom(First(In(3,c)),Out(2,c)),
     Label([Type],First(c)):=4
   ),
 { else search in other atom })
For debugging of your code I would advice the following:
- Create only 1 or a small number of products to see and check exactly what's happening in your model.
- You can debug and step through your code by adding the command Enterdebugger(1) at a relevant location in the code.
- You could use the command Trace([some text..]) in your code to see if the model really executes the part of code you expect. Open up the tracer window to see the result (menu window > tracer).

Regards, Marlies
enterprisedynamics
Posts: 14
Joined: Tuesday 29 March, 2011 - 09:12

Re: Question

Post by enterprisedynamics »

Thank you! I believe it's working now.
Post Reply