Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Please help!! Flashcard Application Description of the study methods •Leitner sy

ID: 3585843 • Letter: P

Question

Please help!! Flashcard Application

Description of the study methods

•Leitner system: The application randomly picks a card from one of the five boxes. Note, the likelihood of a card to be picked from a lower numbered box is exponentially higher than from a higher numbered box. For example, for a card in Box 1 it is twice as likely to be picked as a card in Box 2 (four times as likely as a card in Box 3, ...). If the user knows the answer, the flashcard moves to the next box (if there is one). If the user does not know the answer, the flashcard is moved back to Box.

•Simple: Under this method, the student chooses a box by number. The study method picks the first card and presents it to the user. If the student knows the answer, the card moves one box higher (if a higher box exists). If the student does not know the answer, the card moves one box lower (if a lower box exists).

•Drill: Under this method, the flashcards of a given box are copied into a separate pool. The application randomly picks one flashcard from that pool. If the user knows the answer, the card is removed from the pool. If the user does not know the answer the card remains in the pool. Drill ends when the pool is empty. When users end the drill session, the pool can be discarded. During a drill session the Leitner boxes remain unchanged. A user can start a study session by typing leitner, simple boxnum, and drill boxnum, in the TUI.

A study session randomly chooses to present the student one side of the card. As response, a student enters a string.

•Empty string: Indicates that the student knows the answer. The answer is communicated to the study session, which handles the card accordingly. The application proceeds by randomly picking another card.

•Non-empty string: The string is compared with the other side of the flashcard. The answer is communicated to the study session, which handles the card accordingly. The application proceeds by randomly picking another card.

•Special strings: (1) indicates that the student ends the study session. (2) shows the other side of the flashcard.

Tasks Design or revise your TUI in the following way: The study session should not interact with any concrete study method class. Instead, create an interface StudyMethod that describes the methods 1 that any study method needs to implement. Then the study session can be implemented in terms of this interface alone. Design a class hierarchy for study methods Leitner, Simple, and Drill. To this end, consider whether these classes should be in any inheritance relationship by performing the IS-A test, or whether each of them should implement the interface StudyMethod. In case that there is no inheritance relationship between study methods, consider the introduction of one or more abstract class(es) (e.g., AbstractStudyMethod) to factor common behavior and avoid code duplication.

Box.Java

package cs.221.flashcards;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;


/**
* Implements a Leitner box holding flashcards.
*
* @invariant boxnum > 0 && cards != null
*/
public class Box
{
/**
* Constructs a new Box.
*
* @param num Leitner box number
* @precondition num > 0
*/
public Box(int num)
{
assert num > 0;

boxnum = num;
cards = new ArrayList();
}

/** returns current number of flashcards in the box. */
public int size() { return cards.size(); }

/**
* returns specific flashcard from the box.
*
* @param idx flashcard index
* @return the queried Flashcard
* @precondition 0 <= idx < size()
*/
public FlashCard get(int idx) { return cards.get(idx); }

/**
* Adds a new flashcard to this box.
*
* @param card the new flashcard
* @precondition card is not yet in the box
*/
public void add(FlashCard card) { cards.add(card); }

/**
* Removes a flashcard from the box.
*
* @param card the card to be removed
* @precondition card is in this box
*/
public void remove(FlashCard card) { cards.remove(card); }

/**
* Removes a flashcard from the box.
*
* @param idx of the card to be removed
* @precondition 0 <= idx < size()
*/
public void remove(int idx) { cards.remove(idx); }

/**
* Returns an iterator to go through all flashcards in this box.
*
* @return an Iterator
*/
public Iterator iterator() { return cards.iterator(); }

/** Returns the Leitner-ID of this box. */
public int id() { return boxnum; }

/**
* "Convenience function" that allows to add all of these cards to another box.
* @return a reference to the internal box storage.
* @todo This breaks encapsulation and exposes more class internals than needed.
*/
List getCards() { return cards; }

private final int boxnum; /// Leitner id
private final ArrayList cards; /// Flashcard storage
}

FlashCard.Java

package cs..221.flashcards;

/**

* Represents a text based flashcard.

*

* This class is immutable.

* @invariant front != null && back != null

*/

public class FlashCard

