Showing posts with label Math Drill. Show all posts
Showing posts with label Math Drill. Show all posts

Thursday, May 20, 2010

IPAD Math: dynamic button display

I found that having the math buttons at the bottom of the screen for the proper choice was a poor UI choice.  It caused your eyes to travel from the problem to the buttons and back, slowing down the process.  I made a preliminary UI overlay that allows buttons to be dynamically displayed. This is not a final solution, it takes up too much screen real-estate however it was a good experiment with dynamic view overlays.

The only reason I'm showing this stage, is so that I can discuss the refactoring that will occur to create cleaner, more modular code.

I display a set of buttons around the problem being currently displayed. I made the buttons the same size as the problem, however that didn't allow enough choices, and takes up too much real estate.
In MathProblem I added a method that returns a list of possible choices for the math problem.  In this case it only returns 8 choices, which is based on the display method I'm using.   
- (NSMutableArray *)calculateChoices;

- (NSMutableArray *)calculateChoices
{
NSMutableArray *set=[[NSMutableArray alloc]init];
for (int i=0;i<9;i++)
{
if (i==correctResult)
continue;
[set addObject:[NSNumber numberWithInt:i]];
}
NSNumber *correctResultO=[NSNumber numberWithInt:correctResult];
    NSMutableSet *returnValues=[[NSMutableSet alloc]init];
[returnValues addObject:correctResultO];
for (int i=0;i<7;i++)
{
int randomalue=arc4random()%[set count];
NSNumber * value=(NSNumber *)[set objectAtIndex:randomalue];
[set removeObject:value];
[returnValues addObject:value];
}
[set release];
return [returnValues autorelease];
}

Next I refactored the MathDrillViewController to have some additional properties, and methods to handle displaying a set of selections:
@property (nonatomic,retain) UIView *choiceView;

and I modified the set problem choice to display the dialog.


- (void) setProblemNumber:(int) problemNumber
{
NSLog(@"Choosing problem %d",problemNumber);
if ((currentProblem>=0) && (currentProblem<=[currentProblems count]))
{
MathProblem *oldProblem=(MathProblem*)[currentProblems objectAtIndex:currentProblem];
if (choiceView!=nil)
{
[choiceView removeFromSuperview];
self.choiceView=nil;
}

oldProblem.view.alpha=0.5;
}
currentProblem=problemNumber;
MathProblem *problem=(MathProblem*)[currentProblems objectAtIndex:currentProblem];
problem.view.alpha=1;
int width=problem.view.frame.size.width;
int height=problem.view.frame.size.height;
self.choiceView =[[UIView alloc] initWithFrame:CGRectMake(problem.view.frame.origin.x-width, problem.view.frame.origin.y-height,
  problem.view.frame.size.width*3, problem.view.frame.size.height*3)];
self.choiceView.center=problem.view.center;
[self.displayArea addSubview:choiceView];

choiceView.backgroundColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:0];
NSMutableArray *choices=problem.resultChoices;
int row=0;
int column=0;
for (NSNumber *value in choices)
{
if ((row==1) &&(column==1))
column++;
UIButton *button=[[UIButton alloc]init] ;
button.tag=[value intValue]; 
button.frame=CGRectMake(column*width,height*row,width,height);
button.backgroundColor=[UIColor redColor];
button.userInteractionEnabled=true;
[button setTitle:[value stringValue] forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonChosen:) forControlEvents:UIControlEventTouchUpInside];
[self.choiceView addSubview:button];
column++;
if (column>=3)
{
column=0;
row++;
}
}

}

Originally I had the choiceView belong to the math problem view, but when I did that I didn't get button presses, and the alpha was picked up from the problem view (causing strange display  results).

Note the line:

choiceView.backgroundColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:0];
This set the background to be transparent, so that only the buttons are displayed.


Thursday, May 6, 2010

IPad Math: Fixing the code, and advancing through paths.

The next step is to make a progressive ability to represent the states of the items.  I've also added some highlighting ability.


  1. Modify the MathProblem class to have problemNumber property for which particular index of problems it is.
  2. Modify MathDrillViewController so that it has a currentProblem integer value, as well as an array of problems.
  3. Add a set problem method that sets the current problem

In this code segment the setProblemNumber will find the previous problem and reset it's alpha to 0.5.  It then set the current problem and changes the alpha to 1.  Note that I need to refractor this code a bit.
- (void) setProblemNumber:(int) problemNumber
{
NSLog(@"Choosing problem %d",problemNumber);
if ((currentProblem>=0) && (currentProblem<=[currentProblems count]))
{
MathProblem *oldProblem=(MathProblem*)[currentProblems objectAtIndex:currentProblem];

oldProblem.view.alpha=0.5;
}
currentProblem=problemNumber;
MathProblem *problem=(MathProblem*)[currentProblems objectAtIndex:currentProblem];
problem.view.alpha=1;
}


In this code segment I modified the math problem creation to load an array, and set the alpha to 0.5
- (void)viewDidLoad {
    [super viewDidLoad];
int width=self.view.frame.size.width/6;
int height=(self.view.frame.size.height-100)/5;

currentProblems=[[NSMutableArray alloc]init];
for (int row=0;row<5;row++)
{
for (int column=0;column<6;column++)
{
MathProblem *problem=[[MathProblem alloc] initWithMax:10];
problem.problemNumber=row*6+column;
problem.view.alpha=0.5;
[self.currentProblems addObject:problem];

problem.view.frame=CGRectMake(column*width, height*row, width, height);
problem.controller=self;
// problem.view.frame=CGRectMake(40, 40, 100, 100);
[self.view addSubview:problem.view];
}
}

int buttonWidth=resultChoices.frame.size.width/10;
int buttonHeight=resultChoices.frame.size.height;
resultChoices.userInteractionEnabled=true;
self.view.userInteractionEnabled=true;
 
for (int i=0;i<10;i++)
{
UIButton *button=[[[UIButton alloc]init] retain];
button.tag=i;
button.frame=CGRectMake(i*buttonWidth,buttonHeight+resultChoices.frame.origin.y,buttonWidth,buttonHeight);
button.backgroundColor=[UIColor redColor];
button.userInteractionEnabled=true;
[button setTitle:[NSString stringWithFormat:@"%d",i] forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonChosen:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
}


In this code segment I change the behavior of the select a number to increment to the next problem.



- (IBAction) buttonChosen:(id)sender
{
UIButton *button=(UIButton*) sender;
int choice=button.tag;
if ((currentProblem>=0) && (currentProblem<= [currentProblems count]))
{
MathProblem *problem=(MathProblem*)[currentProblems objectAtIndex:currentProblem];

[problem setChoice:choice];
NSLog(@"setting choice to %d",choice);

[self setProblemNumber:(currentProblem+1)%([currentProblems count])];
}
}