33#define SYM_ANIMATE_H
44
55#include < iostream>
6+ #include < optional>
7+ #include < string>
8+ #include " uitsl/fetch/autoinstall.hpp"
69#include " default_mode/SymWorld.h"
710#include " default_mode/DataNodes.h"
811#include " ConfigSetup.h"
912// #include "SymJS.h"
1013#include " default_mode/Symbiont.h"
1114#include " default_mode/Host.h"
15+ #include " emp/base/errors.hpp"
1216#include " emp/web/Document.hpp"
1317#include " emp/web/Canvas.hpp"
1418#include " emp/web/web.hpp"
2125namespace UI = emp::web;
2226SymConfigBase config; // load the default configuration
2327
28+ // / Configure accepted URL query params: config keys and autoinstall...
29+ // / e.g., symbulation.html?autoinstall=foo.com/file.json&VERTICAL_TRANSMISSION=0.9
30+ emp::ArgManager::spec_map_t arg_specs = [](){
31+ auto specs = emp::ArgManager::make_builtin_specs (&config);
32+ specs[" autoinstall" ] = emp::ArgSpec (
33+ 1 , // one value expected
34+ " URL of a file to download into the virtual filesystem at startup" ,
35+ {}, // no aliases
36+ [](const emp::optional<emp::vector<std::string>>& urls) {
37+ if (!urls) return ;
38+ for (const std::string& url : *urls) {
39+ std::cout << " autoinstalled " << url << " as "
40+ << uitsl::autoinstall (url) << std::endl;
41+ }
42+ }
43+ );
44+ return specs;
45+ }();
2446
2547
2648class SymAnimate : public UI ::Animate {
@@ -35,8 +57,9 @@ class SymAnimate : public UI::Animate {
3557
3658 const int RECT_WIDTH = 10 ;
3759
38- emp::Random random{config.SEED ()};
39- SymWorld world{random, &config};
60+ emp::Random random;
61+ // optional allows emplacement once config is parsed
62+ std::optional<SymWorld> world;
4063
4164
4265 emp::vector<emp::Ptr<Organism>> p;
@@ -96,17 +119,21 @@ class SymAnimate : public UI::Animate {
96119 buttons.SetCSS (" max-width" , " 600px" );
97120
98121
99- initializeWorld ();
100122 emp::prefab::Card config_panel_ex (" INIT_CLOSED" );
101123 settings << config_panel_ex;
102124 config_panel_ex.AddHeaderContent (" <h3>Settings</h3>" );
103125
104126 // apply configuration query params and config files to config
105- auto specs = emp::ArgManager::make_builtin_specs (&config);
106- emp::ArgManager am (emp::web::GetUrlParams (), specs);
127+ emp::ArgManager am (emp::web::GetUrlParams (), arg_specs);
107128 // cfg.Read("config.cfg");
108129 am.UseCallbacks ();
109- if (am.HasUnused ()) std::exit (EXIT_FAILURE );
130+ if (am.HasUnused ()) {
131+ emp::NotifyWarning (" Unrecognized URL query parameters, ignored." );
132+ }
133+
134+ random = emp::Random{config.SEED ()};
135+ world.emplace (random, &config);
136+ initializeWorld ();
110137
111138 // setup configuration panel
112139 // config_panel.Setup();
@@ -132,14 +159,14 @@ class SymAnimate : public UI::Animate {
132159 buttons.Button (" toggle" ).OnMouseOut ([this ](){ auto but = buttons.Button (" toggle" ); but.SetCSS (" background-color" , " #D3D3D3" ); });
133160
134161 // ----------------------- Add a reset button to reset the animation/world -----------------------
135- /* Note: Must first run world. Reset(), because Inject checks for valid position.
162+ /* Note: Must first run world-> Reset(), because Inject checks for valid position.
136163 If a position is occupied, new org is deleted and your world isn't reset.
137164 Also, canvas must be redrawn to let users see that it is reset */
138165 buttons.AddButton ([this ](){
139- world. Reset ();
166+ world-> Reset ();
140167 buttons.Text (" update" ).Redraw ();
141168 initializeWorld ();
142- p = world. GetPop ();
169+ p = world-> GetPop ();
143170
144171 if (GetActive ()) { // If animation is running, stop animation and adjust button label
145172 ToggleActive ();
@@ -160,7 +187,7 @@ class SymAnimate : public UI::Animate {
160187
161188 // ----------------------- Keep track of number of updates -----------------------
162189 buttons << " <br>" ;
163- buttons << UI::Text (" update" ) << " Update = " << UI::Live ( [this ](){ return world. GetUpdate (); } ) << " " ;
190+ buttons << UI::Text (" update" ) << " Update = " << UI::Live ( [this ](){ return world-> GetUpdate (); } ) << " " ;
164191 buttons << UI::Text (" mut" ) << " Mutualistic = " << UI::Live ( [this ](){ return num_mutualistic; } ) << " " ;
165192 buttons << UI::Text (" par" ) << " Parasitic = " << UI::Live ( [this ](){ return num_parasitic; } );
166193 buttons << " <br>" ;
@@ -186,11 +213,11 @@ class SymAnimate : public UI::Animate {
186213 void initializeWorld (){
187214 // Reset the seed and the random machine of world to ensure consistent result (??)
188215 random.ResetSeed (config.SEED ());
189- world. SetRandom (random);
216+ world-> SetRandom (random);
190217
191- world. Setup ();
218+ world-> Setup ();
192219
193- p = world. GetPop ();
220+ p = world-> GetPop ();
194221
195222 }
196223
@@ -295,15 +322,15 @@ class SymAnimate : public UI::Animate {
295322 */
296323 void DoFrame () {
297324
298- if (world. GetUpdate () == config.UPDATES () && GetActive ()) {
325+ if (world-> GetUpdate () == config.UPDATES () && GetActive ()) {
299326 ToggleActive ();
300327 } else {
301328 mycanvas = animation.Canvas (" can" ); // get canvas by id
302329 mycanvas.Clear ();
303330
304331 // Update world and draw the new petri dish
305- world. Update ();
306- p = world. GetPop ();
332+ world-> Update ();
333+ p = world-> GetPop ();
307334 drawPetriDish (mycanvas);
308335 buttons.Text (" update" ).Redraw ();
309336 buttons.Text (" mut" ).Redraw ();
0 commit comments