/* The customary usage order of some frequently used modifiers:
*
* public / private
* abstract
* static
* final
*
* Source: https://stackoverflow.com/questions/16731240/
*/
import java.util.ArrayList;
import java.util.List;
/**
* The Event class has the main method of a pedagogical program that
* demonstrates several of Java's object-oriented programming constructs.
*/
public class Event {
public static void main(String[] args)
{
Aquathon race = new Aquathon();
Person aquaman = new Person("Aquaman"),
wonderWoman = new Person("Wonder Woman"),
superman = new Person("Superman");
Dog lassy = new Dog("Lassy"),
scoobyDoo = new Dog("Scooby Doo");
aquaman.swimTraining(8000);
wonderWoman.runTraining(10000);
lassy.runTraining(10000);
Amphibian[] competitors =
{
superman,
wonderWoman,
aquaman,
scoobyDoo,
lassy
};
for (Amphibian winner : race.individualWinners(competitors))
System.out.println("Champion: " + winner.toString());
}
}
class Aquathon
{
private double swimDistance;
private double runDistance;
public Aquathon() { this(0.62, 3.1); }
public Aquathon(double swimMiles, double runMiles)
{
this.swimDistance = swimMiles;
this.runDistance = runMiles;
}
public double finishTime(Swimmer swimmer, Runner runner)
{
double swimTime = this.swimDistance / swimmer.swimSpeed();
double runTime = this.runDistance / runner.runSpeed();
return swimTime + runTime;
}
public List<Amphibian> individualWinners(Amphibian[] competitors)
{
ArrayList<Amphibian> winners = new ArrayList<Amphibian>();
Double fastestTime = 0.0;
for (Amphibian athlete : competitors)
{
double athleteTime = finishTime(athlete, athlete);
if (winners.size() == 0)
{
System.out.println("First winner: " + athlete.toString());
System.out.println("Time: " + athleteTime);
winners.add(athlete);
fastestTime = athleteTime;
}
else
{
if (athleteTime == fastestTime)
{
System.out.println("Yet another winner: " + athlete.toString());
winners.add(athlete);
}
else if (athleteTime < fastestTime)
{
System.out.println("Previous fastest time: " + fastestTime);
System.out.println("New fastest time: " + athleteTime);
System.out.println("New winner: " + athlete.toString());
winners.clear();
winners.add(athlete);
}
}
}
return winners;
}
}
/*************/
/* Functions */
/*************/
class Natural
{
public static double ability()
{
return 0.75 + (Math.random() * 0.5);
}
}
class Performance
{
public static double result(double avg, double talent, double training)
{
final double MAX_TRAINING = 10000;
final double MAX_IMPROVEMENT = 0.5;
double nurture = 1 + training >= MAX_TRAINING ?
MAX_IMPROVEMENT : MAX_IMPROVEMENT * training / MAX_TRAINING;
return avg * talent * nurture;
}
}
/**************/
/* Interfaces */
/**************/
interface Runner
{
public double runSpeed();
public void runTraining(double amount);
}
interface Swimmer
{
public double swimSpeed();
public void swimTraining(double amount);
}
interface Amphibian extends Runner, Swimmer
{
}
/********************/
/* Abstract Classes */
/********************/
abstract class Pedestrian
{
private String name;
public Pedestrian(String name) { this.name = name; }
public String toString()
{
return name + " (" + numberOfLegs() + " legs)";
}
public abstract int numberOfLegs();
}
abstract class Quadruped extends Pedestrian {
public Quadruped(String name) { super(name); }
public int numberOfLegs() { return 4; }
}
abstract class Biped extends Pedestrian {
public Biped(String name) { super(name); }
public int numberOfLegs() { return 2; }
}
/**
* A Person is a Biped that can swim and run.
*/
class Person extends Biped implements Amphibian
{
private static final double AVG_RUN_SPEED = 7; // mph
private static final double AVG_SWIM_SPEED = 2; // mph
private double runTraining = 500; // hours
private double swimTraining = 1; // hours
private double runTalent = Natural.ability();
private double swimTalent = Natural.ability();
public Person(String name) { super(name); }
public void runTraining(double amt) { this.runTraining = amt; }
public void swimTraining(double amt) { this.swimTraining = amt; }
public double runSpeed()
{
return Performance.result(Person.AVG_RUN_SPEED,
this.runTalent,
this.runTraining);
}
public double swimSpeed()
{
return Performance.result(Person.AVG_SWIM_SPEED,
this.swimTalent,
this.swimTraining);
}
}
/**
* A Dog is a Quadruped that can swim and run.
*/
class Dog extends Quadruped implements Amphibian
{
private static final double AVG_RUN_SPEED = 15; // mph
private static final double AVG_SWIM_SPEED = 1; // mph
private double runTraining = 5000; // hours
private double swimTraining = 10; // hours
private double runTalent = Natural.ability();
private double swimTalent = Natural.ability();
public Dog(String name) { super(name); }
public void runTraining(double amt) { this.runTraining = amt; }
public void swimTraining(double amt) { this.swimTraining = amt; }
public double runSpeed()
{
return Performance.result(Dog.AVG_RUN_SPEED,
this.runTalent,
this.runTraining);
}
public double swimSpeed()
{
return Performance.result(Dog.AVG_SWIM_SPEED,
this.swimTalent,
this.swimTraining);
}
}
/**
* A Pig is a Quadruped that can run.
*/
class Pig extends Quadruped implements Runner
{
private static final double AVG_RUN_SPEED = 6; // mph
private double runTraining = 100; // hours
private double runTalent = Natural.ability();
public Pig() { this("Some Pig"); }
public Pig(String name) { super(name); }
public void runTraining(double amt) { this.runTraining = amt; }
public double runSpeed()
{
return Performance.result(Pig.AVG_RUN_SPEED,
this.runTalent,
this.runTraining);
}
}
/**
* A Shark can swim.
*/
class Shark implements Swimmer
{
private static final double AVG_SWIM_SPEED = 20; // mph
private double swimTraining = 10000; // hours
private double swimTalent = Natural.ability();
public String toString() { return "Shark"; }
public void swimTraining(double amt) { this.swimTraining = amt; }
public double swimSpeed()
{
return Performance.result(Shark.AVG_SWIM_SPEED,
this.swimTalent,
this.swimTraining);
}
}