Anylogic, how to setup a button so it would restart the simulation - button

Good day,
Currently, there are 6 edit boxes, which are connected to specific parameters in the model (and the user can edit these boxes in the model runtime) and a button that doesn't do anything. I want to make this button to restart the simulation, yet if the user previously changed some contents in edit boxes, the new simulation will run based on the user input values. The model name is Simulation.
If anyone knows an example (or specific code) it would be highly appreciated.

Adding to Artem's reply on issue 1: it is actually possible, but you will create a new thread, so a bit advanced. This code will stop the current experiment and restart it:
new Thread() {
public void run() {
getExperiment().stop(); // stops the model
getExperiment().run(); // runs it again
getExperimentHost().setPresentable( getEngine().getRoot() );
}
}.start();
You can make sure to set your params for the new run as Artem discussed.
PS: Would be better to simply make the user press the stop button, feed the values to the experiment page, let the user re-adjust them if needed and let her restart the model as usual.

To clarify, there are two questions:
How to have the button in model that restarts the simulation? - this isn't possible. But what can be done is have a button that calls stopSimulation() and returns the user into the Simulation set up
How to have changes made in model during runtime propagate to the next Simulation run? - save the values from edit fields into internal properties of the model and then access them in Simulation's After simulation run Java action by checking root object

Related

How to initialise controllers using provider state in flutter

I recently refactored half my app to use the provider pattern and i now have a problem. The main issue is that i need to initialise controllers in the init (e.g. a text controller to have an initial value or the list size of a tab controller)
How am i meant to init Controllers if the data i need has to come from the state in the build method.
For example.
// This must go in the build as it requires state
myTabsController = TabController(length: myState.list.length, vsync: this);
I'm initialisng the controller every time it builds now... How am i meant to put this in the init but still access the state variables (as there is no context).
I've tried using the afterFirstLayout() callback from the AfterLayoutMixin library but that just causes more problems. Currently with the tab bar it flashes error as no tab initialised for the first frame and then displays properly when the afterFirstLayout is called and initialises the tab. This seems like a hacky fix
I would like to learn more about how to use this pattern properly and what would be the best solution to this problem.
Feel free to ask me to clarify more.
Thanks for your help.

Anylogic - Restart Simulation from a Button

I would like to create a button that the user can press during model execution which stops the model and begins running it again from time = 0.
The following code does work, but only some of the time and will sometimes work for two or three presses of the button before the model just hangs.
pauseSimulation();
stopSimulation();
getExperiment().stop();
((Simulation) getExperiment()).button.action();
getExperiment().run();
This sometimes is associated with getEngine().getState() = PLEASE_WAIT, but not always.
I don't know if it's a timing issue, or that I should be doing things is a slightly different order, or with different phraseology.
Any pointers greatly appreciated.
In your button action use
getExperiment().stop();
In your simulation experiment properties, in the Java Actions section, add the following to After Simulation Run:
run();

copy/paste of Page doesn't start workflow in same SG, starts workflow in other SG

I was perplexed by a user turning up this sort of behavior recently. Assume all SGs have workflow set.
Copy Page X in SG A, paste in same SG A. Page Y is created but no workflow is initiated.
Copy Page X in SG A, paste in other SG B. Page Z is created and workflow is initiated.
Now, the first scenario I confirmed with Nuno when he was on site. We agreed with business folks that we can live with that behavior. However, I'm curious why the second scenario happens as-is. If #1 doesn't kick off workflow, why should #2? Can anyone explain why? Is there any way I could programmatically cause scenario #1 to start the workflow (as the business would like that to happen)? or, worst case disable it from #2. It should be consistent.
But in practical scenario, I would really question the need for workflow to kick off as soon as you copy the page in the same structure group.
When you copy a page in the same structure group, it will create a page with title Copy of original page name and the CMS User will obviously wants/needs to edit the page with proper page name. As soon as they save the page workflow kicks in. Also, CMS user may want to change some component presentations on the page as well.
When you copy this on a different structure group, you are creating a page with a name in other structure group, so the workflow kicks in since it is not same copy in same structure group.
I would consider this as a nice feature :) :).
However as Nick suggested I would recommend submitting a support ticket as well.
If you want to consider a programmatic approach for your scenario # 1, you could implement the EventSystem to force the workflow kick off by simply saving the page again with same user who created it. You need to capture the CopyEvent .
Sample EventSystem stub if you want to go this route (Not Tested) :
private void Subscribe()
{
EventSystem.Subscribe<Page, CopyEventArgs>(PostCopyActivity, EventPhases.Processed);
}
private static void PostCopyActivity(Page page, CopyEventArgs args, EventPhases phase)
{
// do your logic to save page..
string sourceId = args.CopiedObject.OrganizationalItem.Id;
string destinationId = args.Destination.ToString();
if (sourceId.Equals(destinationId))
{
// copying to the same location .. so now get the User Session and Update the page to force workflow
}
}
Hope this information helps.
I went ahead and tried this on my system, and it does not start a workflow in any case (copy/pasting to same structure group or different structure group).
Do you have an event triggered on Paste?