{

/**

   * Constructor setting up a flashcard object.

   *

   * @param challenge front of the card

   * @param response back of the card

   * @precondition challenge != null && response != null

   */

FlashCard(String challenge, String response)

{

assert challenge != null && response != null;

front = challenge;

back = response;

}

/** Returns the front side. */

public String getChallenge() { return front; }

/** Returns the back side. */

public String getResponse() { return back; }

/**

   * Produces a textual representation of this flashcard.

   *

   * @return a string containing two lines, one for front and one for back.

   */

public String toString()

{

return front + ' ' + back + ' ';

}

private final String front;

private final String back;

}

FlashCardApp.Java

package cs.221.flashcards;

import java.util.ArrayList;
import java.util.Iterator;

/**
* Class implementing a flashcard application
*
* @invariant boxes != null && boxes.size() > 0
*/
public class FlashCardApp
{
private final int MAX_BOXES = 5; /// Number of boxes

/** Constructs a new flashcard app object and sets the number of boxes */
public FlashCardApp()
{
for (int i = 1; i <= MAX_BOXES; ++i)
{
boxes.add(new Box(i));
}
}

/** Returns an object according to the Leitner study method. */
public Leitner leitner() { return new Leitner(boxes); }

/** Returns an iterator that lists all flash cards in the system. */
public Iterator listAll()
{
ArrayList allCards = new ArrayList();

for (Box box : boxes)
{
allCards.addAll(box.getCards());
}

return allCards.iterator();
}

/**
* Returns an iterator that lists all flash cards containing a given pattern.
*
* @param pattern search pattern for texts on flashcards.
* @return Iterator where all elements contain pattern in either
* front or back of the card.
*
* @precondition pattern != null
*/
public Iterator list(String pattern)
{
assert pattern != null;

ArrayList foundCards = new ArrayList();

for (Box box : boxes)
{
Iterator cardIter = box.iterator();

while (cardIter.hasNext())
{
FlashCard currCard = cardIter.next();
boolean inclCard = ( currCard.getChallenge().indexOf(pattern) >= 0
|| currCard.getResponse().indexOf(pattern) >= 0
);

if (inclCard) foundCards.add(currCard);
}
}

return foundCards.iterator();
}

/**
* Returns an iterator that lists all flash cards in a given box.
*
* @param boxid Leitner box id.
* @return Iterator where all elements contain pattern in either
* front or back of the card.
*
* @precondition 0 < boxid <= number of boxes in the app
*/
public Iterator list(int boxid)
{
assert boxid > 0 && boxid <= boxes.size();

return boxes.get(boxid - 1).iterator();
}


/**
* Creates a new flashcard and adds it to the first box.
*
* @precondition challenge != null && response != null
*/
public void create(String challenge, String response)
{
assert challenge != null && response != null;

boxes.get(0).add(new FlashCard(challenge, response));
}

private final ArrayList boxes = new ArrayList(); /// List of boxes
}

Leitner.Java

package edu.uab.cs.flashcards;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;


