Tuesday, October 4, 2011

Resetting the numbers at the end of the quiz!

Ok, just a quick-hitter. I'm going to change the logic to handle coming to the end of the list of vocabulary words. Let's take a look at the Android app. Weird - can't find it. I know it's there.

Ah, here it is - in NextLevelActivity:

// check for last quiz number
boolean wasResetToBeginning = appState
.incrementQuizStartAndFinish(this);


if (wasResetToBeginning) {
text = "Congratulations - you have completed the quiz! Resetting to start";
}


Ok, this code obviously goes in the iPhone version of the NextLevel - NextLevelViewController.

Here's what we have now:

// increment the quiz range by the difference between start and end
[Utils incrementQuizRange];


Let's go back and look at the Android app procedure:


public boolean incrementQuizStartAndFinish(Context context) {

boolean wasResetToBeginning = false;
int numQuestionsInQuiz = quizEndNum - quizStartNum + 1;
quizStartNum = quizEndNum + 1;
quizEndNum = quizStartNum + numQuestionsInQuiz - 1;

int lastNum = Utils.getLastWordNumber(context, this.jlptLevel);

if (quizStartNum > lastNum) {
this.quizStartNum = 1;
this.quizEndNum = numQuestionsInQuiz - 1;
wasResetToBeginning = true;
}

InitUtils.saveState(context);
return wasResetToBeginning;
}


Yes, I like that code. Good old logic.

Ok, let's see what we currently have for the iPhone:

+ (void) incrementQuizRange {

NSInteger startNum = [Utils getStartNum];
NSInteger endNum = [Utils getEndNum];
NSInteger diff = endNum - startNum;

startNum = endNum + 1;
endNum = endNum + diff + 1;

[Utils setStartNum: startNum];
[Utils setEndNum: endNum];

}



So, the first thing I need to do is get a method comparable to this:


int lastNum = Utils.getLastWordNumber(context, this.jlptLevel);


That method looks like this:

static int getLastWordNumber(Context context, int inputLevel) {

DataBaseHelper dbHelper;
dbHelper = DataBaseHelper.createDB(context);

int lastNum = dbHelper.getLevelCount(inputLevel);

dbHelper.close();

return lastNum;
}


Here's getLevelCount:

public int getLevelCount(int level) {

ArrayList rows = null;

rows = selectByLevel(level);

return rows.size();


}

Ok, so let's add this to the Utils:

+ (NSInteger *) getLastWordNum:(NSInteger) jlptLevel;

Ok, this is a little different because I have a common_select method that's sticking all the answers into AppState, which I don't want. I maybe can add a boolean saying whether or not do do that, but the Android implementation is cleaner because it just returns an array.

Ok, I just need to add this method:

- (void) common_select: (NSString *) querySQL statement: (sqlite3_stmt *) statement cntr_question: (int) cntr_question {

[self common_select: querySQL statement: statement cntr_question: cntr_question add_to_app_state: YES];

}


Ok, here's the method. I'm not happy about the way it worked out. I swear to the ends of the earth I'll refactor this to return an NSArray. It will be beautiful.



So, I don't have to change the current calling code. I had a little trouble remembering that the method call needs to be defined after the called method. Also, these should all be static methods. I'll refactor that later.

Ok, here's how the method is called:


MyDatabaseReader *myDatabaseReader = [[MyDatabaseReader alloc] init];

NSInteger jlptLevel = [Utils getJlptLevel];

[myDatabaseReader selectByLevel:jlptLevel];


Hmph - all I really needed to do was return an NSArray.

Ok, here's the code to get the count. It's really the same as select all by level without the row count returned, and the app state update set to no.

-(NSInteger) getLastWordNum:(NSInteger) level
{
const char *dbpath = [databasePath UTF8String];

sqlite3_stmt *statement;

if (sqlite3_open(dbpath, &jlptDB) == SQLITE_OK)
{
int cntr_question = 0;

NSLog(@"getLastWordNum, open ok");


NSString *querySQL = [NSString stringWithFormat: @"SELECT kanji, hiragana, english FROM v_all_words_by_level_freq_sequence WHERE level = %d; order by level, number", level];

int rowCount = [self common_select: querySQL statement: statement cntr_question: cntr_question add_to_app_state: NO];

sqlite3_close(jlptDB);
return rowCount;
}
else {
NSLog(@"select all, open failed");
return 0;
}
}


Ok, let's keep moving. I've got the Utils method set up. Ok, all I have to do now is update the utils to indicate if it hit the last method.

Ok, this is the Utils method now:

+ (BOOL) incrementQuizRange {

BOOL wasResetToBeginning = NO;

NSInteger startNum = [Utils getStartNum];
NSInteger endNum = [Utils getEndNum];
NSInteger diff = endNum - startNum;

int jlptLevel = [Utils getJlptLevel];

MyDatabaseReader *myDatabaseReader = [[MyDatabaseReader alloc] init];

int lastNum = [myDatabaseReader getLastWordNum:jlptLevel];
//int lastNum = Utils.getLastWordNumber(context, this.jlptLevel

[myDatabaseReader release];


startNum = endNum + 1;
endNum = endNum + diff + 1;

if (startNum > lastNum) {
startNum = 1;
endNum = diff - 1;
wasResetToBeginning = YES;
}



[Utils setStartNum: startNum];
[Utils setEndNum: endNum];

return wasResetToBeginning;
}


No problems there.

Ok, now, at last, back to the NextLevelViewController.

Set up a connection to the message on the nib as a UILabel/IBOutlet.

And try this code out:

// increment the quiz range by the difference between start and end
BOOL wasResetToBeginning = [Utils incrementQuizRange];

if (wasResetToBeginning) {
self.congratMessage.text = @"You have completed all the words - restarting!";
}
else {
self.congratMessage.text = @"You have advanced to the next level!";
}


Oops, got this message:

setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key congratMessage.'


Ah, spelling:

// increment the quiz range by the difference between start and end
BOOL wasResetToBeginning = [Utils incrementQuizRange];

if (wasResetToBeginning) {
self.congratMessage.text = @"You have completed all the words - restarting!";
}
else {
self.congratMessage.text = @"You have advanced to the next level!";
}



And the synthesize - and change the nib.

Ok, now that's working. Now, let's get near the end.

Ah, as I suspected. A crash.

Ok, as it turns out, I must not have carried the math over correctly.

This works, but needs more testing:


+ (BOOL) incrementQuizRange {

BOOL wasResetToBeginning = NO;

MyDatabaseReader *myDatabaseReader = [[MyDatabaseReader alloc] init];

int jlptLevel = [Utils getJlptLevel];

int lastNum = [myDatabaseReader getLastWordNum:jlptLevel];
//int lastNum = Utils.getLastWordNumber(context, this.jlptLevel

[myDatabaseReader release];


NSInteger startNum = [Utils getStartNum];
NSInteger endNum = [Utils getEndNum];
int numQuestionsInQuiz = endNum - startNum + 1;


startNum = endNum + 1;
endNum = startNum + numQuestionsInQuiz - 1;

if (startNum > lastNum) {
startNum = 1;
endNum = numQuestionsInQuiz;
wasResetToBeginning = YES;
}


[Utils setStartNum: startNum];
[Utils setEndNum: endNum];

return wasResetToBeginning;
}

No comments:

Post a Comment