LMU ☀️ CMSI 186
PROGRAMMING LABORATORY
LAB 5: POD RACING Due: 2020-03-26

Learning Outcomes

Students will be able to (1) describe, explain, and use superclasses and subclasses in Java, and (2) explain the mathematical notion of a function and its implementation as a Java lambda.

Reading

Nothing to read, but you can watch this guy.

Activities

crash.gif

You and your friends set out to build some racing pods. Because you haven’t had much experience in building these things, the pods aren’t all that great. They tend not to respond at all to your commands while you are in them: they have a mind of their own. Some start out able to go fast then they just stop working. Others jerkily speed up and slow down. Some go slow for a bit then unexpectedly accelerate. Rather than risking your lives actually getting in those things, you decide to simulate a race in software.

Initialize a repository

As in the previous labs, go to GitHub, select Import Repository. Then:

For Your old repository’s clone URL
Enter https://github.com/rtoal/cmsi-186-lab-5-starter-code
For Your new repository details
Enter the repository name cmsi-186-lab-5

The import might take a few minutes. When done, clone the repo and get ready to work.

Implement the Pod class

Each pod has a name and a velocity function, which reports the velocity of the pod at time t. Here are some examples of velocity functions:

t -> 0
Never starts, just sits at the starting line.
t -> Math.min(t*6, 60)
Immediately accelerates linearly from 0 to 60 in 10 seconds, then stays at 60 forever.
t -> t < 5 ? 0 : t < 25 ? 5*t-25 ? t < 45 ? 225-5*v : 0
Does nothing for the first 5 seconds, then accelerates linearly to 100 over the next 20 seconds, then decelerates to 0 over the next 20 seconds, then stops for good.
t -> 2 * Math.log(t + 1)
Accelerates quickly at first, then less so over time.
CLASSWORK
You should graph these functions now. For the x-axis, go from 0 to 100. For example, here is the plot of the function t -> 2 * Math.log(t + 1) from 0 to 100:

In the starter code, you are given a Pod class that you are to complete. Pods have a name and a velocity function (we’ll explain how to do functions during lecture time); your job is to complete the distanceTraveled method:

import java.util.function.Function;

public class Pod {
    private String name;
    private Function<Double, Double> velocityFunction;

    public Pod(String name, Function<Double, Double> velocityFunction) {
        this.name = name;
        this.velocityFunction = velocityFunction;
    }

    public String getName() {
        return name;
    }

    public double v(double t) {
        return velocityFunction.apply(t);
    }

    public double distanceTraveled(double startTime, double endTime, int slices) {
        // Complete this method. It estimates the distance traveled between the
        // given start and end times by slicing up the time periods into a certain
        // number of slices, as will be described in class. If this method is not
        // passed at least one slice, throw an IllegalArgumentException with the
        // message "At least one slice required".
        return 0.0;
    }
}

The process you are to use for computing the distance traveled is as in the following example. Suppose the velocity function is t->2*t+8, and we want to know the distance traveled between 10 and 20 seconds. We break up the time interval into slices; for this example we’ll use 5 slices:

We compute the velocity at each of the 5 times:

Time:t=10t=12t=14t=16t=18
Velocity:2832364044

Now as an estimate of the true velocity, we say:

Our estimate for the distance traveled (using 5 slices) is 56 + 64 + 72 + 80 + 88 = 360. (The true value is 380; our code underestimated because we only used 5 slices! If you used 1000 slices, our estimate would be 379.9; at 5000 slices, it would be 379.98.)

Once you implement this method, you will be able to use pods like so:

jshell> /open Pod.java

jshell> var p = new Pod("aldar", t -> t < 5 ? 0 : 0.25 * t)

jshell> p.getName()
"aldar"

jshell> p.distanceTraveled(2, 100, 30)
1207.85

jshell> p.distanceTraveled(2, 100, 30000)
1246.8336253099985

jshell> var q = new Pod("reeso", t -> 50 - Math.pow(t - 10, 2))

jshell> q.distanceTraveled(0, 20, 2000)
333.33300000000025

jshell> q.distanceTraveled(0, 30, 2000)
-1497.7511249999993

Although you can create any arbitrary pod simply by using the Pod class, it is pretty convenient to specialize this class into subclasses. For example, I’ve provided you with a subclass called ConstantVelocityPod, representing pods that always travel at the same velocity:

public class ConstantVelocityPod extends Pod {
    public ConstantVelocityPod(String name, double velocity) {
        super(name, t -> velocity);
    }
}

You can use such a pod as follows:

jshell> /open ConstantVelocityPod.java

jshell> var p = new ConstantVelocityPod("neva", 25)

jshell> p.distanceTraveled(0, 10, 50)
250.0

In addition to completing the Pod class, you need to create three new subclasses:

The starter code contains a little tester for the pod class. Please use it as you develop your pods:

$ javac PodTest.java && java PodTest

Implement the race

To race pods, you will need to move pods over time, in little time slices. In the PodRace class, you are to implement the method:

  Set<Pod> race(double distance, Set<Pod> racers, double timeSlice, double timeLimit)

with the following three parameters:

Throw an exception if either the distance or the precision is less than or equal to 0. Return the winners of the race (the first pod(s) to travel the given distance). Note we say “winners” (plural) since there can be multiple winners in the case of a tie, or even zero winners, if each pod is unable to travel the length of the race (or if no one shows up!)

The starter code contains a rudimentary tester for the race class. Please use it as you build out the race class (and please consider extending the test with more cases):

$ javac PodRaceTest.java && java PodRaceTest

Stretch Challenge (Optional)

For some of your subclasses, create a version of distanceTraveled that does not take in a timeSlices parameter. Make this version compute the exact distance traveled.

This is simply an exercise for you to challenge yourself with. There will be no extra credit awarded. If you can do it, great. If not, no worries!

What to turn in

Online:

On hardcopy or email:

  1. Draw graphs of five very interesting velocity functions, with both of the axes clearly labeled. Also label the graph with the function you are detailing. You may, of course, and really should, use a graphing tool for this! (This is not a high school math course where you are learning how to graph with pencil and paper.)
  2. Explain why the program requires an absolute time limit for race.
  3. Explain a situation in which setting too large of a time slice could cause a racer to not win even if that racer were to cross the finish line first.