/**
* A class implementing the Leitner system for flashcard boxes.
*
* @invariant boxes != null
*/
public class Leitner
{
/**
* Constructs a new Leitner object.
*
* @precondition theBoxes != null
*/
public Leitner(ArrayList theBoxes)
{
assert theBoxes != null;

boxes = theBoxes;
}

/**
* Internal method that computes the weight of a box.
*


* The weight of a Leitner box depends on the box id the number of cards
* it stores. The current implementation assigns a card in a lower box double
* the weight as a card in the next higher box.
*
* @param box the box for which this weight is computed.
* @param numBoxes total number of boxes. This is needed to compute the
* distance from box to the box with the highest Leitner id.
* @return the weight of this box.
*
* @precondition box != null && numBoxes >= box.id()
*/
private int weight(Box box, int numBoxes)
{
assert box != null && numBoxes >= box.id();

// Each card in box number N has a weight of 2 ^ (|boxes| - N).
// Note: 1 << X left-shifts the number 1 by X position ( = 2^X )
return (1 << (numBoxes - box.id())) * box.size();
}


/**
* Computes the total weight of all boxes.
*
* @return the total weight of all boxes
*/
private int totalWeight()
{
int num = 0;

for (Box box : boxes)
{
num += weight(box, boxes.size());
}

return num;
}

/**
* Picks a random card and side from all boxes.
*
* Cards in lower boxes receive higher weight (priority). The method
* returns void, but the picked card's sides can be accessed through
* getQuestion and getAnswer, the answer tested using checkAnswer.
*
* @precondition there must be at least one box with one card.
*/
public void pickCard()
{
int maxRand = totalWeight();
assert maxRand > 0; // there must be at least one box with one card.

// rndVal identifies the box where the card is located
// | weight of box 1 | w. of box 2 | weight of Box 3 ... |
// ^=0 [min rndVal] ^first value for box 2 ^max(rndVal) [last value for highest box]
// ^ rndVal [falls in Box 2]
int rndVal = rand.nextInt(maxRand);

// Identify the box from where the card will be picked.
Iterator boxIter = boxes.iterator();
Box currBox = boxIter.next();

// Subtract the box's weight from rndVal until rndVal < weight(box)
// => we have identified the box.
while (rndVal >= weight(currBox, boxes.size()))
{
rndVal -= weight(currBox, boxes.size());

assert boxIter.hasNext();
currBox = boxIter.next();
}

// Set the box from where the next card will be picked.
box = currBox;

// All cards in a box are equally likely to be picked,
// thus we generate another pseudo random number.
card = box.get(rand.nextInt(box.size()));

// Choose side of card.
displayFront = (rand.nextInt(2) == 0);
}

/**
* Returns the question for the last picked card.
*
* @return the question
*
* @precondtion a card has been picked and not been tested.
*/
public String getQuestion()
{
assert card != null;
return displayFront ? card.getChallenge() : card.getResponse();
}

/**
* Returns the answer for the last picked card.
*
* @return the answer
*
* @precondtion a card has been picked and not been tested.
*/
public String getAnswer()
{
assert card != null;
return displayFront ? card.getResponse() : card.getChallenge();
}

/**
* Validates the response against the last picked card.
*
* @param s the response.
* @return true, iff s was correct. s is assumed to be correct, if it is empty
* or the string returned by getAnswer equals s.
*
* @precondition s != null
*/
public boolean checkAnswer(String s)
{
return "".equals(s) || getAnswer().equals(s);
}

/**
* Computes the box number where the card will be placed
*
* @param box current box number
* @param correct indicates whether response was correct.
*
* @precondition box is a valid box number
*/
public int getTargetBox(int box, boolean correct)
{
int newBoxId = 1; // set target box id in case the response is incorrect

if (correct)
{
// response is correct -> update target box id
newBoxId = Math.min(box, boxes.size());
}

return newBoxId;
}

/**
* Moves card to the target box, depending on whether succ indicates
* a correct/incorrect response.
*
* @param correct, indicates whether the last response was correct.
*/
public void moveCard(boolean correct)
{
int target = getTargetBox(box.id() + 1, correct);
box.remove(card); // remove card from current box
boxes.get(target - 1).add(card); // store card in target box
}

private final Random rand = new Random(); /// random number generator.
private Box box = null; /// last picked box.
private FlashCard card = null; /// last picked card.
private boolean displayFront = true; /// indicates side to display.
private final ArrayList boxes; /// the list of boxes.
}

TUI.Java

package cs.221.flashcards.ui;

import java.util.Scanner;
import java.util.Iterator;
import java.util.StringTokenizer;

import java.io.FileNotFoundException;
import java.io.FileReader;

import edu.uab.cs.flashcards.FlashCardApp;
import edu.uab.cs.flashcards.FlashCard;
import edu.uab.cs.flashcards.Leitner;

