kelleyde sgp-copy: Event System, TaskValue Event Tests, CreateNANDProgram - #312
kelleyde sgp-copy: Event System, TaskValue Event Tests, CreateNANDProgram#312kelleyde wants to merge 52 commits into
Conversation
…ion management from event manager. Renaming/reorganization in progress.
…new events types to the event library
…iguring fluctuating environments
…updating directory, add stub for TaskValueEvent test file.
Event system updates
…p-copy Merging Lalejini events files .
…eleted in sgp host tests
…backtracing easier in a debugger when events file is not found
Update event system pull request to accomodate merged changes from main
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #312 +/- ##
==========================================
+ Coverage 76.93% 77.57% +0.63%
==========================================
Files 108 114 +6
Lines 23013 23476 +463
Branches 1609 1622 +13
==========================================
+ Hits 17706 18212 +506
+ Misses 5236 5190 -46
- Partials 71 74 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| json_t& event_json, | ||
| WORLD_T& world | ||
| ) { | ||
| // This should be a task_value event |
| // Check that event_json has event type | ||
| emp_assert(event_json.contains("event_type")); | ||
| const std::string event_type(event_json["event_type"]); | ||
| // emp::Ptr<Event> loaded_event; |
| } | ||
|
|
||
| /** | ||
| * Purpose: |
| } | ||
|
|
||
| /** | ||
| * Purpose: load in and process events configuratoin json file (includes |
| */ | ||
| void ProcessEvents(world_t& world) { | ||
| // Get current update in the world. Process all events that should occur on this update. | ||
| // Options: |
There was a problem hiding this comment.
It looks like this is decided and I agree so this should be removed
|
|
||
| // Event handler function type | ||
| using fun_event_handler_t = std::function<void( | ||
| world_t&, // sgp world to use helper functions and avoid circualr dependency |
| @@ -65,21 +66,11 @@ class LogicTaskEnvironment { | |||
| // TODO - track task performance? | |||
|
|
|||
| // TODO - move this into util file in json directory | |||
There was a problem hiding this comment.
This comment is done now right?
There was a problem hiding this comment.
Yup, I think both of those todos are done. Removing those comments.
| VALUE(EVENTS_CFG_PATH, std::string, "events.json", "JSON file that provides event configuration"), | ||
|
|
||
| GROUP(INSTRUCTIONS, "Instruction settings"), | ||
| VALUE(SENSE_TASK_INSTRUCTION, bool, false, "Should sense task instruction be included in the instruction set?"), |
There was a problem hiding this comment.
Probably clearly call it 'SenseTask' so that it's obvious what the name of the instruction is
There was a problem hiding this comment.
Good call, totally agree. Just in case there are future enable/disable config options, what about INCLUDE_INSTRUCTION_SenseTask? to make it super clear what we're toggling
| */ | ||
| void Update() override { | ||
| emp_assert(setup); | ||
| // NOTE - When do we want events to occur? Typically, I think we want them |
There was a problem hiding this comment.
Agreed, I think they have to just be the first thing that happens in an update. So let's remove the comment
| GIVEN("A host with valid values in its input and output buffers") { | ||
| emp::Random random(31); | ||
| sgpmode::SymConfigSGP config; | ||
| config.EVENTS_CFG_PATH("source/test/sgp_mode_test/no-events.json"); |
There was a problem hiding this comment.
It seems like there should be some way to indicate no events file and that should be fine, since it is reasonable to not specify any events and it's annoying to have to have an empty events file to run anything. Is it too gross to have the loading code not error if the "path" specified is "no-events" (without the .json) and just output that no events file was loaded as specified?
There was a problem hiding this comment.
As per discussion in slack, if no file is found + the config is set to the default setting, we'll generate a default (empty) events file and print a helpful message.
| world.AddOrgAt(host, 0); | ||
| host->AddSymbiont(symbiont); | ||
|
|
||
| THEN("Events are processed") { |
There was a problem hiding this comment.
Ideally this when/then would have more information about what the test is actually checking, but we can leave that for further dev work in the future
anyaevostinar
left a comment
There was a problem hiding this comment.
Wow, very nice! Couple of places with commented out code or discussion comments that can be cleaned up. Main thing is making it so that you don't have to have an events file to run if you don't want any events
Event System
Event files path: source/sgp_mode/events
Event.h - generic event class that more specific event type classes can inherit from. The generic event class includes the minimum necessary member variables for creating an event. Member functions have logic for determining if an event is one time or reoccurring, and for advancing reoccurring events to the next step.
ExampleEvent.h - example of an event class. It is not meant to be functional, just a guide to creating new event classes and types.
TaskValueEvent.h - task_value event class and data structures. Task value events are events where the value(s) of a certain logic task(s) are altered/changed. They have three different action types (specified in the “action” field of the json file), CHANGE will set a task value to a new value, ADD will add a specific value to the previous task value, or MULT will multiply the previous task value by a specific value. These changes can be applied to symbiont tasks (SYM), host tasks (HOST), or both (SHARED), depending on the “group” field of the json file.
Example of json file fields: "event_type": "task_value", "task_name": "NAND", "action": "change", "value": 50, "timing": "1", "group": "host"
Task name can also be a list of multiple different tasks, for example [“NOT”, “NAND”].
If timing is three integers separated by a “:” then it is a reoccurring event, for example “1:4:2” (order is “start:stop:step”). A single integer in the “timing” field indicates a one time event.
Options for “group” are “host”, “symbiont”, “shared”.
Options for “action” are “mult”, “add”, “change”.
EventManager.h - stores all one-time and recurring events in two different vectors, loads events from json file, processes and reorder events, deletes finished events from end of the vector, includes logic for adding new events. For managing all loaded events and processing them.
EventTiming.h - tracks the timing of events, for example, by getting start, end, and next updates, tracking the next step for reoccurring events, or resetting timing. For helping track timing of events.
EventTypeDefinition.h - contains necessary variables and functions to define an event type and includes handling for loading and processing events. For defining event types.
EventTypeLibrary.h - contains map of event names to event ids and vector of event type definitions. There are functions for checking valid event types, loading and processing different event types, adding new event types, getting event ids. For storing event types.
In SGPWorld.h, Update( ) line 656, events are processed at the start of every update.
In SGPWorldSetup.cc line 50 and 1208, events are loaded in from a json file.
Task Value Event Tests
Path: source/test/sgp_mode_test/functional_tests/TaskValueEvent.test.cc
Tests different task value event actions (change, add, mult), groups (host, symbiont, shared), and timing (one time, reoccurring). Also tests task value events on different tasks and multiple tasks at a time. Tests check change in task value and in points host and symbiont accumulate.
Changes to ProgramBuilder.h CreateNANDProgram line 358.
Two registers are used to cycle through a NAND b, b NAND c, c NAND d, and d NAND a. New input gets placed in the register that holds the NAND of the previous two inputs. The NAND of the next two inputs are placed in the opposite register of the new input. For example register 0 = a, register 1 = b, and register 0 = a NAND b, then the next input c is put in register 0, and c NAND b goes in register 1. Following this logic, the next new input d goes in register 1, and c NAND d goes in register 0.