07-10-2020 04:25 AM
I'm glad you finally gave a picture of your actual data structure.
I don't understand what you mean by "start cluster" and "cluster add".
The cluster for tab A parameters. TypeDef it and write it to the config file. (Again, I recommend MGI Read/Write Anything)
Tab B. A cluster for those parameters. Typedef it. Write it to the config file.
I don't understand why the data for the test steps is split between tabs C and D. It seems that the duration for a step should be defined on the same page that you define the parameters for that step.
A step should be a cluster of {duration, pressure limit, pressure limit tolerance, flow limit, flow limit tolerance}. Perhaps there are other items that belong in the cluster as well. That cluster should be a TypeDef. There is no reason for that cluster type definition to ever change during the course of normal operation.
For a whole test of different steps, then you have an array of that cluster that can be be written to the config file.
Your button to add a step is just an event that builds another element into the array. Of course a good user interface probably needs a way to delete a step, and to rearrange them.
I know that MGI Read/Write can handle arrays of clusters. If you do need to change a cluster let's say to add a new parameter, than you can add that and update the type definition. With MGI, you can define what the default data is so that if you read from a config file that was saved prior to your typedef change, it will fill in the missing data with your default data.
07-10-2020 04:59 AM
"StartCluster" and "ClusterAdd" was referring to sample vi I posted in the message prior to my previous reply. (StartCluster being the parameter shown to the user on the front panel at the start of the program and ClusterAdd is the parameters that are added by the user)
Tab C and D was split based on the previous version of the program because there were fixed durations for each test step . (eg if 10s is entered under the Pressure duration field, all Pressure test steps will run for 10s). It was also split due to space. Initially I planned for the additional new fields to appear on the front panel everytime a user clicks a boolean so I wanted to leave some space for them. But your idea certainly gives more flexibility.
By the way, the boolean to add more parameter fields only appears to the user if they choose a certain option (which also lies within the cluster) so there's another layer there.
07-10-2020 08:40 AM
Still have a master cluster which holds all parameters you need and typedef that.
You don't need different clusters for each type. Separate your user interface structure from your data.
Let's say test type A determined by a boolean has requires these parameters.
TestType (=A) Duration. P1 P2 P3 P5
Test type B requres
TestType (=B) Duration P1 P3 P4 P6
Make your cluster a typedef that contains
TestType (will be A or B) Duration P1 P2 P3 P4 P5 P6
For test type A since you don't use P4 or P6, hide the controls that input that data. When you build the array with new data, put is a null or some other valid that reflects it is invalid
For test type B since you don't use P2 or P5, hide the controls that input that data. When you build the array with new data, put is a null or some other valid that reflects it is invalid
When a step for test type A runs, it reads the whole cluster of that element of the array, it knows it is type A, and the test profile won't care about the data (or lack thereof) in P4 and P6. Likewise when a step for test type B runs, it knows it is type B and won't care about the data in P2 and P5.
07-14-2020 06:34 AM
Your suggestions make a lot of sense, but using your example, having a master cluster of P1 P2 P3 P4 P5 P6 works when I know that it can only be from P1 to P6. But say a new test type pops up and require P7, that would require me to continuously go back into development mode to change the type def
07-14-2020 08:02 AM
One way I've dealt with that kind of open-endedness is to take a lesson from the QMH template and use a very open-ended main datatype - a cluster containing a String and a Variant. The String is used to contain the test ID, the Variant can hold whichever specific typedef'ed cluster is relevant for that particular test.
To work with MGI's Read/Write Anything, I then read or write the 2 things separately. The Test ID is read on its own. Then that Test ID is used to select a case from a case structure where that particular test's cluster of parameters is read from the same INI section.
Writing to the INI can be done similarly.
New Test ID's will generally only require you to add a single new case in the area where you read and write INI files. Those who are somewhat fluent in LVOOP would tell you that they could design this in a way that allowed you to add new Test ID's without any changes to the main application code. But unless you're already pretty familiar with LVOOP, I'd recommend you stick with clusters and case structures for now. There's a fairly substantial learning curve.
-Kevin P
07-14-2020 08:37 AM
@Kevin_Price wrote:
But unless you're already pretty familiar with LVOOP, I'd recommend you stick with clusters and case structures for now. There's a fairly substantial learning curve.
I wouldn't call a simple Factory Pattern a substantial learning curve. Maybe a mild one. Once you get the basics of OOP and dynamic dispatch, the Factory Pattern is just another small step.
07-14-2020 09:02 AM
Yeah, I was meaning the learning curve for LVOOP generally. Plus the various intricacies of building and managing the PPL's you'd need in order to support extensibility without changing the main app.
I still need to see a big payoff before going down that road. Last time I did it, the payoff didn't really materialize sufficiently to justify the extra work. And users ended up not *needing* the app to be ever-evolving, so the extensibility hasn't been much of an advantage.
-Kevin P
07-14-2020 09:09 AM
@Kevin_Price wrote:
Plus the various intricacies of building and managing the PPL's you'd need in order to support extensibility without changing the main app.
Ok, THAT I will concede on is a big curve to get through. I am seeing the benefits of doing this mostly because it is a test framework and has been used on several programs.
07-14-2020 09:56 AM
@nikvl wrote:
Your suggestions make a lot of sense, but using your example, having a master cluster of P1 P2 P3 P4 P5 P6 works when I know that it can only be from P1 to P6. But say a new test type pops up and require P7, that would require me to continuously go back into development mode to change the type def
Of course. But you say "continuously" go back. How often do you really have to do that? Of course you are going to have to make modifications to your code as your make modifications to your requirements. But the MGI Library will easily fill in the new P7 with a default value if you go back to read an old config file from prior to your code modification.
It seems like you are asking for the holy grail of a program that can do anything and everything without having to ever touch it again despite not even knowing yet all the things you will eventually do with it.