/**
* Class implementing a text based user interface.
*/
public class TUI
{
/** command for import. */
private static final String CMD_IMPORT = "import";

/** command for flipping a card. */
private static final String CMD_FLIP = "%";

/** command for exiting. */
private static final String CMD_EXIT = "!exit";

/** command for studying with the Leitner system. */
private static final String CMD_LEITNER = "leitner";

/** command for printing all cards. */
private static final String CMD_LISTALL = "listAll";

/** command for printing selected cards. */
private static final String CMD_LIST = "list";

/**
* Prints all cards on the console.
*
* @param iter Iterator over all flashcards that will be printed
*/
static void print(Iterator iter)
{
while (iter.hasNext())
{
System.out.println( iter.next().toString() );
}
}

/**
* Prints an error message.
*
* @param msg error message
*/
static void error(String msg)
{
System.out.println("Err: " + msg);
}

/**
* UI for studying with the Leitner method.
*
* @param leitner a Leitner study object
*/
static void study(Leitner leitner)
{
Scanner inp = new Scanner(System.in);

for (;;)
{
String answer = null;
boolean flip = false;

leitner.pickCard();

do
{
System.out.println(" ?" + (flip ? leitner.getAnswer() : leitner.getQuestion()) );

System.out.print(" >");
answer = inp.nextLine();
flip = !flip;
} while (CMD_FLIP.equals(answer));

if (CMD_EXIT.equals(answer)) break;

boolean validResponse = leitner.checkAnswer(answer);

leitner.moveCard(validResponse);
if (!validResponse) System.out.println(":(" + leitner.getAnswer() + ' ');
}
}


/**
* imports cards from a given file.
*
* @param app the main flashcard application
* @param filename the file to be loaded
* @throws an exception if the file is not found
*/
static int importCards(FlashCardApp app, String filename) throws FileNotFoundException
{
int cnt = 0;
FileReader freader = null;

try
{
freader = new FileReader(filename);

Scanner inp = new Scanner(freader);

while (inp.hasNextLine())
{
String challenge = inp.nextLine();

if (!inp.hasNextLine()) break;
String response = inp.nextLine();

app.create(challenge, response);
++cnt;

// skip empty line (except for end of file)
if (inp.hasNextLine()) inp.nextLine();
}
}
finally
{
try { freader.close(); } catch (Exception ex) { ex.printStackTrace(); }
}

return cnt;
}

/**
* tokenizes user command.
*
* @param tok a string tokenizer, containing the unprocessed input
* @return the next token; null if there is no more token
*/
static String nextToken(StringTokenizer tok)
{
if (!tok.hasMoreTokens()) return null;

return tok.nextToken();
}

/**
* checks that there remains no user input unhandled.
*
* @param tok a string tokenizer, containing the unprocessed input
* @return true, if there is no more input; false otherwise.
*/
static boolean endOfCommand(StringTokenizer tok)
{
return !tok.hasMoreTokens();
}

/**
* Handles IO for importing flashcards from a file.
*
* @param app the flashcard app
* @param filename the file name
*/
static void processImport(FlashCardApp app, String filename)
{
try
{
int cnt = importCards(app, filename);

System.out.println(cnt + " cards imported.");
}
catch (FileNotFoundException ex)
{
error("File " + filename + "not found");
}
}

/**
* Prints all flashcard form a given box or that contain a string.
*
* @param app the flashcard app
* @param what a string for printing
*/
static void processListAll(FlashCardApp app, String what)
{
int boxnum = 0;

try
{
// test if we received a number
Integer num = new Integer(what);

if (num.toString().equals(what)) boxnum = num;
}
catch (NumberFormatException ex)
{}

// calls one of two overloaded functions
if (boxnum != 0)
print(app.list(boxnum));
else
print(app.list(what));
}


/**
* handles user input and calls functions as needed.
*
* @param app the flashcard app
* @param s a command string
* @return true, if the command was valid; false, otherwise.
*/
static boolean handleCommand(FlashCardApp app, String s)
{
StringTokenizer tok = new StringTokenizer(s, " ", false);
String cmd = nextToken(tok);
boolean cmdOK = false;

if (CMD_IMPORT.equals(cmd))
{
String filename = nextToken(tok);

// command was well formed
if (filename != null && endOfCommand(tok))
{
processImport(app, filename);
cmdOK = true;
}
}
else if (CMD_LEITNER.equals(cmd))
{
if (endOfCommand(tok))
{
study(app.leitner());
cmdOK = true;
}
}
else if (CMD_LISTALL.equals(cmd))
{
if (endOfCommand(tok))
{
print(app.listAll());
cmdOK = true;
}
}
else if (CMD_LIST.equals(cmd))
{
String what = nextToken(tok);

if (what != null && endOfCommand(tok))
{
processListAll(app, what);
cmdOK = true;
}
}
else if (CMD_EXIT.equals(cmd))
{
if (endOfCommand(tok))
System.exit(0);
}

return cmdOK;
}

/**
* Main function and main user input loop.
*
* @param args, not used
*/
public static void main(String[] args)
{
FlashCardApp app = new FlashCardApp();
Scanner inp = new Scanner(System.in);

System.out.print(":");
while (inp.hasNextLine())
{
boolean cmdOK = handleCommand(app, inp.nextLine());

if (!cmdOK) error("invalid command");

System.out.print(":");
}
}
}

