For a loop problem in the dive competition Java program

advertisements

Here is the assignment word for word: In a diving competition, each contestant's score is calculated by dropping the lowest and highest scores and then adding the remaining scores. Write a program that reads the provided data file formatted as depicted in the following table. For each diver output the diver's name and total score using the above scoring rules. Format each diver's total score to two decimal places. So for example, the output for Chen Ruolin below would be: Chen Ruolin – 56.90 points. Your program must read the data in from the provided data file and use arrays to store that data. Once all the data has been read in the program needs to calculate each diver's total points and output that diver's name and total points. Where total points is calculated based on the scoring rule defined above.

So far, I have a program that reads the .txt file and outputs the diver's name and the list of scores. For the life of me I can't figure out how to print just the total score (of course sans the highest and lowest scores). Any help would be greatly appreciated, this assignment is giving me a headache!

import java.util.Vector;

public class Diver
{
private String firstName;
private String lastName;
private Vector scores;

public Diver()
{
    firstName = "";
    lastName = "";
    scores = new Vector();
}

public Diver(String firstName, String lastName, double... scores)
{
    this.firstName = firstName;
    this.lastName = lastName;
    this.scores = new Vector();

    for (double score : scores)
    {
        this.scores.add( score );
    }
}

public String getFirstName()
{
    return firstName;
}

public void setFirstName(String firstName)
{
    this.firstName = firstName;
}

public String getLastName()
{
    return lastName;
}

public void setLastName(String lastName)
{
    this.lastName = lastName;
}

public String toString()
{
    return firstName + " " + lastName + scores.toString();
}
}

The TestDiver program:

import java.io.*;
import java.util.*;

class TestDiver
{
    public static void main(String[] args)
    {
        try {
            Scanner scanner = new Scanner(new File("diving_data.txt"));
            scanner.useLocale(Locale.US);

            double[] scores = new double[8];

            while (scanner.hasNext())
            {
                String firstName = scanner.next();
                String lastName  = scanner.next();

                System.out.println("Diver: " + firstName + " " + lastName);

                double min = Double.MIN_VALUE;
                double max = Double.MAX_VALUE;

                for (int i = 0; i < scores.length; i++)
                {
                    scores[i] = scanner.nextDouble();

                    System.out.println(" " + scores[i]);
                }

                Diver diver = new Diver(firstName, lastName, scores);
            }
            scanner.close();
        }
        catch (Exception e)
        {
            System.out.println("Problem: " + e.getMessage());
        }
    }
}

The .txt file: Chen Ruolin 9.2 9.3 9 9.9 9.5 9.5 9.6 9.8
Emilie Heymans 9.2 9.2 9 9.9 9.5 9.5 9.7 9.6
Wang Xin 9.2 9.2 9.1 9.9 9.5 9.6 9.4 9.8
Paola Espinosa 9.2 9.3 9.2 9 9.5 9.3 9.6 9.8
Tatiana Ortiz 9.2 9.3 9 9.4 9.1 9.5 9.6 9.8
Melissa Wu 9.2 9.3 9.3 9.7 9.2 9.2 9.6 9.8
Marie-Eve Marleau 9.2 9.2 9.2 9.9 9.5 9.2 9.3 9.8
Tonia Couch 9.2 9 9.1 9.5 9.2 9.3 9.4 9.6
Laura Wilkinson 9.7 9.1 9.3 9.4 9.5 9.4 9.6 9.2


Since the calculation of scores operates only on properties of the Diver class, it should be a method of the Diver class, rather than being external to the class. The only logic that your main method should contain is the input and output of the data, including the formatting. So move the calculation logic into the Diver class.

Also, if you store the scores in a sorted data structure such as a TreeSet, then you don't need any special logic to figure out which scores are the highest and lowest. All you need to do is iterate through the scores in sorted order and add them up - omitting of course the first and last scores. This will ultimately make your code more readable.

All your Diver class needs then, is the following. The Diver is initially created with no scores, and then scores are added to it. This saves you from having to cache data in your main method.

Notice how I've used a counter, as I increment through the Set adding up scores. I don't add anything to the sum if we're looking at the first element (counter == 0) or the last element (counter == scores.size() - 1).

import java.util.SortedSet;
import java.util.TreeSet;

public class Diver {
    private String firstName;
    private String lastName;
    private SortedSet<Double> scores;

    public Diver(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName  = lastName;
        scores = new TreeSet<>();
    }

    public void addScore(double score) {
        scores.add(score);
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public double getFinalScore() {
        if (scores.size() < 3) {
            return 0.0;
        }
        else {
            double sum = 0.0;
            int counter = 0;
            for(double score : scores) {
                if (counter != 0 && counter != scores.size() - 1) {
                    sum += score;
                }
                counter++;
            }
            return sum;
        }
    }
}

If you wanted to, you could include these methods for finding the lowest and highest score, although the assignment doesn't actually ask you to. See how easy it is, when you use the classes that the JDK provides for you, instead of trying to write your own logic!

    public double getLowestScore() {
        return scores.first();
    }

    public double getHighestScore() {
        return scores.last();
    }

Lastly, the test class. This has the input, output and formatting. Also, the assignment asks you to store all the Diver objects as you read the input file, then output them once you've finished reading the file. The easiest structure to do this with is an ArrayList, because you can keep on adding more objects to it, without having to know how many objects there are to start with. Most importantly, there is no calculation logic in the test class.

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class TestDiver {

    public static void main(String[] args) {
        Scanner in = new Scanner("diving_data.txt");
        List<Diver> divers = new ArrayList<>();
        while (in.hasNext()) {
            String firstName = in.next();
            String lastName  = in.next();

            Diver diver = new Diver(firstName, lastName);
            while(in.hasNextDouble()) {
                diver.addScore(in.nextDouble());
            }
            divers.add(diver);
        }
        in.close();

        for (Diver eachDiver : divers) {
            System.out.format(
                    "%s %s - %.2f points%n",
                    eachDiver.getFirstName(),
                    eachDiver.getLastName(),
                    eachDiver.getFinalScore());
        }
    }
}