Sunday, July 24, 2011

Class Definition - Queue

Now we get into something a bit more interesting. It is time to create the queue class that will be used to store the Category and Question objects that will comprise the parsed XML file (or SQLite DB entries).


This will also serve as a quick tutorial on how to use Java generic types. A generic type is basically like having a variable Object type for your class. This may sound a bit confusing, but they are fairly simple to use. The code for this class will illustrate this. Namely, you will see this:


public class Queue

This says, "this is a Queue which stores items T which extends (or implements) Comparable." To create an instance of this class, you would do as was done in the Category class.


Queue questions = new Queue();

This ensures that every Object in "questions" is a Question Object. To see how to build the rest of the class using the variable T, see the code below.

Since this class is going to be used as a queue, we will build it as a FIFO structure (first item in is the first item out). It will have a enqueue(x) method which adds new items to the back of the queue and a dequeue() method which returns the item from the front of the queue (think of it as, "next please!"). We will also add some other methods for retrieving data from the queue such as a get() method which will return the item from the front of the queue without removing it, a getLast() method which will do the same for the last, a getByIndex(i) method, and a getByString(s) method. Finally, a getLength() method will tell how many items are in the queue. The class also contains a private class called TNode which will simply store an Object of type T and a link to the next item in the queue (think of it as holding hands and looking backwards (can't see whats in front)).




@SuppressWarnings("rawtypes")
public class Queue <T extends Comparable>
{
/*** Description ***
* FIFO list of items of type T. 
* Held together by private class TNode
* Items are added to the back of the list and pulled from the front

***  Variables ***
* #root - The first item in the list
* #end - The last item in the list
* #length - The number of items in the list

*** Methods *** 

* #Constructor - No argument. Initializes all variables to default values. 
* #push - add item of type T to the end of the list.
* #pop  - remove item of type T from the front of the list.
* #get  - get item of type T from the front of the list (without removing)
* #getFromIndex - get the nth item from the list
* #getByValue - find a node which matches the passed argument of type T.

*** Classes ***
*
* TNode
*/
protected TNode root;
protected TNode end; 

int length;

public Queue()
{
this.root = null;
this.end = null;
this.length = 0;
}

public void enqueue(T item)
{
TNode newNode = new TNode(item);
if (root == null)
{
root = newNode;
}
else
{
end.next = newNode;
}
end = newNode;
length++;
}

public T dequeue()
{
T returnVal;

if (root == null)
return null;

returnVal = root.get();
root = root.next;

length --;
return returnVal;
}

public T get()
{
if (root == null)
return null;

return root.get();
}

public T getByIndex(int i)
{
TNode currNode = root;
if (root == null)
return null;

for (int j = 0; j < i; j++)
{
currNode = currNode.next;

if (currNode == null)
return null;
}

return currNode.get();
}

public T getByString (String str)
{
TNode currNode = root;


while (currNode != null)
{
if (currNode.get().toString().equalsIgnoreCase(str))
{
return currNode.get();
}
currNode = currNode.next;
}

return null;
}

public T getLast()
{
if (end == null)
return null;

return end.item;
}

public int getLength()
{
return length;
}

public void join(Queue<T> queue)
{
end.next = queue.root;
}

public void remove(int i)
{
if (i == 0)
root = root.next;
else
{
TNode t = getNodeByIndex(i-1);

if (i == length)
{
end = t;
t.next = null;
}
else // just skip the next node to remove it
{   
t.next = t.next.next;
}
}
length --;
}

protected TNode getNodeByIndex(int i)
{
TNode currNode = root;
if (root == null)
return null;

if (i < 0)
return root;

for (int j = 0; j < i; j++)
{
currNode = currNode.next;

if (currNode == null)
return null;
}

return currNode;


protected class TNode
/*** Description ***
* This class represents a single node in a one directional list of type T. 

*** Methods ***
* #Constructor: expects an item of type T
* #get: returns item of type T from the node

*** Variables ***
* #item: item of type T held by the node
* #next: next node in the list
****
*/
{
protected T item;
protected TNode next;


public TNode (T item)
{
this.item = item;
this.next = null;
}

public T get()
{
return item; 
}
}
}




< Back to Question class definition

Saturday, July 23, 2011

Class Definition - Question

Another straightforward class definition. A question has its text, a set of answers and "knows" which is the correct answer, an associated level of difficulty, and it may or may not have an image as part of the question. The setter and getter methods are very straightforward except for the image setter which must first check whether the passed argument has a valid image associated with it located in the drawable resources. 


Again, if there is something here you do not follow just ask and I will respond. 


import android.content.Context;
import android.graphics.drawable.Drawable;


@SuppressWarnings("rawtypes")
public class Question implements Comparable
{
/*** Description *** 
* This class represents a single question and set of answers.

*** Attributes *** 
* cAnswer  - Index (in answers[]) of correct answer to question
* answers  - Array of strings representing a set of possible answers
* question - String representing the question text
* image - Drawable image created from imageSrc passed in constructor
* level - Integer level number representing the minimum level this question is available at
* c - context
* answerIndex - used to add answers to array

*** Methods ***
* Constructor - intitializes all items to default values

* checkAnswer - returns true when submitted integer representing an array index
* matches cAnswer

* setQuestion, setCAnswer, setImage, addAnswer - setter methods

* getAnswers  - Accessor method which returns answers
* getQuestion - Accessor method which returns question
* getImage    - Accessor method which returns image
* getCAnswer  - Accessor method which returns cAnswer

* compareTo   - Returns true only when comparing to same object
*/
private int cAnswer;  
private int answerIndex;
private int level;
private String [] answers; 
private String question;
private Drawable image;
private Context c;

public Question (Context c)
{
this.cAnswer = -1; 
this.question = null;
this.image = null;
this.answers = new String[c.getResources().getInteger(R.integer.max_answers)];
this.answerIndex = 0;
this.level = -1;
this.c = c;
}

public void setQuestion(String q)
{
this.question = q;
}

public void setCAnswer(int i)
{
this.cAnswer = i;
}

public void setLevel(int l)
{
this.level = l;
}

public void setImage (String imageName)
{


int id = c.getResources().getIdentifier(imageName, "drawable", c.getPackageName());
if (id != 0)
{
this.image = c.getResources().getDrawable(id);
}
else
this.image = null;

}

public void addAnswer (String a)
{
this.answers[answerIndex++] = a;
}

public String [] getAnswers()
{
return answers;
}

public String getQuestion()
{
return question;
}

public Drawable getImage()
{
return image;
}

public int getCAnswer()
{
return cAnswer;
}

public int getLevel()
{
return level;
}


public int compareTo(Object another) 
{
// TODO Auto-generated method stub


if (this.equals(another))
return 0;
else 
return -1;
}
}


Continue to Queue class definition >
< Back to Class Definition - Category 

Class Definition - Category

This section will define the Category class. I don't believe anything in this section is  particularly challenging if you have read my previous post about this project, so I will simply post the code. If you have questions, please ask and I will respond.  Remember, this is being written for Android so we need to include a Context and we fetch resources from XML files using the Context.getResources() method. If you aren't familar with Android or want to do this project for console, you can omit anything to do with Context and replace the getResources() call with a variable or integer value. 


import android.content.Context;


@SuppressWarnings("rawtypes")
public class Category implements Comparable
/***
 *** Description ***
 *
 * This class defines a Category object. Each Category contains a name, a list of questions, 
 * and an array of integers representing the number of questions at each difficulty level. 
 * 
 *** Attributes ***
 *
 * String name     - The name of the category
 * int [] levels   - The number of questions at each difficulty level
 * Queue<Question> - A Queue<T> of Question objects 
 * 
 *** Methods ***
 *
 * Constructor: Requires a context and a name. Initializes all attributes. 
 * 
 * addQuestion: Increments the appropriate levels[] index and enqueues the passed Question. 
 * getName: Returns the name
 * getQuestionsAtLevel: returns the number of questions available at the passed integer difficult level
 * getQuestions: Returns the Queue<Question> object
 * toString: returns name
 * compareTo: returns -1 if passed object is not a category, 1 if it is a different Category, or 0 if the same
 * 
 */
{
private String name;
private int [] levels; // levels[0] = easy; levels[1] = normal; levels[2] = genius
private Queue<Question> questions;

public Category (Context c, String name)
{
this.name = name;
this.levels = new int[c.getResources().getInteger(R.integer.number_of_levels)];
this.questions = new Queue<Question>();
}

public void addQuestion (Question q)
{
levels[q.getLevel()]++;
questions.enqueue(q);
}

public String getName()
{
return name;
}

public int getQuestionsAtLevel(int j)
{
int numQs = 0;
for (int i = 0; i <= j; i++)
numQs+= levels[i];
return numQs;
}

public Queue<Question> getQuestions()
{
return questions;
}


public int compareTo(Object another) {
if (another instanceof Category)
{


if (this.toString().equals(another.toString()))
{
return 0;
}
else
return 1;
}
return -1;
}

public String toString()
{
return name;
}
}

Continue to Class Definition - Question >
< Back to Q and A System Take 2 

Q and A System - Take 2

I have spent the past few days revamping the Q and A system. I have created new classes, made others obsolete, and created a much more flexible and powerful interface than the prior system. I will walk you through this system so that you can understand exactly how it does what it does. 

To begin, I will explain the type of question and answer structure we will be dealing with. This system will contain a set of categories, each category containing a set of questions, and each question containing a set of answers. In theory, this could be done using a database or an XML file. For this example, I will use an XML file. 

The XML file will be formatted like so:

<questions>
   <category name="category1">
      <question text="This is a question?" minLevel="0" image="">
             <answer text="Option1" correct="0" />
             <answer text="Option2" correct="0" />
             <answer text="Option3" correct="1" />
             <answer text="Option4" correct="0" />
      </question>
   ...
   </category>
   ...
</questions>

I will explain later what minLevel, correct, and all of the other attributes are. 


The goal for our Q and A system is to turn this XML file into an identical data structure. Originally, I had omitted creating a structure for the categories since they can be represented easily as simply a text string. However, I later found myself wanting my program to want to have the ability to answer questions such as, "for the given difficulty level, how many questions does this category contain?" In order to answer this question, a category structure had to be built. 

So, we want to have a list of categories with varying length (assume we want this system to be used for various q and a games). Each category in the list has a list of questions which also vary in quantity. And each question has a set of answers (in this case, we set an upper bound on how many potential answers can exist). So it looks like the structures we will need to define are:

Category - The name of the category, an array of integers representing how many questions the category contains at varying difficulty settings, and a Queue<T> of question objects. 

Question - An array of possible answers, the index of the correct answer, the difficulty level of the question, and a drawable image.

Queue<T> - This class will create of list of T objects. If you are unfamiliar with Java generics, this will offer you a quick glance at how they work. This class will operate just like you would expect a queue to behave... you can push items on, pop them off, get items by index (not an array so this is a bit deceiving), or retrieve them by matching the Object's toString() method call. 

SO, lets begin...

Tuesday, July 19, 2011

Question Node Class

This class is also fairly straightforward. These class represents a node in a linked list of Question objects. Each node stores a boolean value indicating whether or not the node's question has ever been accessed, a reference to the next QuestionNode in the list, and a Question object. This class will be located within the QuestionQueue class since only the QuestionQueue will need to access it. 

private class QuestionNode
/*** Description ***
* This class represents a single node in a one directional list of questions. 

*** Notes ***
* There is no setter method for 'next'. Instead, the outer class
* directly sets this variable value (ex: thisNode.next = ...). 
* This is because passing an entire Question object is pointless 
* since this is already a private class. 

* Accessor methods are still used simply for code clarification.
*
*** Variables ***
*
* q - the Question object this node holds
* next - the next QuestionNode in the list
* used - tracks whether the Question this node holds has been used or not

*** Methods ***
*
* Constructor - Expects a Question object to hold. 

* getQuestion - Accessor method for q. Also sets used to true.
* used   - Accessor method for used.
* getNext   - Accessor method for next.

* setNext(QuestionNode) - Setter method for next. 
*/
{
private Question q;
private QuestionNode next;
private boolean used;

public QuestionNode (Question q)
{
this.q = q;
this.next = null;
}

public Question getQuestion()
{
this.used = true;
return q; 
}

public boolean used()
{
return used;
}

public QuestionNode getNext()
{
return next;
}

}

Question Class

This class is the most straightforward of all that will be used to construct this Q&A system. The class simply represents a trivia question. 


Each question has the following attributes:

  • Question text
  • An array of possible answers 
  • The index in the array of the correct answer
  • A drawable image for image related questions (not implemented yet)
The class has simple getter and setter methods with access each of the fields. 



private class Question
/*** Description *** 
* This class represents a single question/answer.

*** Variables *** 
* cAnswer  - Index (in answers[]) of correct answer to question
* answers  - Array of strings representing a set of possible answers
* question - String representing the question text
* image - Drawable image created from imageSrc passed in constructor

*** Methods ***
* Constructor - intitializes all items to default values

* checkAnswer - returns true when submitted integer representing an array index
* matches cAnswer

* setQuestion, setCAnswer, setImage, addAnswer - setter methods

* getAnswers  - Accessor method which returns answers
* getQuestion - Accessor method which returns question
* getImage    - Accessor method which returns image
* getCAnswer  - Accessor method which returns cAnswer
*/
{
private int cAnswer;  
private int answerIndex;
private String [] answers; 
private String question;
private Drawable image;

public Question ()
{
this.cAnswer = -1; 
this.question = null;
this.image = null;
this.answers = new String[MAX_ANSWERS];
this.answerIndex = 0;
}

public void setQuestion(String q)
{
this.question = q;
}

public void setCAnswer(int i)
{
this.cAnswer = i;
}

public void setImage (String imagePath)
/* NOT FUNCTIONAL YET */
{
this.image = null;
}

public void addAnswer (String a)
{
this.answers[answerIndex++] = a;
}

public boolean checkAnswer(int answer)
{
return (cAnswer == answer);
}

public String [] getAnswers()
{
return answers;
}

public String getQuestion()
{
return question;
}

public Drawable getImage()
{
return image;
}

public int getCAnswer()
{
return cAnswer;
}


}