Skip to content
Snippets Groups Projects
Commit 518d86a8 authored by Simon Barrett's avatar Simon Barrett
Browse files

Uploading to Gitlab

parent 32e096b8
No related branches found
No related tags found
No related merge requests found
Showing
with 1325 additions and 0 deletions
Lesson.java
\ No newline at end of file
<component name="ArtifactManager">
<artifact type="jar" name="1218123:jar">
<output-path>$PROJECT_DIR$/out/artifacts/1218123_jar</output-path>
<root id="archive" name="java-cw1-attempt-2.jar">
<element id="module-output" name="java-cw1-attempt-2" />
</root>
</artifact>
</component>
\ No newline at end of file
File added
## Title
Lesson Title Goes Here
## Lesson Text
Lesson Text goes here all as one line
## Questions
# Question
Question goes here (Do not number the question, this is done in the program)
# Answers
Add as many answers as you want
One per line
Do not number the answers
This is done in the program
If this is the correct answer then the int for correct answer will be 5
# Correct Answer
Int representing the correct answers place in the answers above goes here
You can then Repeat the # Question tag as many times as you like.
\ No newline at end of file
public class Lesson {
/*
This class creates a lesson object along with the ability to print the lesson and print and complete the quiz
associated with it.
*/
/* Design Decision:
Part [1] - Lesson Title, Lesson and QuestionArray are marked as final as once initialised they will not change
Part [2] - Lesson + Quiz Completed and QuizScore record what parts of a lesson each user has completed
Makes logical sense to store completion data with the lesson, however as code gets larger it may be useful to
split part [2] into a separate class as you don't need to store all of part [1], only the lessonTitle
in the user record. This could save on memory.
It is currently written this way to simplify the reading of the program, reducing the time needed to go through it.
*/
final private String lessonTitle;
final private String lessonText;
final private Question[] questionArray;
private boolean lessonCompleted;
private boolean quizCompleted;
private int quizScore;
/**
* When a lesson is initialised the user hasn't seen or completed the lesson or quiz so these are set to false and zero
* @param lessonTitle
* @param lessonText
* @param questionArray
*/
public Lesson(String lessonTitle, String lessonText, Question[] questionArray) {
this.lessonTitle = lessonTitle;
this.lessonText = lessonText;
this.questionArray = questionArray;
this.lessonCompleted = false;
this.quizCompleted = false;
this.quizScore = 0;
}
/* GETTER METHODS
3 Standard getter methods, 1 custom getter method
*/
public String getLessonTitle() {
return lessonTitle;
}
public int getQuizScore() {
return quizScore;
}
public boolean isQuizCompleted() {
return quizCompleted;
}
// Rather than have a getter and then call .length on it, it has been combined here for readability.
public int getQuestionArrayLength() {
return questionArray.length;
}
// END GETTER METHODS
/* SETTER METHODS
3 fields are marked as final so can't be set
*/
public void setQuizCompleted(boolean quizCompleted) {
this.quizCompleted = quizCompleted;
}
/**
* Checks if current quiz score is greater than saved score and replaces it.
* This ensures that users best quiz score is saved.
* @param quizScore
*/
public void setQuizScore(int quizScore) {
if(quizScore > this.quizScore) {
this.quizScore = quizScore;
}
}
// END SETTER METHODS
// CUSTOM METHODS
/**
* Prints out the lesson title followed by the lesson text with empty lines in between for styling
* <p>
* Sets lessonCompleted to true as the lesson has now been printed out for user to read
*/
public void printLesson() {
// Prints out lesson title and text and sets the lesson completed to true
System.out.println("You have chosen the lesson: " + lessonTitle);
System.out.println(" ");
System.out.println(lessonText);
System.out.println(" ");
lessonCompleted = true;
}
/**
* Iterates over questionArray printing out each question in turn, recording user score,
* and giving user immediate feedback on the quiz
* @return total correct user answers
*/
public int doQuiz() {
// Initialise the users score and questions answered so they can see how they are doing after every question
int correctAnswers = 0;
int questionsAnswered = 0;
// Styling so it is easy to see where the quiz starts
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | Quiz | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" ");
for(int i = 0; i < questionArray.length; i++) {
// Checks that user got the question correct and adds 1 to score if they do
if(questionArray[i].askQuestion(i + 1)) {
correctAnswers += 1;
}
questionsAnswered += 1;
// Checks to see if it is the last questions and outputs a different string depending on if it is or not.
if (i != questionArray.length - 1) {
System.out.print("Your current score is " + correctAnswers + "/" + questionsAnswered + ".");
} else {
System.out.println("Your final score is " + correctAnswers + "/" + questionsAnswered + ".");
System.out.println("Congratulations on completing the lesson and the quiz.");
}
// Creates gap before next question
System.out.println(" ");
System.out.println(" ");
}
// Returns the users total score for the quiz so this can be recorded
return correctAnswers;
}
// END CUSTOM METHODS
}
## Title
CSS - Cascading Style Sheets
## Lesson Text
Cascading Style Sheets (CSS) is a language used to describe how a document written in markup Language (E.G. HTML) is presented. It is one of the three main web technologies alongside HTML and JavaScript. CSS can be written inline, in an internal <style> element or added as an external stylesheet using a <link> in the HTML header. One of the most important CSS concepts is the box model, which is a box which wraps around every HTML element and includes padding, margin, and other properties. You can find the full list of CSS properties here: https://www.w3schools.com/cssref/default.asp
## Questions
# Question
What does CSS stand for?
# Answers
Caesar salad, sir?
Cascading Style Sheets
Completely straightforward and sensible
Can see something?
# Correct Answer
2
# Question
How do you select a class?
# Answers
.class
#class
<class>
@class
# Correct Answer
1
# Question
Which of these is not a valid colour?
# Answers
color: #000
color: rgb(0,0,0)
color: #000000
color: 000000
# Correct Answer
4
# Question
How do you select an id?
# Answers
.id
#id
<id>
@id
# Correct Answer
2
# Question
What is the corresponding keyword to the font-weight: 700?
# Answers
Bold
Normal
Light
Bolder
# Correct Answer
1
## Title
Data Types
## Lesson Text
Java is a statically-typed programming language. This means that all variables must first be declared before they can be used. This involves stating both the variables type and name. In java there are 8 primitive data types. These are: byte, short, int, long, float, double, boolean, char. These are predefined by the language and their names are reserved keywords.
## Questions
# Question
What is the correct way to declare a variable?
# Answers
i = 5;
int i 5;
int i = 5;
int i(5);
# Correct Answer
3
# Question
Which data type is best to store a true/false value?
# Answers
byte
char
Boolean
Int
Double
# Correct Answer
3
# Question
What is the default value for an int?
# Answers
Null
Undefined
0
# Correct Answer
3
\ No newline at end of file
## Title
HTML - HyperText Markup Language
## Lesson Text
HyperText Markup Language (HTML) is the building block of the web. Invented in 1993 by Tim Berners-Lee it has gone through many iterations with the current being HTML5. This introduced semantic tags in order to help developers clearly define a pages content for browsers and screen readers. HTML is written using tags which general come in a pair: the opening tag <tag> and the closing tag </tag>, however sometimes the closing tag can be left out. Each type of tag defines how the browser will format and display the content. You can find a full list of tags here: https://www.w3schools.com/TAGS/default.ASP.
## Questions
# Question
What does HTML stand for?
# Answers
Help To Make Layout
Highly Typed Machine Language
HyperText Markup Language
Hey! That’s my Llama
# Correct Answer
3
# Question
Which of these tags doesn’t need a closing tag?
# Answers
<h1>
<body>
<form>
<img>
# Correct Answer
4
# Question
Where should the <!DOCTYPE html> tag go on the page?
# Answers
It’s should be the first item
At the start of the body element
It’s should be the last item
Anywhere you want
# Correct Answer
1
# Question
What tag do you normally use to link to another web page?
# Answers
<a>
<link>
<nav>
<li>
# Correct Answer
1
# Question
What is the correct way to declare a comment in HTML?
# Answers
// This is a comment
/* This is a comment*/
<! This is a comment ->
<!- -This is a comment - ->
# Correct Answer
4
## Title
Java Keywords
## Lesson Text
Java has a number of keywords which are reserved so that you can’t use them as identifiers in your program. These keywords indicate to java that a certain action needs to be performed. When programming in an IDE you will often be told if a word is a keyword and you can’t use it as an identifier. For a full list visit this link: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html. This quiz will test your knowledge of keywords, for each question you have to find the word which isn’t a keyword.
## Questions
# Question
Which of these is not a keyword?
# Answers
continue
goto
finally
next
# Correct Answer
4
# Question
Which of these is not a keyword?
# Answers
for
if
when
else
# Correct Answer
3
# Question
Which of these is not a keyword?
# Answers
private
protected
public
personal
# Correct Answer
4
# Question
Which of these is not a keyword?
# Answers
huge
short
long
double
# Correct Answer
1
# Question
Which of these is not a keyword?
# Answers
case
catch
class
client
# Correct Answer
4
# Question
Which of these is not a keyword?
# Answers
implements
impresses
interface
instanceof
# Correct Answer
2
# Question
Which of these is not a keyword?
# Answers
try
catch
maybe
throws
# Correct Answer
3
\ No newline at end of file
## Title
Object-Oriented Programming
## Lesson Text
Object-Oriented programming (OOP) is a type of programming paradigm based on the concept of “Objects”, which contain fields and methods. Fields contains data and can be primitive types or hold other objects through composition. Methods define procedures and depending on the fields access modifier are often the only way to access fields. Classes must be built with a constructor, this can set values for the fields when the class is initialised. It can also contain getters and setters to access private values from outside of the class.
## Questions
# Question
Which of these is not a Java access modifier keyword?
# Answers
Private
Public
Class Private
Protected
Default
# Correct Answer
3
# Question
Coupling and Cohesion are two OOP concepts, which statement best describes the way we want them to be used in our program?
# Answers
Decreased Coupling, Decreased Cohesion
Decreased Coupling, Increased Cohesion
Increased Coupling, Decreased Cohesion
Increased Coupling, Increased Cohesion
# Correct Answer
2
# Question
What is the best reason to use a design pattern?
# Answers
It will result in code which is more extensible and maintainable
It will result in an easier to describe product
You can proudly tell everyone you are following a certain pattern
# Correct Answer
1
# Question
Composition is best described by what type of relationship?
# Answers
IS – A
HAS – A
WAS – A
DOES – A
CREATES – A
# Correct Answer
2
# Question
Inheritance is best described by what type of relationship?
# Answers
IS – A
HAS – A
WAS – A
DOES – A
CREATES – A
# Correct Answer
1
# Question
When would you use an interface class?
# Answers
When you wanted to ensure that a class contained certain variables and methods
The interface class is the main way that a user operates your program
When you need to store a large amount of data you use an interface class to do it
# Correct Answer
1
\ No newline at end of file
## Title
Scrum Framework
## Lesson Text
Scrum is a lightweight framework used to generate value through solutions to problems. Originally designed for Software Engineering it is now used in multiple other fields. In a nutshell, Scrum requires a Scrum Master to foster an environment where a Product Owner orders the work for a complex problem into a product backlog. The Scrum Team then turns a selection of the work into an Increment of value during a Sprint. This is shown to stakeholders to inspect the results, the sprint is reviewed and then the Sprint starts again.
## Questions
# Question
Which one of these isn’t a member of the Scrum team?
# Answers
Scrum Master
Chief Technology Officer
Product Owner
Developer
# Correct Answer
2
# Question
What is the recommended longest length of time for a sprint?
# Answers
One Week
One Month
Two Weeks
6 Weeks
# Correct Answer
2
# Question
Which of these is not part of the scrum workflow ?
# Answers
Sprint
Sprint Planning
Team Brunch
Daily Scrum
Sprint Review
Sprint Retrospective
# Correct Answer
3
# Question
What is the Definition of Done?
# Answers
The Criteria to determine whether work on sprint backlog item is complete
The Product which has been produced at the end of the Sprint
When the developer is fed up of working on a feature
# Correct Answer
1
# Question
Which of these is not a Scrum Value?
# Answers
Commitment
Courage
Focus
Freedom
Openness
Respect
# Correct Answer
4
# Question
The length for a daily scrum should be?
# Answers
30 minutes
15 minutes
10 minutes
1 hour
45 minutes
# Correct Answer
2
\ No newline at end of file
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class LessonReader {
/*
This class reads a text file and creates a lesson from it. The text file needs to be a certain structure. The structure
is clearly defined in the ReadMe. This class has been designed so that the quiz for a lesson can have a variable amount
of questions and these questions can have a variable amount of answers related to them.
Please Note: If the Text File is not written how it's specified in the ReadMe this class may fail. However, it does
have fall back values so that the user will see that the lesson has not been inputted correctly.
*/
/**
* Converts a text file to an ArrayList<String> line by line, each line being a new entry
* @param fileName In the form "fileName.txt"
* @return Text File as ArrayList<String>
*/
public ArrayList<String> createArrayListFromTextFile(String fileName) {
Scanner scanner = null;
ArrayList<String> stringArrayList = new ArrayList<>();
try {
scanner = new Scanner(new BufferedReader(new FileReader(fileName)));
while (scanner.hasNext()){
stringArrayList.add(scanner.nextLine());
}
} catch (IOException e) {
System.err.println(e.getMessage());
} finally {
scanner.close();
}
return stringArrayList;
};
/**
* Creates a lesson from the Text File that you give it, Text file must be formatted a specific
* way, this can be found in the ReadMe.
* @param fileName in the form "fileName.txt"
* @return Lesson object built from text file
*/
public Lesson createLessonFromTextFile(String fileName) {
/* Create the variables needed to build a lesson and give them fallback values
if the text file provided is empty.
*/
String lessonTitle = "This lesson doesn't have a title";
String lessonText = "This lesson doesn't have any text";
String questionString = "";
int correctAnswer = 1;
// Scans in the text file and gives the function the ArrayList to work with
ArrayList<String> textArray = createArrayListFromTextFile(fileName);
/* The answers input for a Question object and the questionsArray input for a Lesson object
both require the data in an array, however to make the program more flexible and resilient and allow different
amounts of answers and questions these are originally initialised as ArrayLists and then converted
*/
ArrayList<String> answersArrayList = new ArrayList<>();
ArrayList<Question> questionsArrayList = new ArrayList<>();
// Array is looped through to get the title and Lesson text
for(int i = 0; i < textArray.size(); i++) {
if(textArray.get(i).equals("## Title")) {
lessonTitle = textArray.get(i + 1);
}
if(textArray.get(i).equals("## Lesson Text")) {
lessonText = textArray.get(i + 1);
}
if(textArray.get(i).equals("## Questions")) {
/* Once Array gets to the Questions a second loop is created so that each question can
be created separately, this allows for the text file to have different amounts of questions
*/
for(int j = i; j < textArray.size(); j++) {
if (textArray.get(j).equals("# Question")) {
questionString = textArray.get(j + 1);
}
if (textArray.get(j).equals("# Answers")) {
/*
A while loop goes through the answers adding them to the answersArrayList,
This allows for each question to have a different amount of answers
Design Decision: Though having multiple loops inside each other is bad practice
it is unlikely that a text file will get to the size where this has any negative performance
impact and allowing different questions to have different amounts of answers
adds to the programs' user experience and flexibility.
*/
boolean endOfAnswers = false;
while(!endOfAnswers) {
j += 1;
if(textArray.get(j).equals("# Correct Answer")) {
correctAnswer = Integer.parseInt(textArray.get(j + 1));
endOfAnswers = true;
} else {
answersArrayList.add(textArray.get(j));
}
}
// Converts an Array List into an array
String[] answerArray = new String[answersArrayList.size()];
answerArray = answersArrayList.toArray(answerArray);
// Creates the Question and adds it to question Array
Question question = new Question(questionString, answerArray, correctAnswer);
questionsArrayList.add(question);
// Removes the answers to the previous question so the array List can be reused
answersArrayList.clear();
}
}
}
}
// Converts the ArrayList of Questions to an Array which can be used to create the lesson
Question[] questionArray = new Question[questionsArrayList.size()];
questionArray = questionsArrayList.toArray(questionArray);
// Creates the Lesson and returns it so that it can be used in the program
Lesson lesson = new Lesson(lessonTitle,lessonText, questionArray);
return lesson;
}
}
public class Module {
/*
This class holds the lesson objects and enables the user to pick from them. It has been designed so that it
can be replicated and reused to add a Courses class to the program. This is expanded upon in the ReadMe.
*/
private Lesson[] lessons;
public Module(Lesson[] lessons) {
this.lessons = lessons;
}
// GETTER METHODS
/**
* Returns a lesson from the Lesson array depending on User input
* User starts choice at 1 rather than 0 so this needs to be translated to arrays with base 0
* @param choice
* @return Lesson object from array at choice - 1
*/
public Lesson getLesson(int choice) {
return lessons[choice - 1];
}
// Rather than have a getter and then call .length on it, it has been combined here for readability.
public int getLessonsArrayLength() {
return lessons.length;
}
// END GETTER METHODS
/**
* Loops through the array printing out each lesson
* Also prints out the user instruction based on the number of lessons in the module
*/
public void listAll() {
// Lesson Menu Title
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | LESSONS | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" Please pick from one of the lessons below: ");
System.out.println(" ");
// Empty Strings declared which will be used to build the userInstruction string
String userInstruction = "";
String numberToChooseLesson = "";
/* Loops through the lesson array printing out the titles along with a lesson number
that users can to press to access their chosen lesson
*/
for(int i = 0; i < lessons.length; i++) {
System.out.println("[" + (i + 1) + "] " + lessons[i].getLessonTitle());
/* If it is the last lesson to add to the userInstruction String then the String needs to
include the closing bracket
*/
if(i != lessons.length - 1) {
numberToChooseLesson = (i + 1) + ", ";
} else {
numberToChooseLesson = (i + 1) + "):";
}
userInstruction = userInstruction + numberToChooseLesson;
}
System.out.println("By pressing the corresponding number (" + userInstruction);
};
}
public class Question {
/*
This class creates a Question which can be presented to the user.
It has been designed so that the question can have as many answers
as you wish to present to the user.
*/
private String question;
private String[] answers;
private int correctAnswer;
/**
* Basic all arguments Constructor
* @param question Just include the question String, no question number or punctuation before
* @param answers Just include the answer String, no answer number or punctuation before
* @param correctAnswer Add an int relating to the position of the correct answer based on array starting at 1, not 0.
* (E.G. if you have 4 answers and the correct one is number 3 then use 3.)
*/
public Question(String question, String[] answers, int correctAnswer) {
this.question = question;
this.answers = answers;
this.correctAnswer = correctAnswer;
}
/**
* Prints the Question for the user, the user can then pick an answer.
* <p>
* Returns a Boolean, true = user answered correctly, false = user answered incorrectly.
* @param questionNumber used to format the question string displayed to the user.
*/
public boolean askQuestion(int questionNumber) {
/* Design decision. This was a choice between using a bool to represent correct or incorrect
or using 1 to represent a correct answer and 0 for an incorrect answer. I decided on a boolean so that it
reduces the use of "Magic Numbers" in the code, and it makes the code more resilient changes.
*/
// Prints question with corresponding number
System.out.println("Question " + questionNumber + ": " + question);
System.out.println(" ");
// Empty Strings declared which will be used to build the userInstruction string
String userInstruction = "";
String numberToChooseLesson = "";
// Prints out the answers with their corresponding number and adds it to the userInstruction string
for(int i = 0; i < answers.length; i++) {
System.out.println((i + 1) + ". " + answers[i]);
/* Check if it is the last answer, if so the string that is added to the userInstruction
changes to represent this.
*/
if(i != answers.length - 1) {
numberToChooseLesson = (i + 1) + ", ";
} else {
numberToChooseLesson = (i + 1) + "):";
}
userInstruction = userInstruction + numberToChooseLesson;
}
// Prints out the userInstruction string with all the valid choices a user can make
System.out.println(" ");
System.out.println("Choose your answer by pressing the corresponding number (" + userInstruction);
// Takes in the user input and checks if they got it right and then returns a boolean based on that
int userChoice = ScannerExtension.scanForUserIntChoice(answers.length);
if(userChoice == correctAnswer) {
System.out.println("Correct!");
return true;
} else {
System.out.println("Incorrect");
}
return false;
};
}
public class QuizSystem {
/*
This class is the heart of the Quiz and is where the main method is run from, it contains the vast majority of
the logic for how the user navigates through the quiz and contains the styling to make the quiz more readable rather
than just having a block of text in the command line. This class both initialises the vast majority of the data and
contains the code logic for it, a discussion of why this decision has been made is written below.
*/
public static void main(String[] args) {
// Welcome message, shown once to users when quiz starts
System.out.println(" ");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | Welcome to the MSc Software Engineering Quiz | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" Simon Barrett (C1218123) 2021");
// QUIZ AND DATA SET UP
/* Create a boolean which is used to keep the quiz repeating itself and the storage to contain users
completion data */
boolean continueWithQuiz = true;
UsersStorage users = new UsersStorage();
// Create all the lessons and add them to the module array to use
LessonReader lessonReader = new LessonReader();
Lesson htmlLesson = lessonReader.createLessonFromTextFile("HTMLLesson.txt");
Lesson scrumLesson = lessonReader.createLessonFromTextFile("ScrumLesson.txt");
Lesson cssLesson = lessonReader.createLessonFromTextFile("CSSLesson.txt");
Lesson dataTypesLesson = lessonReader.createLessonFromTextFile("DataTypes.txt");
Lesson oopLesson = lessonReader.createLessonFromTextFile("OOP.txt");
Lesson keywordsLesson = lessonReader.createLessonFromTextFile("Keywords.txt");
Lesson[] cmt652LessonsArray = {htmlLesson, cssLesson, scrumLesson, dataTypesLesson,oopLesson,keywordsLesson};
Module cmt652 = new Module(cmt652LessonsArray);
// END QUIZ AND DATA SETUP
// Quiz will repeat itself until the user chooses to end it.
// continueWithQuiz can be changed by the output from checkUserDecision()
while (continueWithQuiz) {
// Value set to false so that main menu loops until user chooses to view the lesson
boolean goToLesson = false;
/*
Design Decision: The code has been broken up into 4 methods as listed below the main method. This is to
increase readability, and make the logic easier to follow. It is also so that when code is changed in one
method it is easier to see if and where the code breaks and to maintain a better separation of code. This is
instead of having all the code inside the while loop where it could get confusing.
The methods could also be removed from this Class and put into their own class if the program got larger,
however at this stage I don't think it's necessary. It is enough that they make it more readable.
*/
/*
Design Decision: The user has three options to choose from in the main menu which means that a boolean can't be
used for the user decision, even though this would be the preferred option as it makes the code more resilient and
harder for the next developer to make a mistake.
*/
int userDecision = checkUserDecision();
/* !!! CHECK THE BELOW NUMBERS AGAINST THE OUTPUTS for checkUserDecision BEFORE CHANGING THEM !!!!
User choice evaluated (these values have been hard-coded as it is unlikely the menu will change and if it does
then it will likely be refactored at that time), having "Magic numbers" is a known weakness of this code */
// User chooses to go to the lessons
if (userDecision == 1) {
goToLesson = true;
// User chooses to check progress, once user has checked progress it will loop back to the main menu
} else if (userDecision == 2) {
// Create Progress Banner
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | Check Your Progress | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println("Please type in your name to access your data, or (all) to print all user data");
ScannerExtension.viewUserData(users);
// User chooses to exit game
} else if (userDecision == 3) {
continueWithQuiz = false;
}
// If user has chosen to view the lessons then this logic is run
if(goToLesson) {
Lesson chosenLesson = chooseLessonToComplete(cmt652);
String userName = checkIfUserWantsToDoQuiz(chosenLesson);
addUserProgressToCompletionData(users, userName, chosenLesson);
}
}
// Styling shown to user when they exit
System.out.println(" ");
System.out.println(" + ----------------------------------------------------------- +");
System.out.println(" + | Thank you for playing the MSc Software Engineering Quiz | +");
System.out.println(" + | Have a great day!!! | +");
System.out.println(" + ----------------------------------------------------------- +");
}
// 4 MAIN CONTROL FLOW METHODS
/**
* Checks if user wants to continue quiz, see their completion data or see everyone's completion data.
* @return 1 = to go to lessons, 2 = go to data, 3 = exit game
*/
public static int checkUserDecision() {
// Create Main Menu text
System.out.println(" ");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | MAIN MENU | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" Please pick from one of the options:");
System.out.println(" ");
// Create a list from user to choose from
/*
DO NOT CHANGE THESE NUMBERS WITHOUT CHECKING THE IF/ELSE STATEMENT AFTER THE METHOD IS CALLED
*/
System.out.println("[1] See the list of lessons");
System.out.println("[2] Check your progress");
System.out.println("[3] Exit Game");
System.out.println("By pressing the corresponding number (1, 2, 3):");
// User makes choice
int userDecision = ScannerExtension.scanForUserIntChoice(3);
return userDecision;
}
/**
* Lists all the lessons in the module, user chooses lesson, user is shown lesson
* @param module contains the data needed to run the quiz
* @return Returns the users Chosen Lesson Object
*/
public static Lesson chooseLessonToComplete(Module module) {
// List all the Lessons in the module, User inputs lesson choice and this is saved as a variable
module.listAll();
int choice = ScannerExtension.scanForUserIntChoice(module.getLessonsArrayLength());
Lesson chosenLesson = module.getLesson(choice);
// Styled header so it is easy to see where the lesson begins
System.out.println(" + ------------------------------------------------ +");
System.out.println(" + | LESSON | +");
System.out.println(" + ------------------------------------------------ +");
System.out.println(" ");
// Print out users chosen lesson and return the variable
chosenLesson.printLesson();
return chosenLesson;
}
/**
* Checks if user wishes to do the quiz, user does the quiz and has their score updated, or
* is taken back to the main menu if they don't want to do the quiz.
* @param chosenLesson
* @return Returns the username which the player used to record their progress
*/
public static String checkIfUserWantsToDoQuiz(Lesson chosenLesson) {
// Ask user if they want to do the quiz, and check users decision
System.out.println("Would you like to complete the quiz now? Type 'y' (yes) or 'n' (no): ");
String userName = "";
String nextString = ScannerExtension.chooseYorN();
// Decision based on users choice, y = users does the quiz, n = user taken back to main menu
// Username is taken in both cases and a different string is shown based on user decision
if (nextString.equals("y")) {
// User does the quiz. Score and quiz completion is updated on the lesson object
chosenLesson.setQuizScore(chosenLesson.doQuiz());
chosenLesson.setQuizCompleted(true);
System.out.println("Please enter your name (in lowercase) to record that you have completed the lesson and the quiz: ");
userName = ScannerExtension.scanStringToLowercase();
System.out.println("Record of Lesson + Quiz Completion and Quiz Score saved under username: " + userName);
} else if (nextString.equals("n")) {
System.out.println("Please enter your name (in lowercase) to record that you have completed the lesson: ");
userName = ScannerExtension.scanStringToLowercase();
System.out.println("Record of Lesson Completion saved under username: " + userName);
System.out.println(" ");
}
System.out.println(" ");
// Output the username so that it can be used to save User completion data
return userName;
}
/**
* Either adds user progress to their data, or adds a new user to the UserStorage
* @param users UserStorage for the program
* @param userName Username give by user to store their data
* @param chosenLesson Lesson object data you wish to store
*/
public static void addUserProgressToCompletionData(UsersStorage users, String userName, Lesson chosenLesson) {
// Add User progress to UserStorage
int userExists = users.checkIfUserExists(userName);
// Create a user and add to storage if they don't already exist
if (userExists == -1) {
User recordCurrentIteration = new User(userName);
recordCurrentIteration.addToUserRecord(chosenLesson);
users.add(recordCurrentIteration);
} else {
// Add to existing users data
users.getUsers().get(userExists).addToUserRecord(chosenLesson);
}
}
}
\ No newline at end of file
import java.util.ArrayList;
import java.util.Scanner;
public class ScannerExtension {
/* Design Decision: This extension file has been designed so that all scanner logic is held in one place
and future developers know exactly where to look if there is something wrong with a scanner.
The middle two scanners are needed to achieve specific goals but have been designed to have a level of
reusability and been given method names to make it clear what goal they achieve.
The last scanner is very specific to the method which calls it but despite the cohesion it has been placed
in this file so that all the scanner logic for the program stays together.
I have added these Scanner extensions so that the user is unable to crash the program by typing incorrect
information, thus creating a better user experience and making the program more resilient.
These Self-Contained methods are static so that you do not need to create a new class everytime we need to use one.
*/
public static Scanner scanner = new Scanner(System.in);
/**
* Takes in a string from the scanner and converts it to lower case
* @return lower case version of the string entered into the scanner
*/
public static String scanStringToLowercase() {
String nextString = scanner.next();
nextString = nextString.toLowerCase();
return nextString;
}
/*
Known Edge Case: For the below method if you type an incorrect int followed by a letter it crashes
the program. This will be fixed in future editions.
*/
/**
* Extends Scanner to include error handling so that a user can only pick an integer in the given range
* <p>
* Method will keep asking for a user choice until user has picked a valid integer
* @param totalChoices User can pick a number from 1 - totalChoices (inclusive).
* @return Users integer choice
*/
public static int scanForUserIntChoice(int totalChoices) {
boolean correctEntry = false;
// Prevents a user from entering a non-integer and asks them to pick again
while (scanner.hasNextInt() == false) {
scanner.next();
System.out.println("Incorrect entry! Please choose from one of the options above.");
}
int nextInt = scanner.nextInt();
while (!correctEntry) {
// Scanner will keep looping until the user has entered a valid choice
if(nextInt <= totalChoices && nextInt > 0) {
correctEntry = true;
} else {
System.out.println("Incorrect entry! Please choose from one of the options above.");
nextInt = scanner.nextInt();
}
}
// Return a valid choice which has been error handled so program won't crash
return nextInt;
}
/**
* User can choose between y or n, this will be converted to lowerCase so Y and N work as well
* <p>
* Method will keep asking for a user choice until they pick a correctEntry
* @return y or n
*/
public static String chooseYorN() {
boolean correctEntry = false;
String nextString = scanner.next();
/* Convert user input to lowercase and check if they have entered y or n,
Loop will continue until user makes one of those two choices
*/
nextString = nextString.toLowerCase();
while (!correctEntry) {
if(nextString.equals("y") || nextString.equals("n")) {
correctEntry = true;
} else {
System.out.println("Incorrect entry! Please choose 'y' or 'n'.");
nextString = scanner.next();
nextString = nextString.toLowerCase();
}
}
return nextString;
}
/**
*User can type in all to see all users data or theirs own name to check their data
*<p>
*If the name the user inputs doesn't match any data in the UserCompletionData then user can try another
*name or press x to exit and go back to the main menu
* @param users UserStorage object for user input from scanner to be checked against
*/
public static void viewUserData(UsersStorage users) {
String nextString = scanner.next();
nextString = nextString.toLowerCase();
// Checks if string equals all, if so it prints out all user data
if(nextString.equals("all")) {
users.printAllUsersData();
} else {
/*
If the user didn't type all then the input will be checked to see if the username has data attached to it
Loop will keep going until a correct username is given or the user decides to exit by pressing x.
*/
boolean correctEntry = false;
while (!correctEntry){
int userExists = users.checkIfUserExists(nextString);
if(userExists == -1) {
System.out.println("This user doesn't exist. Please enter another username or 'x' to exit.");
nextString = scanner.next();
nextString = nextString.toLowerCase();
if(nextString.equals("x")) {
correctEntry = true;
}
} else {
ArrayList<Lesson> userRecord= users.getUsers().get(userExists).getUserRecord();
System.out.println(nextString + ":");
for(int i = 0; i < userRecord.size(); i++) {
System.out.println(users.printOutUserCompletionDataForLesson(userRecord.get(i)));
}
correctEntry = true;
}
}
}
}
}
import java.util.ArrayList;
public class User {
/*
Class to represent a User, includes the User's name and a record of which
lessons, quizzes and scores they have completed.
*/
private String username;
private ArrayList<Lesson> userRecord;
public User(String username) {
this.username = username;
this.userRecord = new ArrayList<>();
}
// GETTER METHODS
public String getUsername() {
return username;
}
public ArrayList<Lesson> getUserRecord() {
return userRecord;
}
// END GETTER METHODS
// CUSTOM METHODS
/**
* Checks the Users record to see if they have already completed the lesson and/or quiz for that Lesson
* object. If not then their record is updated to show what they have done for that Lesson.
* @param currentLesson
*/
public void addToUserRecord(Lesson currentLesson) {
boolean inUserRecord = false;
int lessonsPlaceInRecord = 0;
// Check to see if currentLesson is in the user record already
for(int i = 0; i < userRecord.size(); i++) {
if(userRecord.get(i).getLessonTitle().equals(currentLesson.getLessonTitle())){
inUserRecord = true;
lessonsPlaceInRecord = i;
}
}
// Update or create the lesson in the user record
if(inUserRecord) {
userRecord.get(lessonsPlaceInRecord).setQuizScore(currentLesson.getQuizScore());
} else {
userRecord.add(currentLesson);
}
}
}
import java.util.ArrayList;
public class UsersStorage {
/*
This class stores a list of the Custom object User to record each user's progress while the program is running.
It has been put into its own class due to the need to have some custom methods to interact with the storage.
*/
private ArrayList<User> users;
public UsersStorage() {
this.users = new ArrayList<>();
}
// GETTER METHODS
public ArrayList<User> getUsers() {
return users;
}
// END GETTER METHODS
// CUSTOM METHODS
/**
* Adds a user to the Storage ArrayList
* @param user Custom User object
*/
public void add(User user) {
users.add(user);
}
/**
* Check if the username entered already exists in Storage ArrayList
* @param username Username you want to check
* @return Returns -1 if the user doesn't exist, or returns the users place in the Storage ArrayList if they do
*/
public int checkIfUserExists(String username) {
for(int i = 0; i < users.size(); i++){
String userNameInStorage = users.get(i).getUsername();
if(userNameInStorage.equals(username)) {
return i;
}
}
return -1;
}
/**
* Returns a string to display to the user based on if the user has completed just the lesson
* or the lesson and the quiz and prints the score if applicable
* @return Custom String based on input
*/
public String printOutUserCompletionDataForLesson(Lesson lesson) {
String lessonTitle = lesson.getLessonTitle();
if(lesson.isQuizCompleted() == false) {
return "Has completed the lesson for " + lessonTitle + " but not the quiz.";
} else {
return "Has completed the lesson and quiz for " + lessonTitle + ", with a score of " + lesson.getQuizScore() + "/" + lesson.getQuestionArrayLength() + ".";
}
}
/*
Design Decision: The method below is not strictly necessary but has been included so that it is easy to check if
the storage is working. Removing it could simplify the Program, Class and related ScannerExtension.
*/
/**
* Prints out all the data in the Storage Array List
*/
public void printAllUsersData() {
for(int i = 0; i < users.size(); i++) {
/* Get a user from the array and loop over their record printing out each lesson,
quiz and quiz score stored for them.
Repeat this for every user stored in Storage ArrayList
*/
User currentUser = users.get(i);
System.out.println(currentUser.getUsername() + ": ");
for (int j = 0; j < currentUser.getUserRecord().size(); j++) {
System.out.println(printOutUserCompletionDataForLesson(currentUser.getUserRecord().get(j)));
}
/*
Design Decision: Though having two nested arrays results in O(i * j) it is unlikely in this program that
the arrays would get big enough for this to cause a performance issue. However, if the program was to grow
it may be worth looking at more efficient ways to do this.
*/
}
// Fallback string, to be shown if no user data has been entered but user asks to see all user data.
if(users.size() == 0) {
System.out.println("No user data is stored at this time.");
}
}
}
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment