
package Olympics.g5;

import Olympics.Move;
import Olympics.Olympics;
import Olympics.RiderInfo;
import java.util.*;

public class Rider {

    // copied from Olympics.IFCConstants
    public static final int LEFT = -1;
    public static final int RIGHT = 1;
    public static final int STAY = 0;

    // my index in the info array
    public int id, lanechange, targetLane;
    public double acceleration, lastAccel, lastSpeed;
    public RiderInfo info;

    public Rider(RiderInfo ri, int i) {
	id = i;
	info = ri;
	acceleration = 0;
	lanechange = STAY;
	lastAccel = 0;
	lastSpeed = 0;
    }

    public boolean alive() {
	// the 2nd check is to account for a mysterious bug where a rider
	// dies right at the beginning (& has neg pos but full energy)
	return this.info.energy() > 0 && info.position() >= 0;
    }

    public void goToSpeed(double speed) {
	double speedGap = round(speed - info.speed(), 4);
	if (speedGap >= 0)
	    acceleration = Math.min(1, speedGap);
	else
	    acceleration = Math.max(-1, speedGap);

	lastAccel = acceleration;
	lastSpeed = info.speed();
    }

    public boolean goToLane(int target) {
	targetLane = target;
	boolean ret = false;
	int lanediff = target - info.lane();
	if (lanediff < 0)
	    lanechange = LEFT;
	else if (lanediff > 0)
	    lanechange = RIGHT;
	else {
	    lanechange = STAY;
	    ret = true;
	}
	return ret;
    }

    private double round(double input, int places) {
	return Math.round(input*Math.pow(10,places))/Math.pow(10,places);
    }

    public void lead(double speed, int lane) {
	goToSpeed(speed);
	if (lane == info.lane() && lastAccel > 0 && info.speed() <= lastSpeed)
	    goToLane(lane + (Math.random()<0.5?-1:1));
	else
	    goToLane(lane);
    }

    public boolean follow(Rider target) {
	boolean inPosition = false;
	double speedGap = round(target.info.speed() - info.speed(), 4);
	double posGap = round(target.info.position() - info.position(), 4);

	if (posGap < 2 && info.speed() >= 1) {
	    if (speedGap <= 5)
		acceleration = -1;
	    else
		acceleration = 0;
	    goToLane(target.info.lane() + (Math.random()<0.5?-1:1));
	}
	else if (goToLane(target.info.lane())) {
	    if (posGap > 2) {
		if (speedGap >= -5)
		    acceleration = 1;
		else
		    acceleration = 0;
		// if you accelerated last turn but your speed didn't
		// increase, you've hit someone else. so, move to a
		// random lane.
		if (lastAccel > 0 && lastSpeed >= info.speed())
		    lanechange = (Math.random()<0.5 ? 1 : -1);
	    }
	    else {
		acceleration = 0;
		inPosition = true;
	    }
	}
	else if (speedGap >= 0)
	    acceleration = Math.min(1, speedGap);

	// update values for next turn
	lastAccel = acceleration;
	lastSpeed = info.speed();

	return inPosition;
    }

    // only works with our own riders
    public void imitate(Rider target) {
	acceleration = target.acceleration;
	lanechange = target.lanechange;
    }
}