Explanation / Answer

TUI.java
-----------------------------------------------------------
import java.util.Scanner;
import java.util.ArrayList;
import java.util.StringTokenizer;

import java.io.FileNotFoundException;
import java.io.FileReader;


/** Thrown when a user input cannot be processed. */
class InvalidCommandException extends Exception
{
    static final long serialVersionUID = -5607746478748725987L;
}

/**
* Class implementing a text based user interface.
*/
public class TUI
{
    /** Prints all cards on the console. */
    static void print(ArrayList<FlashCard> lst)
    {
        for (FlashCard card : lst)
        {
            System.out.println( card.toString() );
        }
    }

    /** Prints an error message. */
    static void error(String msg)
    {
        System.out.println("Err: " + msg);
    }

    /** UI for studying with the StudyMethod interface. */
    static void study(StudyMethod studyM)
    {
        Scanner inp = new Scanner(System.in);

        for (;;)
        {
            String answer;
            boolean flip = false;

            studyM.pickCard();

            do
            {
                System.out.println(" ?" + (flip ? studyM.getAnswer() : studyM.getQuestion()) );

                System.out.print(" >");
                answer = inp.nextLine();
                flip = !flip;
            } while ("%".equals(answer));

            if ("!exit".equals(answer)) break;

            boolean validResponse = studyM.testAnswer(answer);

            studyM.moveCard(validResponse);
            if (!validResponse) System.out.println(":(" + studyM.getAnswer() + ' ');
        }
    }

    /** imports cards from a given file. */
    static int importCards(FlashCardApp app, String filename) throws FileNotFoundException
    {
        int        cnt = 0;
        FileReader freader = null;

        try
        {
            freader = new FileReader(filename);

            Scanner inp = new Scanner(freader);

            while (inp.hasNextLine())
            {
                String challenge = inp.nextLine();

                if (!inp.hasNextLine()) break;
                String response = inp.nextLine();

                app.create(challenge, response);
                ++cnt;

                // skip empty line (except for end of file)
                if (inp.hasNextLine()) inp.nextLine();
            }
        }
        finally
        {
            try { freader.close(); } catch (Exception ex) { ex.printStackTrace(); }
        }

        return cnt;
    }

    /** tokenizes user command. */
    static String nextToken(StringTokenizer tok) throws InvalidCommandException
    {
        if (!tok.hasMoreTokens()) throw new InvalidCommandException();

        return tok.nextToken();
    }

    /** checks that there remains no user input unhandled. */
    static void endOfCommand(StringTokenizer tok) throws InvalidCommandException
    {
        if (tok.hasMoreTokens()) throw new InvalidCommandException();
    }

