ATTENTIONThis FlexSim Community Forum is read-only. Please post any new questions, ideas, or discussions to our new community (we call it Answers) at https://answers.flexsim.com/. Our new Question & Answer site brings a modern, mobile-friendly interface and more focus on getting answers quickly. There are a few differences between how our new Q&A community works vs. a classic, threaded-conversation-style forum like the one below, so be sure to read our Answers Best Practices. |
flexsim.com |
#1
|
|||
|
|||
Edit Value of Variable in Flexscript Node
I'm trying to find out how to set the value of variables that are contained in Flexscript nodes in the tree. I found that the variable contained in the text of the Flexscript appears as a node under the Flexscript node and the value of the variable appears as a node in the 2nd rank below the variable's node. The variable node looks like a normal attribute/variable but has the letter K over the yellow circle. I wrote some code that would find the variable based on its node's name and then replace the value of the variable (in the 2nd rank) with setnodenum(). The value in the tree changes but the value in the actual text of the Flexscript code does not change. Has anyone ever done this and if so how?
|
#2
|
||||
|
||||
Joe,
Is there a particular reason why you want to do that? If you have a variable you can give it a different value in any of a million ways. I would strongly suggest against trying to change the tree under a flexscript node. When a flexscript node is build, it breaks up into the seperate commands and those are stored in the three and is available for the engine to execute it. It is not mend to try to change that on the fly. Steven |
#3
|
|||
|
|||
Edit Value of Variable in Flexscript Node
The reason I need to do this is for performance. I have many event generated global table lookups when my model runs. I was using a user defined command to lookup values in my global tables that looped through the rows until a match was found. So, to improve performance I'm trying to develop a process that will find the row number of the global table when the model is reset and then write all those values as hard coded numbers into the text of the Flexscript that gets executed during runtime. In this way there would be no looping through rows in global tables and no comparetext() commands going during runtime. This approach would leave only direct global table lookups for Flexsim to execute during runtime.
Hard coding the values into every MTBF_MTTR object and every processor is not an option due to the size of the model. This would make the code in the model a maintenance nightmare. Any suggestions for an alternative to what I was attempting to do would be greatly appreciated. |
#4
|
||||
|
||||
If I understood you correctly there are 2 solutions that come to mind. They are:
1 Use a seperate global table to store the pointers to the rows you need 2 use an array. You can even make a treenode array that points directly to the table cell. That is as fast as it can get. Hope this is of any help. Steven |
#5
|
|||
|
|||
Steven - forgive me for not understanding you. I'm new to Flexsim. If you set up a treenode array how would the code with original global table lookup know where to go in the array to retrieve the correct rownumber unless the coder manually told it where to go? Please keep in mind that I want the code in each object to be completely maintenance free, meaning that no hard coded values exist that would ever need to be changed manually.
|
#6
|
||||
|
||||
Joe, it might very well be that I'm understanding you completely but let's give it another try. If I understand correctly you have for instance an MTBF object and you want that the MTBF times are read from a table. But you don´t want to call a function that runs through a table to find the row where you want to take your data from. Is this right?
1 A few things come to mind: Have you read this post: http://www.flexsim.com/community/for...read.php?t=542 It deals with speeds of different commands and what is the fastest way of getting access to different pieces of data. 2 Are you aware that you can toggle a flexscript node as c++ and that you can compile your model? This will give you a speed gain from anywhere between 2 till 10 times or sometimes even more. 3 Then to come back to your original question, the first thing that you could do is create a label on your object and give your object a unique number. that way you can use that unique number as an entry in your array. That would still mean that you manually have to enter that number on an object but you have to do it only once when you create the object. 4 Or you could use a global variable. You create a global variable in the Tools section and use that variable in your code. On reset you can fill those global variables with the data you want. That way you never have to touch your code again, only in the onreset you manipulate the values. Hope this is of any help Steven |
The Following 2 Users Say Thank You to Steven Hamoen For This Useful Post: | ||
Kris Geisberger (09-17-2008) |
#7
|
|||
|
|||
Another option for 3 and 4 in Steven's post:
When I have a group of objects (say Processors) and I want each to look-up a unique row in a single Global Table called "Machines" for setup, process, and down time data... I make sure that center port 1 of all of these objects are connected to a single dummy object (you can use any object) that I would name something like MachineRowIndex. Then in the Setup Time of the Processors for instance use the command cpcpno(current,1) in place of the row parameter in a command like gettablenum(). Also, rearrange the center ports of the MachineRowIndex object to correspond to the row order that the data is arranged in the Global Table. ex. gettablenum("Machines", cpcpno(current,1), 1) If these look-ups are very frequent, see the post that Steven linked above for a better way to reference the Global Table instead of using "Machines" in the above example. Another example is a table of Conveyor speeds. Use another dummy row index object to center port connect to all of your conveyors to, just like in the above example. If you wish you can now centralize your reset code in the OnReset of the row index object; using a for loop to go through all of the objects connected to its center ports and use commands like changeconveyorspeed() and setvarnum() to change the conveyor variables to match the data from the table. In a way, you can see that this central dummy row index object can be interpreted as a "Manager", so often I call them MachineManager, or ConveyorManager respectively. ...What you name the object is irrelevant. Kris Last edited by Kris Geisberger; 09-17-2008 at 09:33 AM. |
The Following User Says Thank You to Kris Geisberger For This Useful Post: | ||
Joe Allen (09-17-2008) |
#8
|
|||
|
|||
Steven - yes you are understanding me correctly. 1) - I need to read the post. Thank you for providing the link. 2) - I plan on switching the model to run in C++ mode when all coding and logic is done. 3and4) - I was hoping I wouldn't have to create global variables or labels and that I would be able to handle everything with an algorithm that ran on reset. I guess I'll just have to "bite the bullet".
Are you sure there is no way to edit the text in a Flexscript node with code? |
#9
|
||||
|
||||
You can edit the text in a Flexscript node with the setnodestr() command, which you would probably want to use the concat() command for what you set the text string to, but this is still a bad idea, especially because you would then have to rebuild Flexscript each time you change it.
A better idea, as Steven suggested, is to just use Global Variables or macros and set these values before running your simulation. |
The Following User Says Thank You to Phil BoBo For This Useful Post: | ||
Joe Allen (09-17-2008) |
#10
|
||||
|
||||
Joe,
If you were really ambitious you could still do what you were trying to do, except instead of writing a new value to a node you could change the value in a string and write the string to the node. What I mean by this is that in your code where you are going through and trying to change the node value of a sub Flescript node you could instead have your code rewrite the string for the whole node and then call the buildnodeflexscript() command on the node. If for example, I wanted to change the column value in the following Trigger code: treenode current = ownerobject(c); item = parnode(1); return gettablenum("Mytable", 1, 2); So, to change the column from 2 to 3 I could write the following code: int newvalue = 3; setnodestr(mynode, concat("treenode current = ownerobject(c); item = parnode(1); return gettablenum(\"Mytable\", 1, ", numtostring(newvalue, 0, 0), ");") ); buildnodeflexscript(mynode); You'll notice that the quotes inside of the string had to have a \ put in front of them to designate that the quotes were inside of the string and not defining it. The down side of doing this is that the strings have to be defined in your code but the plus side is that this will do exactly what you want. I wouldn't recommend doing this on reset as it is doubtful that your model is going to change every time you hit reset. I would place this on the import finish trigger of the MTEI or on a button in the control GUI. Good Luck, Brandon
__________________
thats not normal. |
The Following 2 Users Say Thank You to Brandon Peterson For This Useful Post: | ||
Tom David (09-17-2008) |
#11
|
|||
|
|||
I'm feeling ambitious. That's exactly what I was looking for. Thanks Brandon.
Phil - I see your point but I'm not worried about rebuilding Flexscript every time I change it since the code would be very specific to updating values for MTTBMTTR and would never change. The only rebuilding I plan to do is one variable value. If the only option is to rebuild the entire Flexscript node I'll do that. The code will loop through each machine in the global table and rebuild the corresponding Flexscript for First Time Failure, MTBF and MTTR nodes (searching for a nodename match and replacing the value assigned to the row number variable each time). Once this code is built I won't ever have to change it again as long as the code template is identical across all MTBFMTTR objects. The work is done upfront in code on one production line and any future line (we have many) can utilize the same code templates. |
#12
|
||||
|
||||
Joe asked me the following:
Brandon - I have one question. If instead of putting in /"mytable/" into the code that rebuilds the Flexscript I instead substitute a string variable that gets read in as an input parameter to this procudure. How would I define the variable in the code of the calling procedure. Like this? string tablename = "mytable"; ...or like this? string tablename = concat(/", "mytable", /"); Answer: Basically when you create the string the string becomes the entire block of code that will be executed later so if you were going to use a variable that pointed to the table then it would be declared within the string. I would also like to point out that if you are trying to get the model to run faster then you would want to use a treenode in your table look ups or a rank value instead of a string. In almost all of my models I will #define the ranks of the tables in the the Global Variables GUI so that I can use them in my table look ups. Good Luck, Brandon
__________________
thats not normal. |
#13
|
|||
|
|||
I'm trying to use gettablenum() with a treenode object of the global table rather than a string of the global table name and I can't seem to get it to work properly. Why doesn't this work?
int ranknumformyGT = 5; int rownum = 2; int colnum = 2; double theval = gettablenum(rank(rank(rank(model(),1),4),ranknumfo rmyGT),rownum,colnum); |
#15
|
|||
|
|||
That's not the actual code, just a hastily typed sample of how I might try and use it. Here is the actual code that I can't get to work:
pt("The value in global table GTTest in cell 2, 2 is "); treenode GTobj = rank(rank(rank(model(),1),4),2); double theval = gettablenum(GTobj,2,2); pf(theval); pr(); |
#16
|
||||
|
||||
The table data of a global table isn't the GlobalTable object itself. It is a variable called "data".
The proper way you should be doing this is: pt("The value in global table GTTest in cell 2, 2 is "); treenode GTobj = reftable(2); double theval = gettablenum(GTobj,2,2); pf(theval); pr(); |
The Following User Says Thank You to Phil BoBo For This Useful Post: | ||
Joe Allen (09-17-2008) |
#18
|
|||
|
|||
Brandon - how do I get carriage returns into a string? I'm not sure if the code that you listed above will work as is. I also would like to not have to list the contents of the string all on one line of code. I know how to do this in VB but not in Flexscript. How would I write the following VB code in Flexscript?
strMyString = "Line 1" & Chr(10) & _ "Line 2" & Chr(10) & _ "Line 3" |
#19
|
||||
|
||||
put \r into the string
string blah = "joe\ris\rgreat!"; just like \" puts a " into the string, \r puts a return character. |
The Following User Says Thank You to Phil BoBo For This Useful Post: | ||
Joe Allen (09-17-2008) |
#20
|
|||
|
|||
Success!
It works! Thanks to everyone on this thread that helped me out. You helped me add quite a lot of tools to my belt today.
If anyone is interested in the code I'll post it. It makes use of some global variables but they all start with a GV_ to identify them as such so it shouldn't be too hard to decifer what is going on. |
Thread | Thread Starter | Forum | Replies | Last Post |
Edit GUI's in userlibs | Steven Hamoen | User Development | 1 | 03-05-2009 03:43 AM |
size of arrays in Flexscript | Steven Hamoen | Q&A | 13 | 06-23-2008 01:04 PM |
Clean Flexscript | Steven Hamoen | Q&A | 1 | 04-04-2008 07:00 AM |
GUI: cant enter GUI edit mode | KelvinHo | Q&A | 4 | 04-01-2008 10:44 AM |
can I use an edit box entry to update multiple labels? | KelvinHo | Q&A | 10 | 03-28-2008 07:17 AM |