Skip to content

Commit c344469

Browse files
authored
Merge pull request #160 from RoboTutorLLC/development
Merge Development to branch
2 parents 3c5b48e + 76bc390 commit c344469

6 files changed

Lines changed: 445 additions & 40 deletions

File tree

app/src/main/java/cmu/xprize/robotutor/tutorengine/util/CycleMatrixActivityMenu.java

Lines changed: 206 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,26 @@ public class CycleMatrixActivityMenu implements IActivityMenu {
3636

3737
TransitionMatrixModel _matrix;
3838
IStudentDataModel _student;
39+
PromotionMechanism _promotionMechanism;
40+
private static final int MIN_NUM_ATTEMPTS = 3;
3941

4042
public CycleMatrixActivityMenu(TransitionMatrixModel matrix, IStudentDataModel student) {
4143
this._matrix = matrix;
4244
this._student = student;
45+
this._promotionMechanism = new PromotionMechanism(this._student, this._matrix);
4346
}
4447

4548
@Override
4649
public String getLayoutName() {
47-
return "ask_activity_selector_2x2";
50+
if(this._promotionMechanism.performance.getNumberAttempts() >= MIN_NUM_ATTEMPTS
51+
&&
52+
this._promotionMechanism.performance.getTotalNumberQuestions() >= 3
53+
&&
54+
this._promotionMechanism.performance.getNumberCorrect() / this._promotionMechanism.performance.getNumberAttempts() > PlacementPromotionRules.HIGH_PERFORMANCE_THRESHOLD
55+
)
56+
return "ask_activity_selector_2x2_elevate";
57+
else
58+
return "ask_activity_selector_2x2";
4859
}
4960

5061
@Override
@@ -100,9 +111,62 @@ public CAt_Data[] getTutorsToShow() {
100111
Log.e("SUPER_PLACEMENT", "not ready yet");
101112
nextTutors[0] = (CAt_Data) transitionMap.get(tutorId);
102113
nextTutors[1] = nextTutors[0];
114+
115+
// Add null check for nextTutors[0]
116+
if (nextTutors[0] == null) {
117+
Log.e(MENU_BUG_TAG, "Could not find tutor with ID: " + tutorId + " in placement mode");
118+
// Try to get root tutor as fallback
119+
String rootTutor = "";
120+
switch(_student.getActiveSkill()) {
121+
case SELECT_WRITING:
122+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_WRITING);
123+
break;
124+
case SELECT_STORIES:
125+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_STORIES);
126+
break;
127+
case SELECT_MATH:
128+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_MATH);
129+
break;
130+
}
131+
nextTutors[0] = (CAt_Data) transitionMap.get(rootTutor);
132+
nextTutors[1] = nextTutors[0];
133+
}
103134
} else {
104135
nextTutors[0] = (CAt_Data) transitionMap.get(tutorId); // N
105-
nextTutors[1] = isPlacementMode ? nextTutors[0] : (CAt_Data) transitionMap.get(nextTutors[0].next); // N or N + 1
136+
137+
// Add null checking here
138+
if (nextTutors[0] != null && nextTutors[0].next != null) {
139+
CAt_Data nextTutor = (CAt_Data) transitionMap.get(nextTutors[0].next);
140+
nextTutors[1] = isPlacementMode ? nextTutors[0] : nextTutor;
141+
142+
// Add null check for nextTutors[1]
143+
if (nextTutors[1] == null) {
144+
nextTutors[1] = nextTutors[0]; // Use the same tutor if next is null
145+
Log.e(MENU_BUG_TAG, "Next tutor is null, using same tutor twice: " + tutorId);
146+
}
147+
} else {
148+
// If there's no valid next tutor, use the same tutor twice
149+
if (nextTutors[0] == null) {
150+
Log.e(MENU_BUG_TAG, "Current tutor is null for ID: " + tutorId);
151+
// Try to get root tutor as fallback
152+
String rootTutor = "";
153+
switch(_student.getActiveSkill()) {
154+
case SELECT_WRITING:
155+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_WRITING);
156+
break;
157+
case SELECT_STORIES:
158+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_STORIES);
159+
break;
160+
case SELECT_MATH:
161+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_MATH);
162+
break;
163+
}
164+
nextTutors[0] = (CAt_Data) transitionMap.get(rootTutor);
165+
}
166+
167+
nextTutors[1] = nextTutors[0];
168+
Log.d(MENU_BUG_TAG, "No next tutor available, using the same tutor twice");
169+
}
106170
}
107171

