Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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

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(":"); } } }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Postgresql 16 Administration Cookbook Solve Real World Database Administration Challenges With 180+ Practical Recipes And Best Practices

Authors: Gianni Ciolli ,Boriss Mejias ,Jimmy Angelakos ,Vibhor Kumar ,Simon Riggs

1st Edition

1835460585, 978-1835460580

More Books

Students also viewed these Databases questions