    /** handles user input and calls functions as needed. */
    static void handleCommand(FlashCardApp app, String s) throws InvalidCommandException
    {
        StringTokenizer tok = new StringTokenizer(s, " ", false);
        String cmd = nextToken(tok);

        if (cmd.equals("import"))
        {
            String filename = nextToken(tok);

            endOfCommand(tok);

            try
            {
                int cnt = importCards(app, filename);

                System.out.println(cnt + " cards imported.");
            }
            catch (FileNotFoundException ex)
            {
                error("File " + filename + "not found");
            }
        }
        else if (cmd.equals("leitner"))
        {
            endOfCommand(tok);
            study(app.leitner());
        }
        else if (cmd.equals("simple"))
        {
            endOfCommand(tok);
            study(app.simple());
        }
        else if (cmd.equals("drill-1"))
        {
            endOfCommand(tok);
            study(app.drill(0));
        }
        else if (cmd.equals("drill-2"))
        {
            endOfCommand(tok);
            study(app.drill(1));
        }
        else if (cmd.equals("drill-3"))
        {
            endOfCommand(tok);
            study(app.drill(2));
        }
        else if (cmd.equals("drill-4"))
        {
            endOfCommand(tok);
            study(app.drill(3));
        }
        else if (cmd.equals("drill-5"))
        {
            endOfCommand(tok);
            study(app.drill(4));
        }
        else if (cmd.equals("list-all"))
        {
            endOfCommand(tok);
            print(app.getAllCards());
        }
        else if (cmd.equals("list-box"))
        {
            String what = nextToken(tok);
            boolean printed = false;
            endOfCommand(tok);

            try
            {
                Integer num = new Integer(what);

                if (num > 0 && num < app.lastBoxNumber())
                {
                    print(app.getCards(num));
                    printed = true;
                }
            }
            catch (NumberFormatException ex)
            {}

            if (!printed) System.out.println("invalid box number");
        }
        else if (cmd.equals("list-with"))
        {
            String what = nextToken(tok);

            endOfCommand(tok);
            print(app.getCardsWith(what));
        }
        else if (cmd.equals("!exit"))
        {
            endOfCommand(tok);
            System.exit(0);
        }
        else
        {
            throw new InvalidCommandException();
        }
    }

    /** Main function and main user input loop. */
    public static void main(String[] args)
    {
        FlashCardApp app = new FlashCardApp();
        Scanner      inp = new Scanner(System.in);

        System.out.print(":");
        while (inp.hasNextLine())
        {
            try
            {
                handleCommand(app, inp.nextLine());
            }
            catch (InvalidCommandException e)
            {
                error("invalid command");
            }

            System.out.print(":");
        }
    }
}
-------------------------------------------------------------------------------------------------
StudyMethod.java
----------------------------------------
public interface StudyMethod
{
    public void pickCard();
    public String getQuestion();
    public String getAnswer();
    public boolean testAnswer(String s);
    public void moveCard(boolean correct);
}
-------------------------------------------------------------------------------------------------
Simple.java
------------------------------------------
import java.util.ArrayList;

/**
* A class implementing the Simple Leitner system for flashcard boxes. Extends Leitner.
*/
public class Simple extends Leitner {


    /**
     * Constructs a new Simple Leitner object.
   
     */
    public Simple(ArrayList<Box> theBoxes) {
        super(theBoxes);
    }

    /**
     * Computes the box number where the card will be placed
     */
    public int getTargetBox(int boxnum, boolean correct)
    {
        if (!correct && boxnum == 1) return 1;
        if (!correct && boxnum > 1) return (boxnum - 1);
        if(boxnum < 6) return (boxnum+1);
        else return 5;
    }

}
------------------------------------------------------------------------------------------------
Leitner.java
---------------------------------------------------
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

/**
* A class implementing the Leitner system for flashcard boxes.
*/
public class Leitner implements StudyMethod
{
    public Leitner(ArrayList<Box> theBoxes)
    {
        assert theBoxes != null;

        boxes = theBoxes;
    }

    private int weight(Box box, int numBoxes)
    {
        assert box != null && numBoxes >= box.id();
      
        return (1 << (numBoxes - box.id())) * box.size();
    }

    /** Computes the total weight of all boxes */
    private int totalWeight()
    {
        int num = 0;

        for (Box box : boxes)
        {
            num += weight(box, boxes.size());
        }

        return num;
    }

    /**
     * Picks a random card from all boxes.
     * Cards in lower boxes receive higher weight (priority)..
     */
    public void pickCard()
    {
        int           maxRand = totalWeight();
        assert maxRand > 0; // there must be at least one box with one card.
      
        int           rndVal = rand.nextInt(maxRand);

        // Identify the box from where the card will be picked.
        Iterator<Box> boxIter = boxes.iterator();
        Box           currBox = boxIter.next();

        // Subtract the box's weight from rndVal until rndVal < weight(box)
        //    => we have identified the box.
        while (rndVal >= weight(currBox, boxes.size()))
        {
            rndVal -= weight(currBox, boxes.size());

            assert boxIter.hasNext();
            currBox = boxIter.next();
        }

        // Set the box from where the next card will be picked.
        box = currBox;

        // All cards in a box are equally likely to be picked,
        //   thus we generate another pseudo random number.
        card = box.get(rand.nextInt(box.size()));

        // Choose side of card.
        displayFront = (rand.nextInt(2) == 0);
    }