108172
return nextTutors;
@@ -143,10 +207,22 @@ public CAsk_Data initializeActiveLayout() {
143207
activeLayout.items[1].help = "something different";
144208

145209
activeLayout.items[2] = new CAskElement();
146-
activeLayout.items[2].componentID = "SbuttonRepeat";
147-
activeLayout.items[2].behavior = AS_CONST.SELECT_REPEAT;
148-
activeLayout.items[2].prompt = "lets do it again";
149-
activeLayout.items[2].help = "lets do it again";
210+
if(this._promotionMechanism.performance.getNumberAttempts() >= MIN_NUM_ATTEMPTS
211+
&&
212+
this._promotionMechanism.performance.getTotalNumberQuestions() >= 3
213+
&&
214+
this._promotionMechanism.performance.getNumberCorrect() / this._promotionMechanism.performance.getNumberAttempts() > PlacementPromotionRules.HIGH_PERFORMANCE_THRESHOLD){
215+
activeLayout.items[2].componentID = "Sbutton1";
216+
activeLayout.items[2].behavior = AS_CONST.ELEVATE;
217+
activeLayout.items[2].prompt = "I want something harder";
218+
activeLayout.items[2].help = "something harder";
219+
}
220+
else{
221+
activeLayout.items[2].componentID = "SbuttonRepeat";
222+
activeLayout.items[2].behavior = AS_CONST.SELECT_REPEAT;
223+
activeLayout.items[2].prompt = "lets do it again";
224+
activeLayout.items[2].help = "lets do it again";
225+
}
150226

151227
activeLayout.items[3] = new CAskElement();
152228
activeLayout.items[3].componentID = "SbuttonExit";
@@ -163,7 +239,18 @@ public Map<String, String> getButtonBehaviorMap() {
163239

164240
map.put(SELECT_OPTION_0, AS_CONST.QUEUEMAP_KEYS.BUTTON_BEHAVIOR);
165241
map.put(SELECT_OPTION_1, AS_CONST.QUEUEMAP_KEYS.BUTTON_BEHAVIOR);
166-
map.put(AS_CONST.SELECT_REPEAT, AS_CONST.QUEUEMAP_KEYS.BUTTON_BEHAVIOR);
242+
243+
if(this._promotionMechanism.performance.getNumberAttempts() >= MIN_NUM_ATTEMPTS
244+
&&
245+
this._promotionMechanism.performance.getTotalNumberQuestions() >= 3
246+
&&
247+
this._promotionMechanism.performance.getNumberCorrect() / this._promotionMechanism.performance.getNumberAttempts() > PlacementPromotionRules.HIGH_PERFORMANCE_THRESHOLD){
248+
map.put(AS_CONST.ELEVATE, AS_CONST.QUEUEMAP_KEYS.BUTTON_BEHAVIOR);
249+
}
250+
else{
251+
map.put(AS_CONST.SELECT_REPEAT, AS_CONST.QUEUEMAP_KEYS.BUTTON_BEHAVIOR);
252+
}
253+
167254
map.put(AS_CONST.SELECT_EXIT, AS_CONST.QUEUEMAP_KEYS.EXIT_BUTTON_BEHAVIOR);
168255
return map;
169256
}
@@ -177,7 +264,7 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
177264
String rootTutor = "";
178265

179266
String activeSkill = null;
180-
String chosenTutorId;
267+
String chosenTutorId = null;
181268

182269
Log.d("OH_BEHAVE", "some behavior here should be different...");
183270

@@ -189,12 +276,49 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
189276
transitionMap = _matrix.getTransitionMapByContentArea(activeSkill);
190277
rootTutor = _matrix.getRootSkillByContentArea(activeSkill);
191278
RoboTutor.logManager.postEvent_I(REPEAT_DEBUG_TAG, String.format("activeSkill=%s;chosenTutorId=%s;transitionMap=%s;rootTutor=%s", activeSkill, chosenTutorId, activeSkill, rootTutor));
279+
}
280+
else if (buttonBehavior.equals(AS_CONST.ELEVATE)) {
281+
activeSkill = _student.getLastSkill();
282+
transitionMap = _matrix.getTransitionMapByContentArea(activeSkill);
283+
chosenTutorId = _student.getLastTutor();
192284

285+
if(activeSkill != null) {
286+
// If the last activity is not null then go to that activity but update the placement index by 1
287+
if(activeSkill.equals(SELECT_MATH)) {
288+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_MATH);
289+
CAt_Data transitionData = (CAt_Data) transitionMap.get(chosenTutorId);
290+
if (transitionData != null && transitionData.harder != null) {
291+
chosenTutorId = transitionData.harder;
292+
} else {
293+
// If no harder level available, stay at current level
294+
Log.e(MENU_BUG_TAG, "No harder math level available for " + chosenTutorId);
295+
}
296+
}
297+
else if(activeSkill.equals(SELECT_WRITING)) {
298+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_WRITING);
299+
CAt_Data transitionData = (CAt_Data) transitionMap.get(chosenTutorId);
300+
if (transitionData != null && transitionData.harder != null) {
301+
chosenTutorId = transitionData.harder;
302+
} else {
303+
// If no harder level available, stay at current level
304+
Log.e(MENU_BUG_TAG, "No harder writing level available for " + chosenTutorId);
305+
}
306+
}
307+
else if(activeSkill.equals(SELECT_STORIES)) {
308+
rootTutor = _matrix.getRootSkillByContentArea(SELECT_STORIES);
309+
CAt_Data transitionData = (CAt_Data) transitionMap.get(chosenTutorId);
310+
if (transitionData != null && transitionData.harder != null) {
311+
chosenTutorId = transitionData.harder;
312+
} else {
313+
// If no harder level available for stories, stay at current level
314+
Log.e(MENU_BUG_TAG, "No harder stories level available for " + chosenTutorId);
315+
}
316+
}
317+
}
193318
} else {
194-
195319
activeSkill = _student.getActiveSkill();
196320
CAt_Data zeroIndexedTutor;
197-
String[] nextTutors = new String[3];
321+
String[] nextTutorIds = new String[3];
198322

199323
boolean inPlacementMode = false;
200324

@@ -207,6 +331,11 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
207331

208332
case SELECT_STORIES:
209333
zeroIndexedTutorId = _student.getStoryTutorID();
334+
if (zeroIndexedTutorId == null) {
335+
// If story tutor ID is null, get the root story tutor
336+
zeroIndexedTutorId = _matrix.getRootSkillByContentArea(SELECT_STORIES);
337+
Log.e(MENU_BUG_TAG, "Story tutor ID was null, falling back to root: " + zeroIndexedTutorId);
338+
}
210339
Log.d("REPEAT_ME", "storyTutor=" + zeroIndexedTutorId);
211340
break;
212341

@@ -221,26 +350,79 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
221350
RoboTutor.logManager.postEvent_I(MENU_BUG_TAG, "CycleMatrixActivityMenu: activeSkill=" + activeSkill + " -- activeTutorId=" + zeroIndexedTutorId);
222351
transitionMap = _matrix.getTransitionMapByContentArea(activeSkill);
223352
rootTutor = _matrix.getRootSkillByContentArea(activeSkill);
353+
354+
// Additional safety for stories
355+
if (activeSkill != null && activeSkill.equals(SELECT_STORIES) && (transitionMap == null || transitionMap.isEmpty())) {
356+
Log.e(MENU_BUG_TAG, "Story transition map is null or empty!");
357+
// Create a minimal transition map if none exists
358+
if (transitionMap == null) {
359+
transitionMap = new HashMap();
360+
}
361+
// Make sure the root tutor exists in the map
362+
if (rootTutor != null && !transitionMap.containsKey(rootTutor)) {
363+
Log.e(MENU_BUG_TAG, "Adding root story tutor to map as fallback: " + rootTutor);
364+
CAt_Data rootData = new CAt_Data();
365+
rootData.tutor_id = rootTutor;
366+
rootData.next = rootTutor; // Point to itself as fallback
367+
rootData.same = rootTutor;
368+
transitionMap.put(rootTutor, rootData);
369+
}
370+
}
371+
224372
zeroIndexedTutor = (CAt_Data) transitionMap.get(zeroIndexedTutorId);
225-
nextTutors[0] = zeroIndexedTutor.tutor_id;
226-
nextTutors[1] = inPlacementMode ? nextTutors[0] : ((CAt_Data) transitionMap.get(zeroIndexedTutor.next)).tutor_id; // next hardest tutor!!! (I don't know WHY this is implemented twice)
373+
374+
if (zeroIndexedTutor != null) {
375+
nextTutorIds[0] = zeroIndexedTutor.tutor_id;
376+
377+
if (zeroIndexedTutor.next != null) {
378+
CAt_Data nextTutor = (CAt_Data) transitionMap.get(zeroIndexedTutor.next);
379+
nextTutorIds[1] = inPlacementMode ? nextTutorIds[0] : (nextTutor != null ? nextTutor.tutor_id : nextTutorIds[0]);
380+
381+
// Initialize nextTutorIds[2] to prevent null when SELECT_OPTION_2 is used
382+
if (nextTutor != null && nextTutor.next != null) {
383+
CAt_Data nextNextTutor = (CAt_Data) transitionMap.get(nextTutor.next);
384+
nextTutorIds[2] = nextNextTutor != null ? nextNextTutor.tutor_id : nextTutorIds[1];
385+
} else {
386+
nextTutorIds[2] = nextTutorIds[1]; // Use previous tutor if no "next next" is available
387+
}
388+
} else {
389+
nextTutorIds[1] = nextTutorIds[0];
390+
nextTutorIds[2] = nextTutorIds[0]; // Initialize index 2 as well
391+
Log.d(MENU_BUG_TAG, "No next tutor defined, using the same tutor twice");
392+
}
393+
} else {
394+
// Handle case where zeroIndexedTutor is null
395+
Log.e(MENU_BUG_TAG, "Could not find tutor with ID: " + zeroIndexedTutorId);
396+
// Use root tutor as fallback
397+
CAt_Data rootTutorData = (CAt_Data) transitionMap.get(rootTutor);
398+
if (rootTutorData != null) {
399+
nextTutorIds[0] = rootTutorData.tutor_id;
400+
nextTutorIds[1] = rootTutorData.tutor_id;
401+
} else {
402+
// Critical error - no valid tutor found
403+
Log.e(MENU_BUG_TAG, "Critical error: No valid tutor found in transition map");
404+
// Set to null and handle later
405+
nextTutorIds[0] = null;
406+
nextTutorIds[1] = null;
407+
}
408+
}
227409

228410
switch(buttonBehavior.toUpperCase()) {
229411

230412
case SELECT_OPTION_0: // TRACE_PROMOTION looks good...
231-
chosenTutorId = nextTutors[0];
413+
chosenTutorId = nextTutorIds[0];
232414
break;
233415

234416
case SELECT_OPTION_1: // TRACE_PROMOTION looks good...
235417
// launch the next tutor
236418
// something like this...
237-
chosenTutorId = nextTutors[1];
419+
chosenTutorId = nextTutorIds[1];
238420

239421
break;
240422

241423
case SELECT_OPTION_2:
242424
// launch the next.next tutor
243-
chosenTutorId = nextTutors[2];
425+
chosenTutorId = nextTutorIds[2];
244426
break;
245427

246428
default:
@@ -250,7 +432,7 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
250432

251433
// If they choose the second option, update our position in thematrix //
252434
// will only be updated if SELECT_OPTION_1 or SELECT_OPTION_2 were selected //
253-
if (!chosenTutorId.equals(zeroIndexedTutorId)) {
435+
if (!chosenTutorId.equals(zeroIndexedTutorId) && !buttonBehavior.equals(AS_CONST.ELEVATE)) {
254436
switch (activeSkill) {
255437
case SELECT_WRITING:
256438
_student.updateWritingTutorID(chosenTutorId, true);
@@ -265,12 +447,18 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
265447
break;
266448
}
267449
}
268-
269450
}
270451

271452

272453
// TRACE_PROMOTION doesn't save tutorToLaunch when we choose the second option!!!
273454
// the next tutor to be launched
455+
456+
// Final check to ensure chosenTutorId is not null
457+
if (chosenTutorId == null) {
458+
Log.e(MENU_BUG_TAG, "Critical error: chosenTutorId is null, using root tutor as fallback");
459+
chosenTutorId = rootTutor;
460+
}
461+
274462
CAt_Data tutorToLaunch = (CAt_Data) transitionMap.get(chosenTutorId);
275463
Log.wtf(MENU_BUG_TAG, chosenTutorId + " " + activeSkill);
276464

@@ -292,4 +480,4 @@ public CAt_Data getTutorToLaunch(String buttonBehavior) {
292480
public String getDebugMenuSkill() {
293481
return RoboTutor.STUDENT_CHOSE_REPEAT ? _student.getLastSkill() : _student.getActiveSkill(); // DEBUG_MENU_LOGIC (x) lastSkill vs ActiveSkill...
294482
}
295-
}
483+
}

0 commit comments

Comments
 (0)