public class Clerk { /* Teilaufgabe (a): Instanzenvariablen mit Defaultwerten */
    private String firstName, lastName;
    private int yearOfBirth;
    private int salaryClass;
    private boolean married;
    
    /*
     * wegen der vermeidung von magic numbers hier der Grundsold und die
     * weiteren Konstanten
     */
    private static final double basicSalary = 2000.0;
    private static final double classMultiplier = 17.0 / 9.0;
    private static final double marriageBonus = 12.3;
    private static final int year = 2006;
    
    public String toString() {
        return firstName + " " + lastName + "(born " + yearOfBirth + ", " + (married?"married":"bachelor") + ")";
    }
    
    /**
     * Teilaufgabe (b): Initialisieren der Instanzenvariablen per Konstruktor
     */
    public Clerk(String firstName, String lastName, int yearOfBirth,
            int salaryClass, boolean married) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.yearOfBirth = yearOfBirth;
        this.salaryClass = salaryClass;
        this.married = married;
    }
    
    /** Teilaufgabe (c): Befoerdern eines Angestellten */
    public void promote(int newSalaryClass) {
        salaryClass = newSalaryClass;
    }
    
    /** Teilaufgabe (d): Heirat und Scheidung */
    public void marry() {
        married = true;
    }
    
    public void divorce() {
        married = false;
    }
    
    /** Teilaufgabe (e): Berechnung des Solds */
    public double salary(int thisYear) {
        /* berechnet den Sold */
        double thesalary;
        /* Grundsold + x * 17/9 Prozent mit x = salaryClass: */
        thesalary = basicSalary
        * ((100.0 + classMultiplier) / 100.0 * salaryClass);
        // System.out.println("s1: " + thesalary);
        /* Altersbonus */
        int age = thisYear - yearOfBirth;
        int nbonus = 0;
        if (age >= 30)
            nbonus = (age - 25) / 5;
        thesalary = ((100.0 + nbonus) / 100.0) * thesalary;
        /* Verheiratetenzuschlag */
        if (married)
            thesalary += ((100.0 + marriageBonus) / 100.0) * basicSalary;
        return thesalary;
    }
    
    /** Teilaufgabe (f): wer beneidet wen? */
    public boolean envies(Clerk c) {
        return (yearOfBirth < c.yearOfBirth) && (salary(year) < c.salary(year));
    }      
    
    /** Teilaufgabe (g): main (enthaelt etwas mehr als verlangt) */
    public static void main(String[] args) {
        Clerk c1 = new Clerk("Jack", "Miller", 1970, 1, false);
        Clerk c2 = new Clerk("John", "Smith", 1980, 1, false);
        System.out.println(c1 + " earns " + c1.salary(year));
        System.out.println(c2 + " earns " + c2.salary(year));
        System.out.println(c1 + " envies " + c2 + ": " + c1.envies(c2));
        c2.promote(7);
        System.out.println(c2 + " earns " + c2.salary(year));
        System.out.println(c1 + " envies " + c2 + ": " + c1.envies(c2));
        System.out.println(c2 + " envies himself: " + c2.envies(c2));
        Clerk c3 = new Clerk("Clark", "Kent", 1962, 3, false);
        Clerk c4 = new Clerk("Jerry", "Maguire", 1974, 1, true);
        Clerk[] clerks = new Clerk[]{c1, c2, c3, c4};
        System.out.println(java.util.Arrays.toString(clerks) + "are happy: " + allHappy(clerks));
        // wir machen sie gluecklich
        c4.divorce();
        c2.promote(1);
        System.out.println(java.util.Arrays.toString(clerks) + "are happy: " + allHappy(clerks));
    }
    
    /** Teilaufgabe(h): Ist eine Reihung von Clerk-Objekten paarweise zufrieden? */
    public static boolean allHappy(Clerk[] cs) {
        for (Clerk c1 : cs) {
            for (Clerk c2 : cs) {
                if (c1.envies(c2)) {    // beachte die Nichtreflexivitaet!
                    return false;
                }
            }
        }
        return true;
    }
}