    /**
     * Returns the question for the last picked card.
     */
    public String getQuestion()
    {
        assert card != null;

        return displayFront ? card.getChallenge() : card.getResponse();
    }

    /**
     * Returns the answer for the last picked card.
     */
    public String getAnswer()
    {
        assert card != null;

        return displayFront ? card.getResponse() : card.getChallenge();
    }

    /**
     * Validates the response against the last picked card.
     */
    public boolean testAnswer(String s)
    {
        return "".equals(s) || getAnswer().equals(s);
    }

    /**
     * Computes the box number where the card will be placed
     */
    public int getTargetBox(int boxnum, boolean correct)
    {
        if (!correct) return 1;

        return Math.min(boxnum + 1, boxes.size());
    }


    /**
     * Moves card to the target box, depending on whether succ indicates
     * a correct/incorrect response.
     */
    public void moveCard(boolean correct)
    {
        int newBoxId = getTargetBox(box.id(), correct);

        box.remove(card);                  // remove card from current box
        boxes.get(newBoxId - 1).add(card); // store card in target box
    }

    private final ArrayList<Box> boxes;               /// the list of boxes.
    private final Random         rand = new Random(); /// random number generator.
    private Box                  box = null;          /// last picked box.
    private FlashCard            card = null;         /// last picked card.
    private boolean              displayFront = true; /// indicates side to display.
}
-------------------------------------------------------------------------------------------------
FlashCardApp.java
-------------------------------------------------------
import java.util.ArrayList;
import java.util.Iterator;

/**
* Class implementing a flashcard application
*/
public class FlashCardApp
{
    /** Number of boxes. */
    private final int MAX_BOXES = 5;

    /** Constructs a new flashcard app object and initializes the boxes. */
    public FlashCardApp()
    {
        for (int i = 1; i <= MAX_BOXES; ++i)
        {
            boxes.add(new Box(i));
        }
    }

    /** Returns an object according to the Leitner study method. */
    public Leitner leitner()
    {
        return new Leitner(boxes);
    }

    /** Returns an object according to the Leitner study method. */
    public Simple simple()
    {
        return new Simple(boxes);
    }

    /** Returns an object according to the Leitner study method. */
    public Drill drill(int num)
    {
        return new Drill(boxes.get(num));
    }

    /**
     * Returns an arraylist containing all flashcards in the system.
     */
    public ArrayList<FlashCard> getAllCards()
    {
        ArrayList<FlashCard> allCards = new ArrayList<FlashCard>();

        for (Box box : boxes)
        {
            allCards.addAll(box.getAllCards());
        }

        return allCards;
    }

    /**
     * Returns an arraylist containing all flashcards that contain a pattern.
     */
    public ArrayList<FlashCard> getCardsWith(String pattern)
    {
        assert pattern != null;

        ArrayList<FlashCard> foundCards = new ArrayList<FlashCard>();

        for (Box box : boxes)
        {
            ArrayList<FlashCard> cards = box.getAllCards();

            for (FlashCard card : cards)
            {
                boolean inclCard = ( card.getChallenge().indexOf(pattern) >= 0
                        || card.getResponse().indexOf(pattern) >= 0
                );

                if (inclCard) foundCards.add(card);
            }
        }

        return foundCards;
    }

    /**
     * Returns an arraylist that contains all flash cards in a given box.
     */
    public ArrayList<FlashCard> getCards(int boxid)
    {
        assert boxid > 0 && boxid <= boxes.size();

        return boxes.get(boxid - 1).getAllCards();
    }


    /**
     * Creates a new flashcard and adds it to the first box.
     */
    public void create(String challenge, String response)
    {
        assert challenge != null && response != null;

        boxes.get(0).add(new FlashCard(challenge, response));
    }

    public int lastBoxNumber()
    {
        return MAX_BOXES;
    }

    private final ArrayList<Box> boxes = new ArrayList<Box>(); /// List of boxes
    private final ArrayList<FlashCard> box = new ArrayList<FlashCard>();
}
-------------------------------------------------------------------------------------------------
FlashCard.java
-----------------------------------------------------
public class FlashCard {
    /**
     * Constructor setting up a flashcard object.
     */
    FlashCard(String challenge, String response) {
        assert challenge != null && response != null;

        front = challenge;
        back = response;
    }

