Solo Project: Flashcard Displayer

Solo Project: Flashcard Displayer

Goals

To implement a heap and use it as a priority queue. This project also integrates other skills practiced in previous assignments, like file I/O, getting user input, using built-in methods, etc.

Tip: Please leave plenty of time for Part III.

Honor Pledge

This is a solo project. I ask you to sign and upload your HonorPledge.txt along with your code submission. The content of the honor pledge is:

The work I submitted was purely my own work. I haven't sought help outside of these exceptions:

  • the textbook and other course materials
  • clarifying questions answered or hints provided by Prof. Jiang (or on Piazza, or by the lab assistant on April 13)
  • discussions of the three design questions in Part II
  • error messages searched on the Internet (without copying any code directly)

Name: YOUR_NAME

Setup

In this project, you'll build a flashcard displaying program. You'll allow the user to load flashcards from a file, which will include when the flashcard should be shown next, and display all the flashcards that are currently due. The user will tell you if they got the flashcard right or wrong, and based on that, you'll determine when the flashcard should be shown next. You'll also allow the user to save the flashcards so that they can restart the program later and look at the flashcards with updated due date.

Download the starter folder. It has a PriorityQueue interface and a file of sample flashcards.

Part I: Storing Flashcards

Your flashcard program will need a class that can store flashcard information (the front and back of the flashcard) together with when the flashcard should be shown next. Write a Flashcard class that has at least the following constructor and methods (don't change their headers):

/**
 * Creates a new flashcard with the given dueDate, text for the front
 * of the card (front), and text for the back of the card (back).
 * dueDate must be in the format YYYY-MM-DDTHH:MM. For example,
 * 2019-11-04T13:03 represents 1:03PM on November 4, 2019. It's
 * okay if this method crashes if the date format is incorrect.
 * In the format above, the time may be more precise (e.g., seconds
 * or milliseconds may be included). The parse method in LocalDateTime
 * can deal with these situations without any changes to your code.
 */
public Flashcard(String dueDate, String front, String back);
 
/**
 * Gets the text for the front of this flashcard.
 */
public String getFrontText();
 
/**
 * Gets the text for the Back of this flashcard.
 */
public String getBackText();
 
/**
 * Gets the time when this flashcard is next due.
 */
public LocalDateTime getDueDate();

You'll want to take a look at the LocalDateTime class, which you'll use to represent your date. You can use the parse method of LocalDateTime to turn a String into a LocalDateTime object. parse takes two arguments: the string to be converted, and a formatting string. The formatting string tells LocalDateTime what format your string is. The static String stored in DateTimeFormatter.ISO_LOCAL_DATE_TIME is the formatting string you'd like to use here.

Important: You'll need to store Flashcards in a priority queue in Part II, so be sure to think about what other method you'll need for that. What interface must Flashcard implement? (Hint: Look at the constraint on the generic type for PriorityQueue. You might also want to review the early slides from Week 6 Wednesday.) This extra method needs only one or two lines of code in it—be sure to browse LocalDateTime and see if there is a built-in method you can make use of.

I also recommend writing a toString for the Flashcard class, to assist your testing for Part II and Part III.

Part II: Implementing a Priority Queue

Next you'll write a class FlashcardPriorityQueue that implements a priority queue by making a min-heap. A min-heap is like a max-heap except that nodes higher in the tree are less than their children, rather than greater than them. To help you generalize about how to code up a heap, you'll build a ternary heap rather than a binary heap. The only new thing with a ternary heap is that each node has up to three children, rather than two. Just like in a binary heap, a ternary heap is complete in that all levels are full, except possibly the last one which is filled from left to right. Here's an example of a ternary min-heap:

(If the image doesn't show up, please see TernaryHeap.png).

Your class should implement the interface PriorityQueue that is included in the starter files. Your class needs only be able to store Flashcards, so you can specify the class name in the angle brackes like this: public class FlashcardPriorityQueue implements PriorityQueue<Flashcard>.

Besides the methods in the PriorityQueue interface, your implementation should also have a constructor:

/**
 * Creates an empty priority queue with the default capacity.
 */
public FlashcardPriorityQueue();

Write a main method in FlashcardPriorityQueue that thoroughly tests the public methods in FlashcardPriorityQueuemain can call also (private) helper methods for different types of tests if you'd like. Think through the cases that might come up (e.g., adding an item when the array doesn't have any more spots), and make sure your tests check that your implementation works in each case.

If you refer to MaxHeap.java in Section 27.4 as a starting point for your code, note that we don't need to use integrityOK or MAX_CAPACITY (the queue can be as long as we want). You also don't need to specify an initialCapacity for the constructor—just create an array with the DEFAULT_CAPACITY. For this project, it's okay (and encouraged) to borrow code from the textbook.

Design questions to help you write this class:

  1. Should the first spot in the array be left unused?
  2. For a node of index i, what are the indices of its three children (if they exist) in the array?
  3. For a node of index i, what is the index of its parent node (if it exists) in the array?

Feel free to discuss the above three design questions with your classmates (or on Piazza), and it won't be a violation of the honor code.

Tip: If you refer to the code for reheap from MaxHeap.java to help you implement poll, ask yourself what would be a better variable name for "largerChildIndex" in your version of reheap. In general, choosing an accurate variable name can save you lots of confusion.

Part III: Implementing a Flashcard App

Write a FlashcardDisplayer class that allows the user to store and display flashcards. FlashcardDisplayer must have the following methods and constructor:

/**
 * Creates a flashcard displayer with the flashcards in file.
 * File has one flashcard per line. On each line, the date the flashcard 
 * should next be shown is first (format: YYYY-MM-DDTHH-MM), followed by a tab, 
 * followed by the text for the front of the flashcard, followed by another tab.
 * followed by the text for the back of the flashcard. You can assume that the 
 * front/back text does not itself contain tabs. (I.e., a properly formatted file
 * has exactly 2 tabs per line.)
 * The time may be more precise (e.g., seconds may be included). The parse method
 * in LocalDateTime can deal with this situation without any changes to your code.
 */
public FlashcardDisplayer(String filePath);
 
/**
 * Writes out all flashcards to a file so that they can be loaded
 * by the FlashcardDisplayer(String filePath) constructor. Returns true
 * if the file could be written. The FlashcardDisplayer should still
 * have all of the same flashcards after this method is called as it
 * did before the method was called. However, flashcards with the same
 * exact same next display date may later be displayed in a different order.
 */
public boolean saveFlashcards(String outFilePath);
 
/**
 * Displays any flashcards that are currently due to the user, and
 * asks them to report whether they got each card correct. If the
 * card was correct (if the user entered "1"), it is added back to the
 * deck of cards with a new due date that is one day later than the current
 * date and time; if the card was incorrect (if the user entered "2"), it is
 * added back to the card with a new due date that is one minute later than
 * that the current date and time.
 */
public void displayFlashcards();

Your implementation should use the FlashcardPriorityQueue you designed in Part I to store the cards. A sample set of flashcards is in SampleFlashcards.txt. In the constructer, for each line you read from the file, you may parse the line using split("\t"), and then add a new Flashcard based on this line to the queue.

See Code Notes and Tips for suggestions on methods that will help you in displayFlashcards.

Your command line version of FlashcardDisplayer should work with one usage: java FlashcardDisplayer flashcardFilename, where the argument flashcardFilename is a path to a file with flashcards as defined in the comments above. This should load the file of flashcards; if it can't be loaded, a helpful message about the fact that the file is missing (not the stack trace errors!) should be displayed and the program should end.

The command line program should recognize three commands: quizsave, and exit:

  • quiz should display the flashcards that are currently due to the user (see example interaction below).
  • save should prompt the user with a filename and save all of the flashcards to that file. After running this command, the FlashcardDisplayer should still have the same flashcards.
  • exit should quit the program.

Here's an example of me interacting with my implementation, called with SampleFlashcards.txt on the command line:

m1-mcs-yjiang3$ java FlashcardDisplayer SampleFlashcards.txt
Time to practice flashcards! The computer will display your flashcards,
you generate the response in your head, and then see if you got it right.
The computer will show you cards that you miss more often than those you know!
Enter a command:
quiz

Card:
Beijing
[Press return for back of card]
China
Press 1 if you got the card correct and 2 if you got the card incorrect.
1

Card:
Kabul
[Press return for back of card]
Afghanistan
Press 1 if you got the card correct and 2 if you got the card incorrect.
2

Card:
Apia
[Press return for back of card]
Samoa
Press 1 if you got the card correct and 2 if you got the card incorrect.
1

Card:
Kampala
[Press return for back of card]
Uganda
Press 1 if you got the card correct and 2 if you got the card incorrect.
1
No cards are waiting to be studied!
Enter a command:
save
Type a filename where you'd like to save the flashcards: 
SampleFlashcards2.txt
Enter a command:
exit
Goodbye!

Your program's interaction may be worded differently, but should have the same overall behaviors. In the interaction above, the back of the card does not show up until the person has actually typed return, giving them time to generate the response. Research in the learning sciences shows that actually generating answers leads to greater retention of material than just re-studying.

I saved the flashcards in a file when I interacted with it on the evening of March 2nd, and here's what it saved:

2023-03-02T17:26:27.117 Kabul   Afghanistan
2023-03-03T17:25:24.149 Beijing China
2023-03-03T17:25:29.613 Apia    Samoa
2023-03-03T17:25:31.861 Kampala Uganda
2023-03-08T01:03    Ottawa  Canada
2023-03-10T01:03    Brasilia    Brazil

Note that the cards for Ottawa and Brasilia have the same due date as before because I haven't practiced them yet. The reason the program didn't display them is because they aren't due until after the evening of March 2nd. Kabul is due again at 5:26PM on March 2nd because I got it wrong at 5:25PM on March 2nd. Thus, in the interaction above, if I had waited a few minutes and then typed "quiz" again, it would have shown me the Kabul flashcard again, since it would once again be due. The other three I practiced got right, so they are all due one day after I practiced. The computer has added extra precision to the due dates for the cards I practiced; this will still be parsed properly using the same formatting string, and you can include or not include this extra precision in your saved file as you wish.

Code Notes and Tips

  • In LocalDateTime, there are several functions that may be helpful: the static method now(), which gives you a LocalDateTime representing the current date and time, and the plusMinutes and plusDays functions, which allow you to add time and return a new LocalDateTime object.
  • In Part II, your task was slightly simplified by not having to deal with generic objects and instead dealing only with Flashcards. If you want an extra challenge, think through how you would do the generic version. You'll likely find it helpful to refer back to HW9 on working with generic arrays.
  • Implementing a ternary heap is a good way to make sure you really understand the ideas we've talked about in class. However, a ternary heap is not necessarily as efficient as a binary heap, depending on what operations you're doing. It's slightly shorter than a binary tree, but when performing reheap, it requires more comparisons to find the child to move upward. This illustrates that just getting a shorter tree doesn't necessarily make things more efficient: for example, if nodes were allowed to have unlimited children, then the tree could always have height two!

Submission Guidelines

Please add your name to each Java file you wrote. Zip up Flashcard.javaFlashcardPriorityQueue.java, and FlashcardDisplayer.java. Upload this zip file along with your signed HonorPledge.txt on Blackboard.

Start early, ask lots of questions, and have fun!

Requirements

Below, I've listed the classes and methods you need to implement for this project, and as always, you are welcome to write any additional (private) methods you like:

ClassRequired constructors, methods or interface implementationsRequired command line functionality
Flashcardpublic Flashcard(String dueDate, String front, String back);
public String getFrontText();
public String getBackText();
public LocalDateTime getDueDate();
Must be implemented so it can be stored in a PriorityQueue.
None
FlashcardPriorityQueueMust implement PriorityQueue<Flashcard>
 
Running from the command line with no arguments should run your tests of FlashcardPriorityQueue. If your tests assume some text file that you've used for testing, you should include this file when you submit on Blackboard.
FlashcardDisplayerpublic FlashcardDisplayer(String file);
public boolean saveFlashcards(String outFile);
public void displayFlashcards();
java FlashcardDisplayer flashcardFilename
Loads the flashcards in the file named flashcardFilename and allows the user to quiz themselves (quiz), save the flashcards (save), and exit the program (exit).

This is a partial list of the things that I'll be looking for when evaluating your work (in addition to style):

  • FlashcardPriorityQueue implements PriorityQueue.
  • You use good abstraction and write methods to simplify your code and make it easier to read.
  • You do not have unnecesary instance variables (data fields).
  • You write accurate and helpful comments.
  • FlashcardPriorityQueue constructs a min ternary heap (not a binary one or a max heap!).
  • All of the methods in FlashcardPriorityQueue work correctly. I will test them using code I wrote, and this code may create multiple FlashcardPriorityQueues, test edge cases, and add and poll in many different orders.
  • Your main method in FlashcardPriorityQueue tests all of your public methods across a variety of interesting cases, and someone can tell if your implementation is working by looking at your test output (without having to look at your code).
  • FlashcardDisplayer can read files and interact with the user.
  • FlashcardDisplayer can save flashcards out to a text file.

This project is worth 10% of your final grade.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值