1
\$\begingroup\$

(See the previous and initial iteration.)

I have refactored the API based on excellent review by cbojar. Also, a honorary mention goes to janos for pruning some unnecessary code out of the transcript reading method.

Now, I have this:

Course.java

package net.coderodde.gpa;

/**
 * This class implements a record for storing the grade of a course, and the 
 * amount of credits awarded for completing it.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.61 (Mar 21, 2016)
 */
public class Course {

    private final int credits;
    private final int grade;

    public Course(int credits, int grade) {
        this.credits = credits;
        this.grade   = grade;
    }

    public int getCredits() { return credits; }
    public int getGrade()   { return grade; }
}

Transcript.java

package net.coderodde.gpa;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * This class implements a transcript record that stores the course descriptors
 * ({@link net.coderodde.gpa.Course}) for a student.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.61 (Mar 21, 2016)
 */
public class Transcript implements Iterable<Course> {

    private final List<Course> courseList = new ArrayList<>();

    public void addCourse(Course course) {
        courseList.add(course);
    }

    @Override
    public Iterator<Course> iterator() {
        return courseList.iterator();
    }

    public double getGradePointAverage() {
        int totalCredits = getTotalCredits();
        int totalCreditWeightedGrades = 0;

        for (Course course : this) {
            totalCreditWeightedGrades += course.getCredits() * 
                                         course.getGrade();
        }

        return (1.0 * totalCreditWeightedGrades) / totalCredits;
    }

    public int getTotalCredits() {
        int sum = 0;

        for (Course course : this) {
            sum += course.getCredits();
        }

        return sum;
    }
}

TranscriptReader.java

package net.coderodde.gpa;

import java.io.InputStream;
import java.util.Scanner;

/**
 * This class is responsible for loading a transcript from an input stream.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.61 (Mar 21, 2016)
 */
public class TranscriptReader {

    private final Scanner scanner;

    public TranscriptReader(InputStream in) {
        this.scanner = new Scanner(in);
    }

    public Transcript readTranscript() {
        Transcript transcript = new Transcript();
        int lineNumber = 1;

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();

            if (line.equals("end")) {
                // Used to end the command line session.
                break;
            }

            if (line.isEmpty()) {
                lineNumber++;
                continue;
            }

            // Since 'line' was 'trimmed', there should not be any whitespace
            // before the first token, and after the last one.
            String[] parts = line.split("\\s*,\\s*");

            if (parts.length != 2) {
                System.err.println(
                        "Line " + lineNumber + " contains invalid number of " +
                        "tokens (" + parts.length + "). Should have exactly " + 
                        "two: number of credits and the grade.");
                lineNumber++;
                continue;
            } 

            String creditsString = parts[0];
            String gradeString   = parts[1];

            int credits;
            int grade;

            try {
                credits = Integer.parseInt(creditsString);
            } catch (NumberFormatException ex) {
                System.err.println(
                        "Invalid credit token on line " + lineNumber +
                        ": " + creditsString);
                ++lineNumber;
                continue;
            }

            try {
                grade = Integer.parseInt(gradeString);
            } catch (NumberFormatException ex) {
                System.err.println(
                        "Invalid grade token on line " + lineNumber +
                        ": "+ gradeString);
                ++lineNumber;
                continue;
            }

            transcript.addCourse(new Course(credits, grade));
            lineNumber++;
        }

        scanner.close();
        return transcript;
    }
}

App.java

package net.coderodde.gpa;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

/**
 * This class implements a command line application for computing GPA (grade 
 * point average).
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.61 (Mar 21, 2016)
 */
public class App {

    public static void main(String[] args) {
        if (args.length > 1) {
            printHelp();
            return;
        }

        InputStream in = null;

        try {
            in = args.length == 0 ? System.in : new FileInputStream(args[0]);
        } catch (FileNotFoundException ex) {
            // I catch FileNotFoundException in order to be able to print 
            // an easy to read error message.
            System.err.println("ERROR: The file \"" + args[0] + 
                               "\" does not exist.");
            System.exit(1);
        }

        TranscriptReader transcriptReader = new TranscriptReader(in);
        Transcript transcript = transcriptReader.readTranscript();
        System.out.println(transcript.getGradePointAverage());
    }

    private static void printHelp() {
        System.out.println("Usage: java -jar FILE.jar [grades.csv]");
        System.out.println("Omit the only argument in order to input " + 
                           "data from command line.");
    }
}

Please, tell me anything that comes to mind.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.