    /**
     * Returns the front side.
     */
    public String getChallenge() {
        return front;
    }

    /**
     * Returns the back side.
     */
    public String getResponse() {
        return back;
    }

    /**
     * Produces a textual representation of this flashcard.
     */
    public String toString() {
        return front + ' ' + back + ' ';
    }

    private final String front;
    private final String back;
}
------------------------------------------------------------------------------------------------
Drill.java
-------------------------------------------------------
import java.util.Random;

/**
* A class implementing the Drill system for flashcard boxes.
*/
public class Drill implements StudyMethod{

    private Box box;
    private FlashCard card;
    private boolean displayFront = true;
    private final Random rand = new Random();

    /**
     * Constructs a new Drill object.
     */
    public Drill(Box box2) {
        assert box2 != null;
        box = box2;
    }
    /**
     * Picks a random card from the box.
     */
    public void pickCard() {

        int maxCard = box.size();
        if(maxCard == 0){
            System.out.println("Box Complete.");
        }
        else{
            int rndVal = rand.nextInt(maxCard);
            card = box.get(rndVal);
        }
    }

    /**
     * Returns the question for the last picked card.
     */
    public String getQuestion()
    {
        assert card != null;
        return displayFront ? card.getChallenge() : card.getResponse();
    }

    /**
     * Returns the answer for the last picked card.
     */
    public String getAnswer()
    {
        assert card != null;
        return displayFront ? card.getResponse() : card.getChallenge();
    }

    /**
     * Validates the response against the last picked card.
     */
    public boolean testAnswer(String s)
    {
        assert s != null;
        boolean isCorrect = card.getResponse() != null;
        if (isCorrect)
        {
            box.remove(card);
        }
        return isCorrect;
    }

    @Override
    public void moveCard(boolean correct) {
      
    }


}
-----------------------------------------------------------------------------------------
CardBox.java
-----------------------------------------------
import java.util.ArrayList;

public class CardBox {
    /** The ArrayList of this class. */
    private final ArrayList<FlashCard> box;

    /**
     * Constructs a CardBox.
     */
    public CardBox(){
        box = new ArrayList<FlashCard>();
    }

    /**
     * Adds a FlashCard to CardBox.
     */
    public void add(FlashCard a){
        box.add(a);
    }

    /**
     * Removes a FlashCard from CardBox.
     */
    public void remove(FlashCard b){
        box.remove(b);
    }

    /**
     * Gets a FlashCard from CardBox.
     */
    public FlashCard get(int index) {
        return box.get(index);
    }

    public int lastIndexOf(FlashCard b){
        return box.lastIndexOf(b);
    }
    /**
     * Gets all the FlashCards from CardBox.
     */
    public ArrayList<FlashCard> getAll(){
        return box;
    }
}
----------------------------------------------------------------------------------------------
Box.java
--------------------------------------------------------
import java.util.ArrayList;

/**
* Implements a Leitner box holding flashcards.
*/
public class Box
{
    /**
     * Constructs a new Box.
     */
    public Box(int num)
    {
        assert num > 0;

        boxnum = num;
        cards = new ArrayList<FlashCard>();
    }

    /** returns current number of flashcards in the box. */
    public int size() { return cards.size(); }

    public FlashCard get(int idx) { return cards.get(idx); }

    /**
     * Adds a new flashcard to this box.

     */
    public void add(FlashCard card) { cards.add(card); }

    /**
     * Removes a flashcard from the box.
     */
    public void remove(FlashCard card) { cards.remove(card); }

    /**
     * Removes a flashcard from the box.
     */
    public void remove(int idx) { cards.remove(idx); }

    /**
     * Returns an ArrayList<FlashCard> containing all cards in the box.
     */
    public ArrayList<FlashCard> getAllCards()
    {
        ArrayList<FlashCard> copy = new ArrayList<FlashCard>();

        for (FlashCard card : cards) copy.add(card);

        return copy;
    }

    /** Returns the Leitner-ID of this box. */
    public int id() { return boxnum; }

    private final int                  boxnum;
    private final ArrayList<FlashCard> cards;
}