Flex addEventListener - how to refresh the screen during called event?

I can't seem to find the answer to what I would have thought was a common problem.
What I want to do this is:
1. Show the Open File Dialog
2. Process the file selected
3. During processing the file, report progress to the User
I have a file defined, and am using the browseForOpen and AddEventListener:
public var fileInput:File = new File();
fileInput.browseForOpen("Open file",[filter]);
fileInput.addEventListener(Event.SELECT, onFileSelect);
// Step 2 - function gets called to process the file
private function onFileSelect(e:Event):void
{
// Step 3 - do some processing, and at intervals report progress to the screen
}
My issue is - any changes to the screen within the event listener do not get done until the function is complete.
Any help would be appreciated,
Thanks
Start a timer perhaps and let it check status of a variable(that denotes processing progress) as a separate running function it would not be predisposed to waiting on the parent function.
[ to be clear Im saying call a sperate function from the timer.]
But I am inclined to agree with Flextras.com in that most times I have done this the processing was milliseconds so just didnt get seen.
In Step 3, if you are doing some cpu intensive job(like huge xml parsing), then you might be seeing this NOT updating problem. As Flex is single threaded, you better make use of Green threading concept.
You can read about Green Threading here.

Asynchronous validation in QWizard

I'm writing a wizard UI based on the QWizard Qt object. There's one particular situation where I want the user to log in to a service using host, username, and password. The rest of the wizard then manipulates this service to do various setup tasks. The login may take a while, especially in error cases where the DNS name takes a long time to resolve -- or perhaps it may not even resolve at all.
So my idea is to make all three fields mandatory using the registerField mechanism, and when the user hits Next, we show a little throbber on the wizard page saying "Connecting to server, please wait..." while we try to connect in the background. If the connection succeeds, we advance to the next page. If not, we highlight the offending field and ask the user to try again.
However, I'm at a loss for how to accomplish this. The options I've thought of:
1) Override validatePage and have it start a thread in the background. Enter a wait inside validatePage() that pumps the Qt event loop until the thread finishes. You'd think this was the ugliest solution, but...
2) Hide the real Next button and add a custom Next button that, when clicked, dispatches my long running function in a thread and waits for a 'validation complete' signal to be raised by something. When that happens, we manually call QWizard::next() (and we completely bypass the real validation logic from validatePage and friends.) This is even uglier, but moves the ugliness to a different level that may make development easier.
Surely there's a better way?
It's not as visually appealing, but you could add a connecting page, and move to that page. If the connection succeeds, call next() on the wizard, and if the connection fails, call previous() and highlight the appropriate fields. It has the advantage of being relatively straightforward to code.
My final choice was #2 (override the Next button, simulate its behavior, but capture its click events manually and do the things I want to with it.) Writing the glue to define the Next button's behavior was minimal, and I was able to subclass QWizardPage with a number of hooks that let me run my task ON the same page, instead of having to switch to an interstitial page and worry about whether to go forwards or backwards. Thanks Caleb for your answer though.
I know this has already been answered (a long time ago!) but in case anyone else is having the same challenge. Another method for this is to create a QLineEdit, initiate it as empty and set it as a mandatory registered field. This will mean that "Next" is not enabled until it is filled with some text.
Run your connection task as normal and when it completes use setText to update the QLineEdit to "True" or "Logged in" or anything other than empty. This will then mean the built in isComplete function will be passed as this previously missing mandatory field is now complete. If you never add it to the layout then it won't be seen and the user won't be able to interact with it.
As an example ...
self.validated_field = QLineEdit("")
self.registerField('validated*', self.validated_field)
and then when your login process completes successfully
self.validated_field.setText("True")
This should do it and is very lightweight. Be sure though that you consider the scenario where a user then goes back to that page and whether you need to reset the field to blank. If that's the case then just add in the initialisePage() function to set it back to blank
self.validated_field.setText("")
Thinking about it you could also add the line edit to the display and disable it so that a user cannot update it and then give it a meaningful completion message to act as a status update...
self.validated_field = QLineEdit("")
self.validated_field.setDisabled(True)
self.validated_field.setStyleSheet("border:0;background-color:none")
self.main_layout.addWidget(self.validated_field)
self.registerField('validated*', self.validated_field)
and then when you update it..
self.validated_field.setText("Logged in")

Resources