diff --git a/README.md b/README.md index cd02ac83..d7fb7338 100755 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Note: This library is still under development, and some concepts or features mig ``` dependencies { ... - implementation 'com.github.CST-Group:cst:1.5.0' + implementation 'com.github.CST-Group:cst:1.6.0' } ``` @@ -53,7 +53,7 @@ Sometimes, the version number (tag) in this README gets out of date, as maintain com.github.CST-Group cst - 1.5.0 + 1.6.0 ``` diff --git a/build.gradle b/build.gradle index 87b497e5..d44fedc9 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ java { } -version = '1.5.0' +version = '1.6.0' repositories { mavenCentral() @@ -177,4 +177,4 @@ testlogger { // set to false to hide failed standard out and error streams showFailedStandardStreams true -} \ No newline at end of file +} diff --git a/src/main/java/br/unicamp/cst/core/entities/Codelet.java b/src/main/java/br/unicamp/cst/core/entities/Codelet.java index a29418aa..57060076 100755 --- a/src/main/java/br/unicamp/cst/core/entities/Codelet.java +++ b/src/main/java/br/unicamp/cst/core/entities/Codelet.java @@ -803,6 +803,21 @@ public synchronized void setIsMemoryObserver(boolean isMemoryObserver) { this.isMemoryObserver = isMemoryObserver; } + /** + * Check if this Codelet is in publish-subscribe mode. + * + */ + public synchronized boolean isPublishSubscribe() { + return isMemoryObserver; + } + + + /** + * Sets and unsets publish-subscribe mode. + * + * @param enable + * sets publish-subscribe mode on true or false + */ @SuppressWarnings("empty-statement") public synchronized void setPublishSubscribe(boolean enable) { if (enable) { diff --git a/src/main/java/br/unicamp/cst/representation/idea/HabitExecutionerCodelet.java b/src/main/java/br/unicamp/cst/representation/idea/HabitExecutionerCodelet.java index 8d7b0046..eaa3a794 100644 --- a/src/main/java/br/unicamp/cst/representation/idea/HabitExecutionerCodelet.java +++ b/src/main/java/br/unicamp/cst/representation/idea/HabitExecutionerCodelet.java @@ -12,37 +12,67 @@ import br.unicamp.cst.core.entities.Codelet; import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.MemoryContainer; + +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * This codelet executes a habit found in its input memories. + * + * It looks for a habit in a memory whose name is the + * same as the name of the codelet plus "Habits". + * + * It also looks for ideas in the other input memories and adds them + * to a root idea, which is passed as a parameter to the habit execution. + * + * If there is another habit in the input memories without the "Habits" + * suffix, it is added to the root idea as well, but not executed. + * + * The habit returns a root idea, which may contain several ideas inside it. + * The codelet looks for ideas inside the root idea whose names match (case insensitive) + * the names of its output memories, and sets those ideas to the respective memories. + * + * If the output memory is a MemoryContainer, it sets the MemoryObjects inside it + * with the name of the Habit being executed by the HabitExecutionerCodelet itslef. + * * @author rgudwin */ public class HabitExecutionerCodelet extends Codelet { - Habit h; Idea root; + String habitName; + + public HabitExecutionerCodelet() { + this.name = "Default"; + } + + public HabitExecutionerCodelet(String name) { + this.name = name; + } @Override public void accessMemoryObjects() { - root = new Idea("root"); + root = new Idea("root", ""); for (Memory m : this.inputs) { Object o = m.getI(); if (o instanceof Idea) { Idea id = (Idea)o; Object value = id.getValue(); - if (value instanceof Habit) { + if (m.getName().equalsIgnoreCase(this.getName()+"Habits") && value instanceof Habit) { h = (Habit) value; + habitName = id.getName(); } else { root.add((Idea)o); } } } - if (root.isLeaf()) { - Logger.getAnonymousLogger().log(Level.INFO, "I was not able to find any valid Idea at inputs"); + if (root.isLeaf() && this.inputs.size() > 1) { + Logger.getAnonymousLogger().log(Level.FINE, "I was not able to find any valid Idea at inputs"); } if (h == null) { Logger.getAnonymousLogger().log(Level.INFO, "I found no habit to execute"); @@ -56,10 +86,71 @@ public void calculateActivation() { @Override public void proc() { - if (h != null) { - Idea ois = h.exec(root); - for (Memory m : outputs) - m.setI(ois); + if (h == null) return; + + Idea outputRoot = h.exec(root); + if (outputRoot == null) return; + + try{this.setActivation(getActivationValue(outputRoot));}catch(Exception e){}; + + setTimeStepValue(outputRoot); + + setPublishSubscribeValue(outputRoot); + + setIdeasToOutputMemories(outputRoot); + } + + private double getActivationValue(Idea idea) { + double act = 0.0d; + Idea actIdea = idea.get("activation"); + if (actIdea != null && actIdea.getValue() instanceof Double) { + act = (double) actIdea.getValue(); + } + return act; + } + + private void setTimeStepValue(Idea idea) { + Idea timeStepIdea = idea.get("timeStep"); + if (timeStepIdea != null && timeStepIdea.getValue() instanceof Long) { + long timeStep = (long) timeStepIdea.getValue(); + try{this.setTimeStep(timeStep);}catch(Exception e){}; + } + } + + private void setPublishSubscribeValue(Idea idea) { + Idea publishSubscribeIdea = idea.get("publishSubscribe"); + if (publishSubscribeIdea != null && publishSubscribeIdea.getValue() instanceof Boolean) { + boolean publishSubscribe = (boolean) publishSubscribeIdea.getValue(); + try{this.setPublishSubscribe(publishSubscribe);}catch(Exception e){}; + } + } + + /** + * Gets the ideas from the outputRoot and sets them to the output memories + * that match by name (case insensitive). + * + * If the memory is a MemoryContainer, it sets the MemoryObjects inside it + * with the name of the Habit being executed by the HabitExecutionerCodelet itslef. + * It does so to differentiate between different Habits writing to the same MemoryContainer. + * + * @param outputRoot + * the root idea that comes from the habit execution + */ + private void setIdeasToOutputMemories(Idea outputRoot) { + Map outputsMap = new HashMap<>(); + for (Memory mem : this.outputs) outputsMap.put(mem.getName().toLowerCase(), mem); + + for (Idea outputIdea : outputRoot.getL()) { + Memory m = outputsMap.get(outputIdea.getName().toLowerCase()); + if (m == null) continue; // Skip to the next idea if no match is found + + if (m instanceof MemoryContainer) { + MemoryContainer mc = (MemoryContainer) m; + mc.setI(outputIdea, getActivationValue(outputIdea), habitName); + } + else { + m.setI(outputIdea); + } } } -} +} \ No newline at end of file diff --git a/src/test/java/br/unicamp/cst/representation/idea/HabitExecutionerCodeletTest.java b/src/test/java/br/unicamp/cst/representation/idea/HabitExecutionerCodeletTest.java index 9ed6d5f7..c0e3e10d 100644 --- a/src/test/java/br/unicamp/cst/representation/idea/HabitExecutionerCodeletTest.java +++ b/src/test/java/br/unicamp/cst/representation/idea/HabitExecutionerCodeletTest.java @@ -3,30 +3,54 @@ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template */ package br.unicamp.cst.representation.idea; -import br.unicamp.cst.core.entities.MemoryContainer; -import br.unicamp.cst.core.entities.MemoryObject; -import br.unicamp.cst.core.entities.Mind; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Random; + import org.junit.jupiter.api.Test; +import br.unicamp.cst.core.entities.MemoryContainer; +import br.unicamp.cst.core.entities.MemoryObject; +import br.unicamp.cst.core.entities.Mind; + /** * * @author rgudwin */ public class HabitExecutionerCodeletTest { - + double act; + long timeStep; + boolean publishSubscribe; + int exec_counter; + int proc_counter; + + Habit summer; + Habit decrementer; + Habit actSetter; + Habit timeStepSetter; + Habit publishSubscribeSetter; + Habit outputSetter; + Habit notExecuted; + Habit nullIdeaSetter; + Habit emptyIdeaSetter; + Mind m; MemoryContainer mc; MemoryObject moi; MemoryObject moo; + + Idea global_idea; - public HabitExecutionerCodeletTest() { + private void setUp() { + MockHabits mh = new MockHabits(); + summer = mh.summer; + decrementer = mh.decrementer; + m = new Mind(); - mc = m.createMemoryContainer("HabitsMemory"); + + mc = m.createMemoryContainer("testHabits"); Idea sh = new Idea("Summer"); sh.setValue(summer); sh.setScope(2); @@ -37,7 +61,7 @@ public HabitExecutionerCodeletTest() { mc.setI(dh); moi = m.createMemoryObject("InputIdeasMemory"); moo = m.createMemoryObject("OutputIdeasMemory"); - HabitExecutionerCodelet hec = new HabitExecutionerCodelet(); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); hec.addInput(mc); hec.addInput(moi); hec.addOutput(moo); @@ -45,42 +69,7 @@ public HabitExecutionerCodeletTest() { m.insertCodelet(hec); m.start(); } - - Habit summer = new Habit() { - @Override - public Idea exec(Idea idea) { - Idea adder = idea.get("value.add"); - int valuetoadd=0; - if (adder != null && adder.getValue() instanceof Integer) { - valuetoadd = (int) adder.getValue(); - } - if (idea.get("value").getValue() instanceof Integer) { - int number = (int) idea.get("value").getValue(); - Idea modifiedIdea = new Idea("incremented",number+valuetoadd); - return(modifiedIdea); - } - System.out.println("Something wrong happened"); - return(null); - } - }; - Habit decrementer = new Habit() { - @Override - public Idea exec(Idea idea) { - Idea adder = idea.get("value.add"); - int valuetodec=0; - if (adder != null && adder.getValue() instanceof Integer) { - valuetodec = (int) adder.getValue(); - } - if (idea.get("value").getValue() instanceof Integer) { - int number = (int) idea.get("value").getValue(); - Idea modifiedIdea = new Idea("decremented",number-valuetodec); - return(modifiedIdea); - } - System.out.println("Something wrong happened"); - return(null); - } - }; - + private void doTest() { Object oo; Random r = new Random(); @@ -127,7 +116,7 @@ private void doTest() { @Test public void testHabitExecutionerCodeletMAX() { - HabitExecutionerCodeletTest test = new HabitExecutionerCodeletTest(); + setUp(); mc.setPolicy(MemoryContainer.Policy.MAX); System.out.println("\nTesting the MAX Policy - Sums for < 50 Decs for > 50"); doTest(); @@ -135,7 +124,7 @@ public void testHabitExecutionerCodeletMAX() { @Test public void testHabitExecutionerCodeletMIN() { - HabitExecutionerCodeletTest test = new HabitExecutionerCodeletTest(); + setUp(); mc.setPolicy(MemoryContainer.Policy.MIN); System.out.println("\nTesting the MIN Policy - Sums for > 50 Decs for < 50"); doTest(); @@ -143,7 +132,7 @@ public void testHabitExecutionerCodeletMIN() { @Test public void testHabitExecutionerCodeletIterate() { - HabitExecutionerCodeletTest test = new HabitExecutionerCodeletTest(); + setUp(); mc.setPolicy(MemoryContainer.Policy.ITERATE); System.out.println("\nTesting the ITERATE Policy - Iterate Sums and Decs"); doTest(); @@ -151,10 +140,620 @@ public void testHabitExecutionerCodeletIterate() { @Test public void testHabitExecutionerCodeletRandom() { - HabitExecutionerCodeletTest test = new HabitExecutionerCodeletTest(); + setUp(); mc.setPolicy(MemoryContainer.Policy.RANDOM_FLAT); System.out.println("\nTesting the RANDOM_FLAT Policy - Sums and Decs at Random"); doTest(); } - -} + + @Test + public void testName() { + System.out.println("\nTesting Name Setting and Default Name"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet(); + assertEquals("Default", hec.getName()); + hec = new HabitExecutionerCodelet("MyName"); + assertEquals("MyName", hec.getName(), "Name should be MyName"); + } + + @Test + public void testActivation() { + System.out.println("\nTesting Activation Setting through Habits"); + + Random r = new Random(); + for (int k=0;k<100;k++) { + act = r.nextDouble(); + MockHabits mh = new MockHabits(); + actSetter = mh.actSetter; + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("Name"); + hec.h = actSetter; + hec.proc(); + + assertEquals(act, hec.getActivation(), "Activation should be " + act); + } + } + + @Test + public void testTimeStep() { + System.out.println("\nTesting TimeStep Setting through Habits"); + + Random r = new Random(); + for (int k=0;k<100;k++) { + timeStep = r.nextInt(1000); + MockHabits mh = new MockHabits(); + timeStepSetter = mh.timeStepSetter; + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("Name"); + hec.h = timeStepSetter; + hec.proc(); + + assertEquals(timeStep, hec.getTimeStep(), "TimeStep should be " + timeStep); + } + + } + + @Test + public void testPublishSubscribe() { + System.out.println("\nTesting PublishSubscribe Setting through Habits"); + + MockHabits mh = new MockHabits(); + publishSubscribeSetter = mh.publishSubscribeSetter; + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("Name"); + hec.h = publishSubscribeSetter; + + publishSubscribe = true; + hec.proc(); + assertEquals(true, hec.isPublishSubscribe(), "PublishSubscribe should be true"); + + publishSubscribe = false; + hec.proc(); + assertEquals(false, hec.isPublishSubscribe(), "PublishSubscribe should be false"); + } + + @Test + public void testNoOutputMemory() { + System.out.println("\nTesting the case where there is no output memory"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + m.insertCodelet(hec); + m.start(); + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + } + + @Test + public void testNoHabitMemoryContainer() { + System.out.println("\nTesting the case where there is no habit memory container"); + + proc_counter = 0; + + m = new Mind(); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test") { + @Override + public void proc() { + proc_counter++; + super.proc(); + } + }; + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(proc_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertNull(hec.h, "The habit should be null"); + } + + @Test + public void testNoHabit() { + System.out.println("\nTesting the case where there is a habit memory container but no habit inside it"); + + proc_counter = 0; + + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test") { + @Override + public void proc() { + proc_counter++; + super.proc(); + } + }; + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(proc_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertNull(hec.h, "The habit should be null"); + } + + @Test + public void testHabitsContainerNameMatching() { + System.out.println("\nTesting the case where there is one Habit Memory Container with correct name"); + + String[] matchingNames = {"testHabits", "TESTHABITS", "TestHabits", "tEsThAbItS"}; + + for (String name : matchingNames) { + exec_counter = 0; + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer(name); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(outputSetter, hec.h, "Habit should be the same as the one set in the container with name: " + name); + } + } + + @Test + public void testHabitsContainerNameNotMatching() { + System.out.println("\nTesting the case where there is one Habit Memory Container with incorrect name"); + + String[] nonMatchingNames = {"someOtherName", "habitsTest", "test_habits", "testhabit"}; + + // Test non-matching names (should not find habit) + for (String name : nonMatchingNames) { + System.out.println("\nTesting with container name: " + name); + + proc_counter = 0; + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer(name); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test") { + @Override + public void proc() { + proc_counter++; + super.proc(); + } + }; + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(proc_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertNull(hec.h, "Habit should be null for container name: " + name); + } + } + + // Test case for when there is one Habit Memory Container with correct name and one without + // In this case, the codelet should find the habit in the container with the correct name + // and add the other habit to the root idea, but not execute it + @Test + public void testDoubleHabitContainers() { + System.out.println("\nTesting the case where there are two habit memory containers, one with the correct name and one without"); + + proc_counter = 0; + m = new Mind(); + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + mc = m.createMemoryContainer("testHabits"); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + + notExecuted = mh.notExecuted; + MemoryContainer mc2 = m.createMemoryContainer("someOtherName"); + Idea neh = new Idea("NotExecuted"); + neh.setValue(notExecuted); + neh.setScope(2); + mc2.setI(neh); + + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test") { + @Override + public void proc() { + proc_counter++; + super.proc(); + } + }; + hec.addInput(mc); + hec.addInput(mc2); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(proc_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + + // Should find the habit in the container with the correct name + assertEquals(outputSetter, hec.h, "Habit should not be null for container with correct name"); + + Idea habit_input = global_idea.get("NotExecuted"); + // The other habit should be added to the root idea, but not executed + assertEquals(habit_input, neh, "The habit in the container with incorrect name should be added to the root idea"); + } + + @Test + public void testNullIdea() { + System.out.println("\nTesting the case where the habit returns a null idea"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + nullIdeaSetter = mh.nullIdeaSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea nish = new Idea("NullIdeaSetter"); + nish.setValue(nullIdeaSetter); + nish.setScope(2); + mc.setI(nish); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + } + + @Test + public void testEmptyIdea() { + System.out.println("\nTesting the case where the habit returns an empty idea"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + emptyIdeaSetter = mh.emptyIdeaSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea eish = new Idea("EmptyIdeaSetter"); + eish.setValue(emptyIdeaSetter); + eish.setScope(2); + mc.setI(eish); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + } + + @Test + public void testSettingIdeaMemoryObject() { + System.out.println("\nTesting the case where the habit sets an idea to an output memory object"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + moi = m.createMemoryObject("InputIdeasMemory"); + moo = m.createMemoryObject("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + + Object oo = moo.getI(); + if (oo != null) { + Idea ooi = (Idea) oo; + int val = (int) ooi.getValue(); + assertEquals(13, val, "The value set in the output memory object should be 13"); + } + else fail("The output memory object is null"); + } + + @Test + public void testSettingIdeaMemoryContainer() { + System.out.println("\nTesting the case where the habit sets an idea to an output memory container"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + moi = m.createMemoryObject("InputIdeasMemory"); + MemoryContainer moc = m.createMemoryContainer("OutputIdeasMemory"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moc); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + + Object oo = moc.getLastI(); + if (oo != null) { + Idea ooi = (Idea) oo; + int val = (int) ooi.getValue(); + assertEquals(13, val, "The value set in the output memory container should be 13"); + } + else fail("The output memory container is empty"); + } + + @Test + public void testSettingTwoIdeasTwoMemories() { + System.out.println("\nTesting the case where the habit sets two ideas to two output memories"); + + exec_counter = 0; + + MockHabits mh = new MockHabits(); + outputSetter = mh.outputSetter; + m = new Mind(); + mc = m.createMemoryContainer("testHabits"); + Idea osh = new Idea("OutputSetter"); + osh.setValue(outputSetter); + osh.setScope(2); + mc.setI(osh); + moi = m.createMemoryObject("InputIdeasMemory"); + MemoryContainer moc = m.createMemoryContainer("OutputIdeasMemory"); + moo = m.createMemoryObject("anotherIdea"); + HabitExecutionerCodelet hec = new HabitExecutionerCodelet("test"); + hec.addInput(mc); + hec.addInput(moi); + hec.addOutput(moc); + hec.addOutput(moo); + + m.insertCodelet(hec); + m.start(); + + try { + while(exec_counter < 5) { System.out.print("."); Thread.sleep(1); } + } catch (Exception e) { + fail("An error occurred: " + e.getMessage()); + } + assertEquals(5, exec_counter, "The habit should have been executed 5 times without errors"); + + Object oo = moc.getLastI(); + if (oo != null) { + Idea ooi = (Idea) oo; + int val = (int) ooi.getValue(); + assertEquals(13, val, "The value set in the first output memory container should be 13"); + } + else fail("The first output memory container is empty"); + + oo = moo.getI(); + if (oo != null) { + Idea ooi = (Idea) oo; + String val = (String) ooi.getValue(); + assertEquals("abc", val, "The value set in the second output memory object should be 'abc'"); + } + else fail("The second output memory object is null"); + } + + class MockHabits { + public MockHabits() { + } + + Habit summer = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + Idea adder = idea.get("value.add"); + int valuetoadd=0; + if (adder != null && adder.getValue() instanceof Integer) { + valuetoadd = (int) adder.getValue(); + } + if (idea.get("value").getValue() instanceof Integer) { + int number = (int) idea.get("value").getValue(); + Idea modifiedIdea = new Idea("OutputIdeasMemory",number+valuetoadd); + root.add(modifiedIdea); + return root; + } + System.out.println("Something wrong happened"); + return(null); + } + }; + + Habit decrementer = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + Idea adder = idea.get("value.add"); + int valuetodec=0; + if (adder != null && adder.getValue() instanceof Integer) { + valuetodec = (int) adder.getValue(); + } + if (idea.get("value").getValue() instanceof Integer) { + int number = (int) idea.get("value").getValue(); + Idea modifiedIdea = new Idea("OutputIdeasMemory",number-valuetodec); + root.add(modifiedIdea); + return root; + } + System.out.println("Something wrong happened"); + return(null); + } + }; + + Habit actSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + root.add(new Idea("activation", act)); + root.add(new Idea("someIdea", 123)); + root.add(new Idea("anotherIdea", "abc")); + return root; + } + }; + + Habit timeStepSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + root.add(new Idea("timeStep", timeStep)); + root.add(new Idea("someIdea", 123)); + root.add(new Idea("anotherIdea", "abc")); + return root; + } + }; + + Habit publishSubscribeSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + root.add(new Idea("publishSubscribe", publishSubscribe)); + root.add(new Idea("someIdea", 123)); + root.add(new Idea("anotherIdea", "abc")); + return root; + } + }; + + Habit outputSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + global_idea = idea; + + Idea root = new Idea("root", ""); + root.add(new Idea("someIdea", 123)); + root.add(new Idea("anotherIdea", "abc")); + root.add(new Idea("OutputIdeasMemory", 13)); + return root; + } + }; + + Habit notExecuted = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + Idea root = new Idea("root", ""); + root.add(new Idea("OutputIdeasMemory", 9999)); + return root; + } + }; + + Habit nullIdeaSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + return null; + } + }; + + Habit emptyIdeaSetter = new Habit() { + @Override + public Idea exec(Idea idea) { + exec_counter++; + + return new Idea("root", ""); + } + }; + } +} \ No newline at end of file