@@ -51,4 +51,234 @@ TEST_CASE("When only first task credit is on","[ony]"){
5151 }
5252 }
5353 }
54+ }
55+ // TODO: tasks -> Tasks for folder name and test name (Task.integration.test.cc)
56+ // MOVE program builder outside of WHEN to cut down replications
57+ // Move CPU cycles from THEN to WHEN
58+ TEST_CASE (" Task completion scoring and marking" , " [tasks]" ) {
59+ emp::Random random (1 );
60+ SymConfigSGP config;
61+ config.SEED (1 );
62+ config.MUTATION_RATE (0.0 );
63+ config.MUTATION_SIZE (0.002 );
64+ config.TRACK_PARENT_TASKS (1 );
65+ config.VT_TASK_MATCH (1 );
66+
67+ WHEN (" OnlyFirstTaskCredit is OFF" ) {
68+ config.ONLY_FIRST_TASK_CREDIT (0 );
69+ SGPWorld world (random, &config, LogicTasks);
70+
71+ // multiple tasks
72+ ProgramBuilder multi_task_program;
73+ multi_task_program.AddNot ();
74+ multi_task_program.AddNand ();
75+ multi_task_program.AddAnd ();
76+
77+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, multi_task_program.Build (100 ));
78+ world.AddOrgAt (host, 0 );
79+
80+ THEN (" Should receive score when task completed" ) {
81+ int initial_points = host->GetPoints ();
82+ host->GetCPU ().RunCPUStep (0 , 100 );
83+
84+ // Get points for alltasks
85+ REQUIRE (host->GetPoints () > initial_points);
86+ }
87+
88+ THEN (" Should mark task when task completed" ) {
89+ host->GetCPU ().RunCPUStep (0 , 100 );
90+
91+ // Check that tasks marked complete
92+ int tasks_completed = 0 ;
93+ for (int i = 0 ; i < CPU_BITSET_LENGTH ; i++) {
94+ tasks_completed += host->GetCPU ().state .tasks_performed ->Get (i);
95+ }
96+ REQUIRE (tasks_completed > 0 );
97+ }
98+ }
99+
100+ WHEN (" OnlyFirstTaskCredit is ON" ) {
101+ config.ONLY_FIRST_TASK_CREDIT (1 );
102+ SGPWorld world (random, &config, LogicTasks);
103+
104+ // Program with multiple tasks
105+ ProgramBuilder multi_task_program;
106+ multi_task_program.AddNot ();
107+ multi_task_program.AddNand ();
108+ multi_task_program.AddAnd ();
109+
110+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, multi_task_program.Build (100 ));
111+ world.AddOrgAt (host, 0 );
112+
113+ THEN (" Should receive score when task completed if it is first task" ) {
114+ int initial_points = host->GetPoints ();
115+ host->GetCPU ().RunCPUStep (0 , 100 );
116+
117+ // Points for first task only
118+ REQUIRE (host->GetPoints () == initial_points + 5 );
119+ }
120+
121+ THEN (" Should not receive score when task completed if it is not first task" ) {
122+ // First for first task
123+ host->GetCPU ().RunCPUStep (0 , 100 );
124+ int points_after_first = host->GetPoints (); // change points after task --> 10
125+
126+ // Second run (should not get points)
127+ host->GetCPU ().RunCPUStep (0 , 100 );
128+ REQUIRE (host->GetPoints () == points_after_first);
129+ }
130+
131+ THEN (" Should mark task completed when it is first task" ) {
132+ host->GetCPU ().RunCPUStep (0 , 100 );
133+
134+ // exactly one task is marked complete
135+ int tasks_completed = 0 ;
136+ for (int i = 0 ; i < CPU_BITSET_LENGTH ; i++) {
137+ tasks_completed += host->GetCPU ().state .tasks_performed ->Get (i);
138+ }
139+ REQUIRE (tasks_completed == 1 );
140+ }
141+
142+ THEN (" Should not mark task completed when it is not first task" ) {
143+ // First run
144+ host->GetCPU ().RunCPUStep (0 , 100 );
145+ int tasks_completed_first = 0 ;
146+ for (int i = 0 ; i < CPU_BITSET_LENGTH ; i++) {
147+ tasks_completed_first += host->GetCPU ().state .tasks_performed ->Get (i);
148+ }
149+
150+ // Second run (should not mark any tasks)
151+ host->GetCPU ().RunCPUStep (0 , 100 );
152+ int tasks_completed_second = 0 ;
153+ for (int i = 0 ; i < CPU_BITSET_LENGTH ; i++) {
154+ tasks_completed_second += host->GetCPU ().state .tasks_performed ->Get (i);
155+ }
156+
157+ REQUIRE (tasks_completed_second == tasks_completed_first);
158+ }
159+ }
160+ }
161+
162+ TEST_CASE (" IsOnlyTask functionality" , " [tasks]" ) {
163+ emp::Random random (1 );
164+ SymConfigSGP config;
165+ config.SEED (1 );
166+ config.MUTATION_RATE (0.0 );
167+ config.MUTATION_SIZE (0.002 );
168+ config.TRACK_PARENT_TASKS (1 );
169+ config.VT_TASK_MATCH (1 );
170+ config.ONLY_FIRST_TASK_CREDIT (1 );
171+
172+ SGPWorld world (random, &config, LogicTasks);
173+
174+ WHEN (" No tasks have been completed yet" ) {
175+ ProgramBuilder multi_task_program;
176+ multi_task_program.AddNot ();
177+ multi_task_program.AddNand ();
178+
179+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, multi_task_program.Build (100 ));
180+ world.AddOrgAt (host, 0 );
181+
182+ THEN (" IsOnlyTask should return true for first task" ) {
183+ // Simulate completing the first task (NOT)
184+ host->GetCPU ().state .tasks_performed ->Set (0 ); // Mark NOT as completed
185+
186+ // Create a non const copy of LogicTasks for testing
187+ TaskSet test_tasks = LogicTasks;
188+ bool is_only = test_tasks.IsOnlyTask (host->GetCPU ().state , 0 );
189+ REQUIRE (is_only == true );
190+ }
191+ }
192+
193+ WHEN (" One task has already been completed" ) {
194+ ProgramBuilder multi_task_program;
195+ multi_task_program.AddNot ();
196+ multi_task_program.AddNand ();
197+
198+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, multi_task_program.Build (100 ));
199+ world.AddOrgAt (host, 0 );
200+
201+ THEN (" IsOnlyTask should return false for second task" ) {
202+ // Mark first task as completed
203+ host->GetCPU ().state .tasks_performed ->Set (0 ); // NOT completed
204+
205+ // Create a non const copy of LogicTasks for testing
206+ TaskSet test_tasks = LogicTasks;
207+ // Check if second task NAND is the only task
208+ bool is_only = test_tasks.IsOnlyTask (host->GetCPU ().state , 1 );
209+ REQUIRE (is_only == false );
210+ }
211+
212+ THEN (" IsOnlyTask should return true for the first completed task" ) {
213+ // Mark first task as completed
214+ host->GetCPU ().state .tasks_performed ->Set (0 ); // NOT completed
215+
216+ // Create a non const copy of LogicTasks for testing
217+ TaskSet test_tasks = LogicTasks;
218+ // Check if first task is the only task
219+ bool is_only = test_tasks.IsOnlyTask (host->GetCPU ().state , 0 );
220+ REQUIRE (is_only == true );
221+ }
222+ }
223+
224+ WHEN (" Multiple tasks have been completed" ) {
225+ ProgramBuilder multi_task_program;
226+ multi_task_program.AddNot ();
227+ multi_task_program.AddNand ();
228+ multi_task_program.AddAnd ();
229+
230+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, multi_task_program.Build (100 ));
231+ world.AddOrgAt (host, 0 );
232+
233+ THEN (" IsOnlyTask should return false for any task" ) {
234+ // Mark multiple tasks
235+ host->GetCPU ().state .tasks_performed ->Set (0 );
236+ host->GetCPU ().state .tasks_performed ->Set (1 );
237+
238+ // Create a non const copy of LogicTasks for testing
239+ TaskSet test_tasks = LogicTasks;
240+ // Check if any task is the only task
241+ bool is_only_not = test_tasks.IsOnlyTask (host->GetCPU ().state , 0 );
242+ bool is_only_nand = test_tasks.IsOnlyTask (host->GetCPU ().state , 1 );
243+ bool is_only_and = test_tasks.IsOnlyTask (host->GetCPU ().state , 2 );
244+
245+ REQUIRE (is_only_not == false );
246+ REQUIRE (is_only_nand == false );
247+ REQUIRE (is_only_and == false );
248+ }
249+ }
250+ }
251+
252+ TEST_CASE (" Task completion edge cases" , " [tasks]" ) { // IsSolved Edge casses documentation
253+ emp::Random random (1 );
254+ SymConfigSGP config;
255+ config.SEED (1 );
256+ config.MUTATION_RATE (0.0 );
257+ config.MUTATION_SIZE (0.002 );
258+ config.TRACK_PARENT_TASKS (1 );
259+ config.VT_TASK_MATCH (1 );
260+ config.ONLY_FIRST_TASK_CREDIT (0 );
261+
262+ SGPWorld world (random, &config, LogicTasks);
263+
264+ WHEN (" Testing output values of 0 and 1" ) {
265+ ProgramBuilder not_program;
266+ not_program.AddNot ();
267+
268+ emp::Ptr<SGPHost> host = emp::NewPtr<SGPHost>(&random, &world, &config, not_program.Build (100 ));
269+ world.AddOrgAt (host, 0 );
270+
271+ THEN (" Outputs of 0 and 1 should not be considered valid task completions" ) {
272+ // Create a NOT task to test with
273+ Task not_task (" NOT" , 1 , 5.0 , [](auto &x) { return ~x[0 ]; });
274+
275+ // Test with output 0
276+ bool is_solved_0 = not_task.IsSolved (host->GetCPU ().state , 0 );
277+ REQUIRE (is_solved_0 == false );
278+
279+ // Test with output 1
280+ bool is_solved_1 = not_task.IsSolved (host->GetCPU ().state , 1 );
281+ REQUIRE (is_solved_1 == false );
282+ }
283+ }
54284}
0 commit comments