eu.lp0.cursus.scoring.scores.impl.GenericRacePenaltiesData.java Source code

Java tutorial

Introduction

Here is the source code for eu.lp0.cursus.scoring.scores.impl.GenericRacePenaltiesData.java

Source

/*
   cursus - Race series management program
   Copyright 2012-2014  Simon Arlott
    
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
    
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.
    
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.lp0.cursus.scoring.scores.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;

import eu.lp0.cursus.db.data.Event;
import eu.lp0.cursus.db.data.Penalty;
import eu.lp0.cursus.db.data.Pilot;
import eu.lp0.cursus.db.data.Race;
import eu.lp0.cursus.db.data.RaceAttendee;
import eu.lp0.cursus.scoring.data.RacePointsData;
import eu.lp0.cursus.scoring.data.ScoredData;
import eu.lp0.cursus.scoring.scores.base.AbstractRacePenaltiesData;

public class GenericRacePenaltiesData<T extends ScoredData & RacePointsData> extends AbstractRacePenaltiesData<T> {
    private final CumulativeMethod method;
    private final boolean noRacePenaltiesForSimulated;

    public enum CumulativeMethod {
        RACE, EVENT, SERIES;
    }

    public GenericRacePenaltiesData(T scores, CumulativeMethod method) {
        this(scores, method, false);
    }

    public GenericRacePenaltiesData(T scores, CumulativeMethod method, boolean noPenaltiesForSimulated) {
        super(scores);

        this.method = method;
        this.noRacePenaltiesForSimulated = noPenaltiesForSimulated;
    }

    @Override
    protected int calculateRacePenalties(Pilot pilot, Race race) {
        RaceAttendee attendee = race.getAttendees().get(pilot);
        if (attendee == null) {
            return 0;
        }

        if (noRacePenaltiesForSimulated) {
            if (scores.hasSimulatedRacePoints(pilot, race)) {
                return 0;
            }
        }

        int autoPenalties = countPreviousAutomaticPenalties(pilot, race);
        int penalties = 0;
        for (Penalty penalty : Iterables.concat(Ordering.natural().immutableSortedCopy(attendee.getPenalties()),
                getSimulatedRacePenalties(pilot, race))) {
            switch (penalty.getType()) {
            case AUTOMATIC:
                if (penalty.getValue() >= 0) {
                    // Add multiple automatic penalties
                    for (int i = 0; i < penalty.getValue(); i++) {
                        penalties += ++autoPenalties;
                    }
                } else {
                    // Remove multiple automatic penalties
                    for (int i = penalty.getValue(); i > 0; i--) {
                        if (autoPenalties > 0) {
                            penalties -= autoPenalties--;
                        }
                    }
                }
                break;

            case FIXED:
                // Fixed penalty added/removed
                penalties += penalty.getValue();
                break;

            case CANCEL_LAPS:
            case ADJUST_LAPS:
                // These is applied in RaceLapsData
                break;

            case EVENT_NON_ATTENDANCE:
                // This should only be applied in OverallPenaltiesData
                Preconditions.checkArgument(false, "Invalid race penalty type: " + penalty.getType()); //$NON-NLS-1$
                break;
            }
        }

        // Can't have negative race penalties because we need
        // to be able to remove them from the race points later
        // and negative race points doesn't make sense
        if (penalties < 0) {
            penalties = 0;
        }

        return penalties;
    }

    protected int countPreviousAutomaticPenalties(Pilot pilot, Race race) {
        int autoPenalties = 0;
        for (Race previousRace : findPreviousRaces(race)) {
            if (previousRace.equals(race)) {
                break;
            } else {
                RaceAttendee previousAttendee = previousRace.getAttendees().get(pilot);
                if (previousAttendee != null) {
                    for (Penalty penalty : previousAttendee.getPenalties()) {
                        if (penalty.getType() == Penalty.Type.AUTOMATIC) {
                            autoPenalties += penalty.getValue();
                            // Don't allow negative automatic penalties, that just gets silly
                            if (autoPenalties < 0) {
                                autoPenalties = 0;
                            }
                        }
                    }
                }
            }
        }
        return autoPenalties;
    }

    protected final List<Race> findPreviousRaces(Race race) {
        List<Race> previousRaces = new ArrayList<Race>(scores.getRaces().size() * 2);
        switch (method) {
        case RACE:
            break;

        case EVENT:
            previousRaces.addAll(race.getEvent().getRaces());
            break;

        case SERIES:
            for (Event event : scores.getSeries().getEvents()) {
                previousRaces.addAll(event.getRaces());
            }
            break;
        }
        return previousRaces;
    }

    @Override
    protected List<Penalty> calculateSimulatedRacePenalties(Pilot pilot, Race race) {
        return Collections.emptyList();
    }
}