TIC2002 (2018)
  • Flat (current format)
  •     Nested
  • Schedule
  • Textbook
  • Admin Info
  • Report Bugs
  • Slack
  • Forum
  • Instructors
  • Announcements
  • File Submissions
  • Tutorial Schedule
  • Team IDs
  • Java Coding Standard
  • samplerepo-things
  • Addressbook-level1
  • Addressbook-level2
  • Addressbook-level3
  • Addressbook-level4
  • Projects List
  • Week 6 [Sep 17]

    Todo

    Admin info to read:

    Admin Appendix B (Policies) → Policy on suggested length for submissions

    Policy on suggested length for submissions

    We don't usually give a strict page limit for documents such as User Guide and the Developer Guide. You need to decide yourself how long the document should be based on the purpose and the intended audience. You can determine the level of details required based on the samples we provide.

    Admin Appendix C (FAQs) → Why very narrow project scope?

    Why very narrow project scope?

    Defining your own unique project is more fun.

    But, wider scope → more diverse projects → harder for us to go deep into your project. The collective know-how we (i.e., students and the teaching team) have built up about SE issues related to the project become shallow and stretched too thinly. It also affects fairness of grading.

    That is why a strictly-defined project is more suitable for a first course in SE that focuses on nuts-and-bolts of SE. After learning those fundamentals, in higher level project modules you can focus more on the creative side of software projects without being dragged down by nuts-and-bolts SE issues (because you already know how to deal with them). However, we would like to allow some room for creativity too. That is why we let you build products that are slight variations of a given theme.

    Also note: The freedom to do 'anything' is not a necessary condition for creativity. Do not mistake being different for being creative. In fact, the more constrained you are, the more you need creativity to stand out.

    Admin Appendix C (FAQs) → Why project requirements are so vague?

    Why project requirements are so vague?

    "You tell me exactly what to do - I do that - you pay me (in grades)" is a model for contract work, not for learning. Being able to survive in imprecise, uncertain, volatile problem contexts is precisely what we are trying to teach you.

    For example, the best way to communicate something often depends on what is being communicated. That is why we don't specify the precise content for project documents. Instead, we aim to refine project documents iteratively. We believe the learning experience will be richer if we let you decide the best way to present your project information rather than just following our instructions blindly. For example, in real-life projects you are rarely told which diagrams to draw; that is a decision you have to make yourself.

    Outcomes

    Implementation

    W6.1 Can use Java constants W6.1a Can use Java constants

    C++ to Java → Miscellaneous Topics →

    Constants

    Java does not directly support constants. The convention is to use a static final variable where a constant is needed. The static modifier causes the variable to be available without instantiating an object. The final modifier causes the variable to be unchangeable. Java constants are normally declared in ALL CAPS separated by underscores.

    Here is an example of a constant named MAX_BALANCE which can be accessed as Account.MAX_BALANCE.

    public class Account{
    
      public static final double MAX_BALANCE = 1000000.0;
    
    }
    

    Math.PI is an example constant that comes with Java.

    W6.2 Can use Java enumerations W6.2a Can explain the meaning of enumerations

    Paradigms → Object Oriented Programming → Classes →

    Enumerations

    An Enumeration is a fixed set of values that can be considered as a data type. An enumeration is often useful when using a regular data type such as int or String would allow invalid values to be assigned to a variable. You are recommended to enumeration types any time you need to represent a fixed set of constants.

    Suppose you want a variable to store the priority of something. There are only three priority levels: high, medium, and low. You can declare the variable as of type int and use only values 2, 1, and 0 to indication the three priority levels. However, this opens the possibility of an invalid values such as 9 to be assigned to it. But if you define an enumeration type called Priority that has three values HIGH, MEDIUM, LOW only, a variable of type Priority will never be assigned an invalid value because the compiler is able to catch such an error.

    Priority: HIGH, MEDIUM, LOW

    W6.2b Can use Java enumerations

    C++ to Java → Miscellaneous Topics →

    Enums

    You can define an enum type by using the enum keyword. Because they are constants, the names of an enum type's fields are in uppercase letters e.g., FLAG_SUCCESS.

    Defining an enumeration to represent days of a week (code to be put in the Day.java file):

    public enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY
    }
    

    Some examples of using the Day enumeration defined above:

    Day today = Day.MONDAY;
    Day[] holidays = new Day[]{Day.SATURDAY, Day.SUNDAY};
    
    switch (today) {
    case SATURDAY:
    case SUNDAY:
        System.out.println("It's the weekend");
        break;
    default:
        System.out.println("It's a week day");
    }
    

    Note that while enumerations are usually a simple set of fixed values, Java enumerations can have behaviors too, as explained in this tutorial from -- Java Tutorial

    Define an enumeration named Priority. Add the missing describe method to the code below so that it produces the output given.

    public class Main {
    
        // Add your method here
    
        public static void main(String[] args) {
            describe("Red", Priority.HIGH);
            describe("Orange", Priority.MEDIUM);
            describe("Blue", Priority.MEDIUM);
            describe("Green", Priority.LOW);
        }
    }
    

    Red indicates high priority
    Orange indicates medium priority
    Blue indicates medium priority
    Green indicates low priority
    

    Use a switch statement to select between possible values for Priority.

        public static void describe(String color, Priority p) {
            switch (p) {
                case LOW:
                    System.out.println(color + " indicates low priority");
                    break;
                // ...
            }
        }
    

    Code for the enumeration is given below:

    public enum Priority {
        HIGH, MEDIUM, LOW
    }
    

    Evidence:

    The ability to do exercises such as,

    Define an enumeration named Priority. Add the missing describe method to the code below so that it produces the output given.

    public class Main {
    
        // Add your method here
    
        public static void main(String[] args) {
            describe("Red", Priority.HIGH);
            describe("Orange", Priority.MEDIUM);
            describe("Blue", Priority.MEDIUM);
            describe("Green", Priority.LOW);
        }
    }
    

    Red indicates high priority
    Orange indicates medium priority
    Blue indicates medium priority
    Green indicates low priority
    

    Use a switch statement to select between possible values for Priority.

        public static void describe(String color, Priority p) {
            switch (p) {
                case LOW:
                    System.out.println(color + " indicates low priority");
                    break;
                // ...
            }
        }
    

    Code for the enumeration is given below:

    public enum Priority {
        HIGH, MEDIUM, LOW
    }
    
    W6.3 Can read/write files using Java W6.3a Can read/write text files using Java

    C++ to Java → Miscellaneous Topics →

    File Access

    You can use the java.io.File class to represent a file object. It can be used to access properties of the file object.

    This code creates a File object to represent a file fruits.txt that exists in the data directory relative to the current working directory and uses that object to print some properties of the file.

    import java.io.File;
    
    public class FileClassDemo {
    
        public static void main(String[] args) {
            File f = new File("data/fruits.txt");
            System.out.println("full path: " + f.getAbsolutePath());
            System.out.println("file exists?: " + f.exists());
            System.out.println("is Directory?: " + f.isDirectory());
        }
    
    }
    

    full path: C:\sample-code\data\fruits.txt
    file exists?: true
    is Directory?: false
    

    If you use backslash to specify the file path in a Windows Computer, you need to use an additional backslash as an escape character because the backslash by itself has a special meaning. e.g., use "data\\fruits.txt", not "data\fruits.txt". Alternatively, you can use forward slash "data/fruits.txt" (even on Windows).

    You can read from a file using a Scanner object that uses a File object as the source of data.

    This code uses a Scanner object to read (and print) contents of a text file line-by-line:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    public class FileReadingDemo {
    
        private static void printFileContents(String filePath) throws FileNotFoundException {
            File f = new File(filePath); // create a File for the given file path
            Scanner s = new Scanner(f); // create a Scanner using the File as the source
            while (s.hasNext()) {
                System.out.println(s.nextLine());
            }
        }
    
        public static void main(String[] args) {
            try {
                printFileContents("data/fruits.txt");
            } catch (FileNotFoundException e) {
                System.out.println("File not found");
            }
        }
    
    }
    

    i.e., contents of the data/fruits.txt

    5 Apples
    3 Bananas
    6 Cherries
    

    You can use a java.io.FileWriter object to write to a file.

    The writeToFile method below uses a FileWrite object to write to a file. The method is being used to write two lines to the file temp/lines.txt.

    import java.io.FileWriter;
    import java.io.IOException;
    
    public class FileWritingDemo {
    
        private static void writeToFile(String filePath, String textToAdd) throws IOException {
            FileWriter fw = new FileWriter(filePath);
            fw.write(textToAdd);
            fw.close();
        }
    
        public static void main(String[] args) {
            String file2 = "temp/lines.txt";
            try {
                writeToFile(file2, "first line" + System.lineSeparator() + "second line");
            } catch (IOException e) {
                System.out.println("Something went wrong: " + e.getMessage());
            }
        }
    
    }
    

    Contents of the temp/lines.txt:

    first line
    second line
    

    Note that you need to call the close() method of the FileWriter object for the writing operation to be completed.

    You can create a FileWriter object that appends to the file (instead of overwriting the current content) by specifying an additional boolean parameter to the constructor.

    The method below appends to the file rather than overwrites.

    private static void appendToFile(String filePath, String textToAppend) throws IOException {
        FileWriter fw = new FileWriter(filePath, true); // create a FileWriter in append mode
        fw.write(textToAppend);
        fw.close();
    }
    

    The java.nio.file.Files is a utility class provides several useful file operations. It relies on the java.nio.file.Paths file to generate Path objects that represent file paths.

    This example uses the Files class to copy a file and delete a file.

    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    
    public class FilesClassDemo {
    
        public static void main(String[] args) throws IOException{
            Files.copy(Paths.get("data/fruits.txt"), Paths.get("temp/fruits2.txt"));
            Files.delete(Paths.get("temp/fruits2.txt"));
        }
    
    }
    

    The techniques above are good enough to manipulate simple text files. Note that it is also possible to perform file I/O operations using other classes.

    This exercise continues from the TaskManager Level 1-4 exercises quoted above.

    Enhance the TaskManager to store tasks in a text file between runs:

    1. The text file can follow a format of your choice. For example, each line can represent one task. The attributes can be separated using a suitable delimiter.
      Here is an example format:
      T | 1 | read book
      D | 0 | return book | June 6th
      T | 1 | join sports club
      
      • In the above example | is used as a delimiter, T → Todo, D → Deadline, 1 → task done, 0 → task not done.
      • 💡 If you use | as the delimiter, use split("\\|") to split the line into its parts. split("|") will not work because | has a special meaning when used in this context.
    2. Load all tasks in the text file to the memory (i.e., convert to Task objects) at the start up of TaskManager. You can assume the data are in a predetermined file e.g., data/tasks.txt.
    3. Save all tasks to the text file every time there is a change to the data. Alternatively, you can introduce a new command to save tasks to the text file.

    Here's an example method for loading data from the text file. Use this method at the start of your main method to load the tasks from the text file.

        private static List<Task> getTasksFromFile() {
            List<Task> loadedTasks = new ArrayList<>();
            try {
                List<String> lines = getLines("data/tasks.txt");
                for (String line : lines) {
                    if (line.trim().isEmpty()) { //ignore empty lines
                        continue;
                    }
                    loadedTasks.add(createTask(line)); //convert the line to a task and add to the list
                }
            } catch (FileNotFoundException e) {
                printError("problem encountered while loading data: " + e.getMessage());
            }
            return loadedTasks;
        }
    

    Evidence:

    Any code that you have written to read from and write to files.

    Design

    W6.4 Can use intermediate-level class diagrams W6.4a Can use UML notes

    Tools → UML →

    Notes

    UML notes can augment UML diagrams with additional information. These notes can be shown connected to a particular element in the diagram or can be shown without a connection. The diagram below shows examples of both.

    Example:

    W6.4b Can specify constraints in UML diagrams

    Tools → UML →

    Constraints

    A constraint can be given inside a note, within curly braces. Natural language or a formal notation such as OCL (Object Constraint Language) may be used to specify constraints.

    Example:

    W6.4c Can show an association as an attribute

    Tools → UML → Class Diagrams →

    Associations as Attributes

    An association can be shown as an attribute instead of a line.

    Association multiplicities and the default value too can be shown as part of the attribute using the following notation. Both are optional.

    name: type [multiplicity] = default value

    The diagram below depicts a multi-player Square Game being played on a board comprising of 100 squares. Each of the squares may be occupied with any number of pieces, each belonging to a certain player.

    A Piece may or may not be on a Square. Note how that association can be replaced by an isOn attribute of the Piece class. The isOn attribute can either be null or hold a reference to a Square object, matching the 0..1 multiplicity of the association it replaces. The default value is null.

    The association that a Board has 100 Sqaures can be shown in either of these two ways:

    W6.4d Can use intermediate-level class diagrams

    Design → Modelling → Modelling Structure

    Class Diagrams - Intermediate

    A class diagram can also show different types of associations: inheritance, compositions, aggregations, dependencies.

    Modeling inheritance

    Modeling composition

    Modeling aggregation

    Modeling dependencies

    A class diagram can also show different types of class-like entities:

    Modeling enumerations

    Modeling abstract classes

    Modeling interfaces

    Which of these statements match the class diagram?

    • a. A Snake must belong to at least one Board.
    • b. A SnakeHeadSquare can contain only one Snake head.
    • c. A Square can contain a Snake head.
    • d. A Snake head can be in more than one SnakeHeadSquare
    • e. The Board has exactly 5 Snakes.

    (a)(b)(c)(d)(e)

    Explanation:

    (a) does not match because a Snake may or may not belong to a Board (multiplicity is 0..1)
    (b) matches the diagram because the multiplicity given in 1
    (c) matches the diagram because SnakeHeadSquare is a Square (due to inheritance)
    (d) matches the diagram because the multiplicity given is *
    (e) matches the diagram because the multiplicity given in 5

    Explain the meaning of various class diagram notations in the following class diagram:

    Consider the code below:

    public interface Billable {
        void bill();
    }
    
    public abstract class Item
             implements Billable {
        public abstract void print();
    }
    
    public class StockItem extends Item {
        private Review review;
        private String name;
    
        public StockItem(
            String name, Rating rating){
    
            this.name = name;
            this.review = new Review(rating);
        }
    
        @Override
        public void print() {
            //...
        }
    
        @Override
        public void bill() {
            //...
        }
    }
    
    public enum Rating {
        GOOD, OK, POOR
    }
    
    public class Review {
        private final Rating rating;
    
        public Review(Rating rating) {
            this.rating = rating;
        }
    }
    
    import java.util.List;
    
    public class Inventory {
        private List<Item> items;
    
        public int getItemCount(){
            return items.size();
        }
    
        public void generateBill(Billable b){
            // ...
        }
    
        public void add(Item s) {
            items.add(s);
        }
    }
    

    (a) Draw a class diagram to represent the code
    (b) Draw an object diagram to represent the situation where the inventory has one item with a name spanner and a review of POOR rating.

    🅿️ Project

    W6.5 Project preparation: Can use file access operations in a small project

    Enhance your TaskManager program as explained in the exercise below:

    This exercise continues from the TaskManager Level 1-4 exercises quoted above.

    Enhance the TaskManager to store tasks in a text file between runs:

    1. The text file can follow a format of your choice. For example, each line can represent one task. The attributes can be separated using a suitable delimiter.
      Here is an example format:
      T | 1 | read book
      D | 0 | return book | June 6th
      T | 1 | join sports club
      
      • In the above example | is used as a delimiter, T → Todo, D → Deadline, 1 → task done, 0 → task not done.
      • 💡 If you use | as the delimiter, use split("\\|") to split the line into its parts. split("|") will not work because | has a special meaning when used in this context.
    2. Load all tasks in the text file to the memory (i.e., convert to Task objects) at the start up of TaskManager. You can assume the data are in a predetermined file e.g., data/tasks.txt.
    3. Save all tasks to the text file every time there is a change to the data. Alternatively, you can introduce a new command to save tasks to the text file.

    Here's an example method for loading data from the text file. Use this method at the start of your main method to load the tasks from the text file.

        private static List<Task> getTasksFromFile() {
            List<Task> loadedTasks = new ArrayList<>();
            try {
                List<String> lines = getLines("data/tasks.txt");
                for (String line : lines) {
                    if (line.trim().isEmpty()) { //ignore empty lines
                        continue;
                    }
                    loadedTasks.add(createTask(line)); //convert the line to a task and add to the list
                }
            } catch (FileNotFoundException e) {
                printError("problem encountered while loading data: " + e.getMessage());
            }
            return loadedTasks;
        }
    

    Tutorial 6


    For W5.3b Can use the ArrayList class
    Details of the LO

    C++ to Java → Collections →

    The ArrayList Class

    The ArrayList class is a resizable-array implementation of the List interface. Unlike a normal array, an ArrayList can grow in size as you add more items to it. The example below illustrate some of the useful methods of the ArrayList class using an ArrayList of String objects.

    import java.util.ArrayList;
    
    public class ArrayListDemo {
    
        public static void main(String args[]) {
            ArrayList<String> items = new ArrayList<>();
    
            System.out.println("Before adding any items:" + items);
    
            items.add("Apple");
            items.add("Box");
            items.add("Cup");
            items.add("Dart");
            print("After adding four items: " + items);
    
            items.remove("Box"); // remove item "Box"
            print("After removing Box: " + items);
    
            items.add(1, "Banana"); // add "Banana" at index 1
            print("After adding Banana: " + items);
    
            items.add("Egg"); // add "Egg", will be added to the end
            items.add("Cup"); // add another "Cup"
            print("After adding Egg: " + items);
    
            print("Number of items: " + items.size());
    
            print("Index of Cup: " + items.indexOf("Cup"));
            print("Index of Zebra: " + items.indexOf("Zebra"));
    
            print("Item at index 3 is: " + items.get(2));
    
            print("Do we have a Box?: " + items.contains("Box"));
            print("Do we have an Apple?: " + items.contains("Apple"));
    
            items.clear();
            print("After clearing: " + items);
        }
    
        private static void print(String text) {
            System.out.println(text);
        }
    }
    

    Before adding any items:[]
    After adding four items: [Apple, Box, Cup, Dart]
    After removing Box: [Apple, Cup, Dart]
    After adding Banana: [Apple, Banana, Cup, Dart]
    After adding Egg: [Apple, Banana, Cup, Dart, Egg, Cup]
    Number of items: 6
    Index of Cup: 2
    Index of Zebra: -1
    Item at index 3 is: Cup
    Do we have a Box?: false
    Do we have an Apple?: true
    After clearing: []
    

    [Try the above code on Repl.it]

    Add the missing methods to the class given below so that it produces the output given.

    💡 Use an ArrayList to store the numbers.

    public class Main {
    
        //TODO: add your methods here
    
        public static void main(String[] args) {
            System.out.println("Adding numbers to the list");
            addNumber(3);
            addNumber(8);
            addNumber(24);
            System.out.println("The total is: " + getTotal());
            System.out.println("8 in the list : " + isFound(8) );
            System.out.println("5 in the list : " + isFound(5) );
            removeNumber(8);
            System.out.println("The total is: " + getTotal());
        }
    
    }
    

    Adding numbers to the list
    [3]
    [3, 8]
    [3, 8, 24]
    The total is: 35
    8 in the list : true
    5 in the list : false
    [3, 24]
    The total is: 27
    

    Partial solution:

    import java.util.ArrayList;
    
    public class Main {
        private static ArrayList<Integer> numbers = new ArrayList<>();
    
        private static void addNumber(int i) {
            numbers.add(Integer.valueOf(i));
            System.out.println(numbers);
        }
    
        // ...
    
    }
    

    This exercise continues from the TaskManager Level 1-3 exercises quoted above.

    Enhance the TaskManager in the following ways:

    1. Use a suitable Collection class to store tasks, instead of using an array.
    2. Introduce a done n command to mark the task at index n as done.

    Here is an example output:

    Welcome to TaskManager-Level4!
    Your task? todo read book
    Tasks in the list: 1
    Your task? deadline return book /by Friday
    Tasks in the list: 2
    Your task? print
    Tasks:
    [1] description: read book
    is done? No
    [2] description: return book
    is done? No
    do by: Friday
    Your task? done 1
    Tasks in the list: 2
    Your task? print
    Tasks:
    [1] description: read book
    is done? Yes
    [2] description: return book
    is done? No
    do by: Friday
    Your task?

    Suggestions:

    • Move the isDone variable to the Task class and provide a setDone(boolean) method.
    public class Task {
        protected String description;
        protected boolean isDone;
    
        // ...
    
        public void setDone(boolean isDone){
            this.isDone = isDone;
        }
    }
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class Main {
        static Scanner in = new Scanner(System.in);
        static List<Task> tasks = new ArrayList<>();
    
        public static void main(String[] args) {
            // ...
        }
    
        private static void addTodo(String line) throws TaskManagerException {
            //...
            tasks.add(new Todo(description));
            //...
        }
    
        private static void markAsDone(String line) {
            int index = Integer.parseInt(line.substring("done".length()).trim());
            tasks.get(index - 1).setDone(true);
            System.out.println("Tasks in the list: " + tasks.size());
        }
    
        private static void printTasks() {
            // ...
            for (int i = 0; i < tasks.size(); i++) {
                System.out.println("[" + (i + 1) + "] " + tasks.get(i));
            }
        }
    }
    


    Evidence:

    To be able to do exercises such as these:

    Add the missing methods to the class given below so that it produces the output given.

    💡 Use an ArrayList to store the numbers.

    public class Main {
    
        //TODO: add your methods here
    
        public static void main(String[] args) {
            System.out.println("Adding numbers to the list");
            addNumber(3);
            addNumber(8);
            addNumber(24);
            System.out.println("The total is: " + getTotal());
            System.out.println("8 in the list : " + isFound(8) );
            System.out.println("5 in the list : " + isFound(5) );
            removeNumber(8);
            System.out.println("The total is: " + getTotal());
        }
    
    }
    

    Adding numbers to the list
    [3]
    [3, 8]
    [3, 8, 24]
    The total is: 35
    8 in the list : true
    5 in the list : false
    [3, 24]
    The total is: 27
    

    Partial solution:

    import java.util.ArrayList;
    
    public class Main {
        private static ArrayList<Integer> numbers = new ArrayList<>();
    
        private static void addNumber(int i) {
            numbers.add(Integer.valueOf(i));
            System.out.println(numbers);
        }
    
        // ...
    
    }
    
    For W5.3c Can use the HashMap class
    Details of the LO

    C++ to Java → Collections →

    The HashMap Class

    HashMap is an implementation of the Map interface. It allows you to store a collection of key-value pairs. The example below illustrates how to use a HashMap<String, Point> to maintain a list of coordinates and their identifiers e.g., the identifier x1 is used to identify the point 0,0 where x1 is the key and 0,0 is the value.

    import java.awt.Point;
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashMapDemo {
        public static void main(String[] args) {
            HashMap<String, Point> points = new HashMap<>();
    
            // put the key-value pairs in the HashMap
            points.put("x1", new Point(0, 0));
            points.put("x2", new Point(0, 5));
            points.put("x3", new Point(5, 5));
            points.put("x4", new Point(5, 0));
    
            // retrieve a value for a key using the get method
            print("Coordinates of x1: " + pointAsString(points.get("x1")));
    
            // check if a key or a value exists
            print("Key x1 exists? " + points.containsKey("x1"));
            print("Key x1 exists? " + points.containsKey("y1"));
            print("Value (0,0) exists? " + points.containsValue(new Point(0, 0)));
            print("Value (1,2) exists? " + points.containsValue(new Point(1, 2)));
    
            // update the value of a key to a new value
            points.put("x1", new Point(-1,-1));
    
            // iterate over the entries
            for (Map.Entry<String, Point> entry : points.entrySet()) {
                print(entry.getKey() + " = " + pointAsString(entry.getValue()));
            }
    
            print("Number of keys: " + points.size());
            points.clear();
            print("Number of keys after clearing: " + points.size());
    
        }
    
        public static String pointAsString(Point p) {
            return "[" + p.x + "," + p.y + "]";
        }
    
        public static void print(String s) {
            System.out.println(s);
        }
    }
    

    Coordinates of x1: [0,0]
    Key x1 exists? true
    Key x1 exists? false
    Value (0,0) exists? true
    Value (1,2) exists? false
    x1 = [-1,-1]
    x2 = [0,5]
    x3 = [5,5]
    x4 = [5,0]
    Number of keys: 4
    Number of keys after clearing: 0
    

    [Try the above code on Repl.it]

    The class given below keeps track of how many people signup to attend an event on each day of the week. Add the missing methods so that it produces the output given.

    💡 Use an HashMap to store the number of entries for each day.

    public class Main {
        private static HashMap<String, Integer> roster = new HashMap<>();
    
        //TODO: add your methods here
    
        public static void main(String[] args) {
            addToRoster("Monday"); // i.e., one person signed up for Monday
            addToRoster("Wednesday"); // i.e., one person signed up for Wednesday
            addToRoster("Wednesday"); // i.e., another person signed up for Wednesday
            addToRoster("Friday");
            addToRoster("Monday");
            printRoster();
        }
    
    }
    

    Monday => 2
    Friday => 1
    Wednesday => 2
    

    Partial solution:

    import java.util.HashMap;
    import java.util.Map;
    
    public class Main {
        private static HashMap<String, Integer> roster = new HashMap<>();
    
        private static void addToRoster(String day) {
            if (roster.containsKey(day)){
                Integer newValue = Integer.valueOf(roster.get(day).intValue() + 1);
                roster.put(day, newValue);
            } else {
                roster.put(day, Integer.valueOf(1));
            }
        }
    
        // ...
    }
    


    Evidence:

    To be able to do exercises such as these:

    The class given below keeps track of how many people signup to attend an event on each day of the week. Add the missing methods so that it produces the output given.

    💡 Use an HashMap to store the number of entries for each day.

    public class Main {
        private static HashMap<String, Integer> roster = new HashMap<>();
    
        //TODO: add your methods here
    
        public static void main(String[] args) {
            addToRoster("Monday"); // i.e., one person signed up for Monday
            addToRoster("Wednesday"); // i.e., one person signed up for Wednesday
            addToRoster("Wednesday"); // i.e., another person signed up for Wednesday
            addToRoster("Friday");
            addToRoster("Monday");
            printRoster();
        }
    
    }
    

    Monday => 2
    Friday => 1
    Wednesday => 2
    

    Partial solution:

    import java.util.HashMap;
    import java.util.Map;
    
    public class Main {
        private static HashMap<String, Integer> roster = new HashMap<>();
    
        private static void addToRoster(String day) {
            if (roster.containsKey(day)){
                Integer newValue = Integer.valueOf(roster.get(day).intValue() + 1);
                roster.put(day, newValue);
            } else {
                roster.put(day, Integer.valueOf(1));
            }
        }
    
        // ...
    }
    
    For W5.4b Can use basic-level class diagrams
    Details of the LO

    Design → Modelling → Modelling Structure

    Class Diagrams (Basics)

    Classes form the basis of class diagrams.

    Associations are the main connections among the classes in a class diagram.

    The most basic class diagram is a bunch of classes with some solid lines among them to represent associations, such as this one.

    An example class diagram showing associations between classes.

    In addition, associations can show additional decorations such as association labels, association roles, multiplicity and navigability to add more information to a class diagram.

    Here is the same class diagram shown earlier but with some additional information included:

    Which association notatations are shown in this diagram?

    • a. association labels
    • b. association roles
    • c. association multiplicity
    • d. class names

    (a) (b) (c) (d)

    Explanation: '1’ is a multiplicity, ‘mentored by’ is a label, and ‘mentor’ is a role.

    Explain the associations, navigabilities, and multiplicities in the class diagram below:

    Draw a class diagram for the code below. Show the attributes, methods, associations, navigabilities, and multiplicities in the class diagram below:

    class Box {
        private Item[] parts = new Item[10];
        private Item spareItem;
        private Lid lid; // lid of this box
        private Box outerBox;
    
        public void open(){
            //...
        }
    }
    
    class Item {
        public static int totalItems;
    }
    
    class Lid {
        Box box; // the box for which this is the lid
    }
    


    Evidence:

    Explain the associations, navigabilities, and multiplicities in the class diagram below:

    Draw a class diagram for the code below. Show the attributes, methods, associations, navigabilities, and multiplicities in the class diagram below:

    class Box {
        private Item[] parts = new Item[10];
        private Item spareItem;
        private Lid lid; // lid of this box
        private Box outerBox;
    
        public void open(){
            //...
        }
    }
    
    class Item {
        public static int totalItems;
    }
    
    class Lid {
        Box box; // the box for which this is the lid
    }
    
    For W5.4c Can use basic object diagrams
    Details of the LO

    Design → Modelling → Modelling Structure

    Object Diagrams

    Object diagrams can be used to complement class diagrams. For example, you can use object diagrams to model different object structures that can result from a design represented by a given class diagram.

    This question is based on the following question from another topic:

    Draw a class diagram for the code below. Show the attributes, methods, associations, navigabilities, and multiplicities in the class diagram below:

    class Box {
        private Item[] parts = new Item[10];
        private Item spareItem;
        private Lid lid; // lid of this box
        private Box outerBox;
    
        public void open(){
            //...
        }
    }
    
    class Item {
        public static int totalItems;
    }
    
    class Lid {
        Box box; // the box for which this is the lid
    }
    

    Draw an object diagram to match the code. Include objects of all three classes in your object diagram.



    Evidence:

    Suppose we wrote a program to follow the class structure given in this class diagram:

    Draw object diagrams to represent the object structures after each of these steps below. Assume that we are trying to minimize the number of total objects.

    i.e. apply step 1 → [diagram 1] → apply step 2 on diagram 1 → [diagram 2] and so on.

    1. There are no persons.

    2. Alfred is the Guardian of Bruce.

    3. Bruce's contact number is the same as Alfred's.

    4. Alfred is also the guardian of another person. That person lists Alfreds home address as his home address as well as office address.

    5. Alfred has a an office address at Wayne Industries building which is different from his home address (i.e. Bat Cave).

    After step 2, the diagram should be like this:

    This question is based on the following question from another topic:

    Draw a class diagram for the code below. Show the attributes, methods, associations, navigabilities, and multiplicities in the class diagram below:

    class Box {
        private Item[] parts = new Item[10];
        private Item spareItem;
        private Lid lid; // lid of this box
        private Box outerBox;
    
        public void open(){
            //...
        }
    }
    
    class Item {
        public static int totalItems;
    }
    
    class Lid {
        Box box; // the box for which this is the lid
    }
    

    Draw an object diagram to match the code. Include objects of all three classes in your object diagram.

    For W5.5 Project preparation: Can use exceptions and collections in a small project

    Enhance your TaskManager program as explained in the exercise below:

    This exercise continues from the TaskManager Level 1-2 exercises quoted above.

    Enhance the TaskManager to print an error message if a command is missing parts. Use exceptions so that error detection and printing of error message happen at different places of code and the error information is passed between the two places using an Exception object.

    Here is an example output:

    Welcome to TaskManager-Level3!
    Your task? todo
    Error: Empty description for TODO
    Your task? todo read book
    Tasks in the list: 1
    Your task? print
    Tasks:
    [1] description: read book
    is done? No
    Your task?

    Suggested approach:

    • Create a TaskManagerException class that inherits the Exception class. Override the constructor that takes a String parameter so that you can specify the error information when you create a TaskManagerException object.
    • Throw a new TaskManagerException object when you detect some necessary information is missing in the command.
    • Catch that exception somewhere else and print the message inside the exception object.
    public class TaskManagerException extends Exception{
        public TaskManagerException(String message) {
            super(message);
        }
    }
    
        public static void main(String[] args) {
            // ...
            while (!isExit) {
                try {
                    line = getInput();
                    String command = line.split(" ")[0];
                    switch (command) {
                        case "todo":
                            addTodo(line);
                            break;
                        // ...
                    }
                } catch (TaskManagerException e) {
                    printError(e.getMessage());
                }
            }
            // ...
    
        }
    
        private static void addTodo(String line) throws TaskManagerException {
            String description = line.substring("todo".length()).trim();
            if (description.isEmpty()){
                throw new TaskManagerException("Empty description for TODO");
            }
            // ...
        }
    

    This exercise continues from the TaskManager Level 1-3 exercises quoted above.

    Enhance the TaskManager in the following ways:

    1. Use a suitable Collection class to store tasks, instead of using an array.
    2. Introduce a done n command to mark the task at index n as done.

    Here is an example output:

    Welcome to TaskManager-Level4!
    Your task? todo read book
    Tasks in the list: 1
    Your task? deadline return book /by Friday
    Tasks in the list: 2
    Your task? print
    Tasks:
    [1] description: read book
    is done? No
    [2] description: return book
    is done? No
    do by: Friday
    Your task? done 1
    Tasks in the list: 2
    Your task? print
    Tasks:
    [1] description: read book
    is done? Yes
    [2] description: return book
    is done? No
    do by: Friday
    Your task?

    Suggestions:

    • Move the isDone variable to the Task class and provide a setDone(boolean) method.
    public class Task {
        protected String description;
        protected boolean isDone;
    
        // ...
    
        public void setDone(boolean isDone){
            this.isDone = isDone;
        }
    }
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class Main {
        static Scanner in = new Scanner(System.in);
        static List<Task> tasks = new ArrayList<>();
    
        public static void main(String[] args) {
            // ...
        }
    
        private static void addTodo(String line) throws TaskManagerException {
            //...
            tasks.add(new Todo(description));
            //...
        }
    
        private static void markAsDone(String line) {
            int index = Integer.parseInt(line.substring("done".length()).trim());
            tasks.get(index - 1).setDone(true);
            System.out.println("Tasks in the list: " + tasks.size());
        }
    
        private static void printTasks() {
            // ...
            for (int i = 0; i < tasks.size(); i++) {
                System.out.println("[" + (i + 1) + "] " + tasks.get(i));
            }
        }
    }
    

    Lecture 6

    Questions to discuss during the lecture:

    Imagine you are building an online system called TeamFormer. A brief description of it is given below.

    TeamFormer is a system for helping TIC2002 students during team forming period. It lets students record who is in which team. Students can use the system to find teams short of members and students looking for teams, easing the team forming process. Note that the system is not meant as a platform for students to communicate with each other to find team members. Students are supposed to talk to each other and form teams outside the system, as they do now. TeamFormer simply helps students to see the team forming status of the class (e.g., who has teams and who doesn’t) and record their own team after forming a team. It is also meant to ease the team-forming-related workload of instructors.

    (a) Specify the vision, scope, user types, and the workflow of TeamFormer.

    (b) Specify requirements of TeamFormer as a list of User Stories.

    Find notation mistakes in the sequence diagram below:

    [slides]