This is a Java program. I will attach the template code at the bottom that needs
ID: 3873925 • Letter: T
Question
This is a Java program. I will attach the template code at the bottom that needs to be implemented. Everything that needs to be added is marked with a /* TODO: complete implementation */, so I think the Box and FlashCard classes are complete. The FlashCard class says it's immutable. The Box class doesn't however. Please include comments in your code explaining functionality and approach decisions. If you don't know what the Leitner system is (I didn't), a quick youtube search of "Leitner flashcards" will make the program objective much more clear. Please read the assignment and follow the parameters (haven't had much success lately on here with that). Much appreciated.
FLASHCARFD CLASS
/**
* 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;
}
-----------------------------------------------------------------------------------------------------------------------------
BOX CLASS
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<FlashCard>();
}
/** 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 ArrayList<FlashCard> containing all cards in the box.
* Note, we return a copy to preserve encapsulation.
*
* @return an ArrayList<FlashCard>
*/
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; /// Leitner id
private final ArrayList<FlashCard> cards; /// Flashcard storage
}
-------------------------------------------------------------------------------------------------------------------------------
FLASHCARD APP CLASS
import java.util.ArrayList;
/**
* Class implementing a flashcard application
*
* @invariant boxes != null && boxes.size() > 0
*/
public class FlashCardApp
{
/** Number of boxes. */
private final int MAX_BOXES = 5;
/** Constructs a new flashcard app object and initializes the boxes. */
public FlashCardApp()
{
/* TODO: complete implementation */
}
/** Returns an object according to the Leitner study method. */
public Leitner leitner()
{
/* TODO: complete implementation */
return null;
}
/**
* Returns an arraylist containing all flashcards in the system.
*
* @return ArrayList<FlashCard>
*/
public ArrayList<FlashCard> getAllCards()
{
/* TODO: complete implementation */
return null;
}
/**
* Returns an arraylist containing all flashcards that contain a pattern.
*
* @param pattern search pattern for texts on flashcards.
* @return ArrayList<FlashCard> where all elements contain pattern in either
* front or back of the card.
*
* @precondition pattern != null
*/
public ArrayList<FlashCard> getCardsWith(String pattern)
{
assert pattern != null;
/* TODO: complete implementation */
return null;
}
/**
* Returns an arraylist that contains all flash cards in a given box.
*
* @param boxid Leitner box id.
* @return ArrayList<FlashCard> with all cards in box boxid.
*
* @precondition 0 < boxid <= number of boxes in the app
*/
public ArrayList<FlashCard> getCards(int boxid)
{
assert boxid > 0 /* && boxid <= max-number-of-boxes */;
/* TODO: complete implementation */
return null;
}
/**
* 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;
/* TODO: complete implementation */
}
/* TODO: add private data members. */
}
--------------------------------------------------------------------------------------------------------------------------
LEITNER CLASS
import java.util.ArrayList;
/**
* 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<Box> theBoxes)
{
assert theBoxes != null;
/* TODO: complete implementation */
}
/**
* 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()
{
/* TODO: complete implementation */
}
/**
* Returns the question for the last picked card.
*
* @return the question
*
* @precondtion a card has been picked and not been tested.
*/
public String getQuestion()
{
/* TODO: complete implementation */
return null;
}
/**
* Returns the answer for the last picked card.
*
* @return the answer
*
* @precondtion a card has been picked and not been tested.
*/
public String getAnswer()
{
/* TODO: complete implementation */
return null;
}
/**
* 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 testAnswer(String s)
{
/* TODO: complete implementation */
return true;
}
/**
* 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)
{
/* TODO: computes the box where the current card needs to be placed.
* 1 iff !correct
* min(box+1, boxes.size()) iff correct
*/
return 0;
}
/**
* 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)
{
/* TODO: complete implementation */
}
/* TODO: add data members */
}
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(":");
}
}
}
FlashCardApp.java
import java.util.ArrayList;
import java.util.Iterator;
/**
* Class implementing a flashcard application
*
* @invariant boxes != null && boxes.size() > 0
*/
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.
*
* @return ArrayList<FlashCard>
*/
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.
*
* @param pattern search pattern for texts on flashcards.
* @return ArrayList<FlashCard> where all elements contain pattern in either
* front or back of the card.
*
* @precondition pattern != null
*/
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.
*
* @param boxid Leitner box id.
* @return ArrayList<FlashCard> with all cards in box boxid.
*
* @precondition 0 < boxid <= number of boxes in the app
*/
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.
*
* @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));
}
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
/**
* 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;
}
Box.java
import java.util.ArrayList;
/**
* 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<FlashCard>();
}
/** 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 ArrayList<FlashCard> containing all cards in the box.
*
* @return an ArrayList<FlashCard>
*/
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; /// Leitner id
private final ArrayList<FlashCard> cards; /// Flashcard storage
}
StudyMethod.java
public interface StudyMethod
{
public void pickCard();
public String getQuestion();
public String getAnswer();
public boolean testAnswer(String s);
public void moveCard(boolean correct);
}
Leitner.java
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 implements StudyMethod
{
/**
* Constructs a new Leitner object.
*
* @precondition theBoxes != null
*/
public Leitner(ArrayList<Box> theBoxes)
{
assert theBoxes != null;
boxes = theBoxes;
}
/**
* Internal method that computes the weight of a box.
* <p>
* 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 */
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).
*
* @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<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.
*
* @return the question
*
* @precondtion pickCard() has been called at least once
*/
public String getQuestion()
{
assert card != null;
return displayFront ? card.getChallenge() : card.getResponse();
}
/**
* Returns the answer for the last picked card.
*
* @return the answer
*
* @precondtion pickCard() has been called at least once
*/
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.
*/
public boolean testAnswer(String s)
{
return "".equals(s) || getAnswer().equals(s);
}
/**
* Computes the box number where the card will be placed
*
* @param boxnum current box number
* @param correct indicates whether response was correct.
*
* @precondition box is a valid box number
*/
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.
*
* @param correct, indicates whether the last response was correct.
*/
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.
}
Simple.java
import java.util.ArrayList;
/**
* A class implementing the Simple Leitner system for flashcard boxes. Extends Leitner.
*
* @invariant boxes != null
*/
public class Simple extends Leitner {
/**
* Constructs a new Simple Leitner object.
*
* @precondition theBoxes != null
*/
public Simple(ArrayList<Box> theBoxes) {
super(theBoxes);
}
/**
* Computes the box number where the card will be placed
*
* @param boxnum current box number
* @param correct indicates whether response was correct.
*
* @precondition box is a valid box number
*/
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;
}
}
Drill.java
import java.util.Random;
/**
* A class implementing the Drill system for flashcard boxes.
*
* @invariant boxes != null
*/
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.
*
* @precondition box2 != null
*/
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.
*
* @return the question
*
* @precondtion pickCard() has been called at least once
*/
public String getQuestion()
{
assert card != null;
return displayFront ? card.getChallenge() : card.getResponse();
}
/**
* Returns the answer for the last picked card.
*
* @return the answer
*
* @precondtion pickCard() has been called at least once
*/
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 isCorrect, which calls the getResponse method of the 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) {
// Does not need this?
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.