188 lines
5.6 KiB
Java

package lu.jpt.csparqltest.rentacar;
import java.util.ArrayList;
import java.util.List;
import eu.larkc.csparql.cep.api.RdfQuadruple;
import lu.jpt.csparqltest.util.RandomHelper;
public class Driver {
// Traits with corresponding behaviour for certain situations
public enum Trait {CAREFUL, REGULAR, FAST, INSANE};
private static final double[] chanceToEngageHandbrakeOnLock = {1.00, 0.85, 0.60, 0.05};
private static final double[] chanceToReleaseHandbrakeOnUnlock = {1.00, 0.95, 0.90, 0.84};
private static final double[] chanceToCrashCar = {0.05, 0.10, 0.20, 0.40};
private static final double[] chanceToDriftCar = {0.00, 0.05, 0.15, 0.70};
private static final double[] chanceToChangeSpeedHard = {0.00, 0.10, 0.30, 0.80};
private static final double[] chanceToStallEngine = {0.20, 0.01, 0.00, 0.00};
private int id;
private CarPool carPool;
private int carUseCycles;
private Car car;
private Trait trait;
private List<RdfQuadruple> quads;
private final String IRI;
public Driver(int id, CarPool carPool) {
this.id = id;
this.IRI = RentACarSimulation.BASE_OBJECT_IRI + "/driver";
this.carPool = carPool;
this.car = null;
this.quads = new ArrayList<RdfQuadruple>();
// Pick a random behaviour and stick to it.
this.trait = (Trait) RandomHelper.getRandomElementFromArray(Trait.values());
}
public int getID() {
return this.id;
}
public String getIri() {
return this.IRI + "#" + this.id;
}
/**
* Simulation triggers this from the outside to make the driver do something
* given a car is available.
*/
public void tick() {
if(car == null) {
// Nothing to do, maybe randomly take a free car
if(RandomHelper.isLuckyByChance(0.75)) {
this.takeRandomCarFor(RandomHelper.getRandomNumberWithin(20,50));
}
} else {
// Do random things with the car
if(this.car.needsInput()) {
this.useCar(this.car);
}
// Decrement use cycles
this.carUseCycles--;
if(this.carUseCycles == 0) {
this.returnCar();
}
}
}
/**
* Interact with the car by starting a CarAction on the car.
* @param car The given car
*/
private void useCar(Car car) {
Car.CarState carState = car.getState();
if(carState == Car.CarState.WRECKED) {
// Sad fade :-(
return;
}
switch(carState) {
case LOCKED:
if(this.carUseCycles > 5) {
car.keyOpen();
}
break;
case OFF:
if(this.carUseCycles > 4) {
car.start();
if(RandomHelper.isLuckyByChance(Driver.chanceToReleaseHandbrakeOnUnlock[this.trait.ordinal()])) {
car.releaseHandbrake();
}
} else {
if(RandomHelper.isLuckyByChance(Driver.chanceToEngageHandbrakeOnLock[this.trait.ordinal()])) {
car.engageHandbrake();
}
car.keyClose();
}
break;
case IDLE:
if(this.carUseCycles > 3) {
car.accelerate(RandomHelper.isLuckyByChance(Driver.chanceToChangeSpeedHard[this.trait.ordinal()]));
} else {
car.stop();
}
break;
case DRIVE:
// Always release handbrake after drifting or forgetting!
if(car.isHandbrakeEngaged()) {
car.releaseHandbrake();
}
if(this.carUseCycles > 3) {
if(RandomHelper.isLuckyByChance(Driver.chanceToCrashCar[this.trait.ordinal()])) {
car.crash();
} else if(RandomHelper.isLuckyByChance(Driver.chanceToStallEngine[this.trait.ordinal()])) {
car.stop();
} else {
int nextAction = RandomHelper.getRandomNumberWithin(0, 1);
switch(nextAction) {
case 0:
boolean accHard = RandomHelper.isLuckyByChance(Driver.chanceToChangeSpeedHard[this.trait.ordinal()]);
car.accelerate(accHard);
if(accHard) {
if(RandomHelper.isLuckyByChance(Driver.chanceToDriftCar[this.trait.ordinal()])) {
car.engageHandbrake();
}
}
break;
case 1:
car.brake(RandomHelper.isLuckyByChance(Driver.chanceToChangeSpeedHard[this.trait.ordinal()]));
break;
}
}
} else {
car.comeToHalt();
}
break;
default:
System.err.println("Driver cannot handle car state: " + carState);
break;
}
}
private void takeRandomCarFor(int useCycles) {
this.car = this.carPool.takeRandomCar();
this.carUseCycles = useCycles;
long time = System.currentTimeMillis();
String baseIri = RentACarSimulation.BASE_OBJECT_IRI;
String baseOnt = RentACarSimulation.BASE_ONTOLOGY_IRI;
String eventIri = baseIri + "/event#" + time;
this.quads.add(new RdfQuadruple(eventIri, "rdf:type", baseOnt+"CarTakenEvent", time));
this.quads.add(new RdfQuadruple(eventIri, baseOnt+"relatedUser", this.getIri(), time));
this.quads.add(new RdfQuadruple(eventIri, baseOnt+"relatedCar", this.car.getIri(), System.currentTimeMillis()));
this.quads.add(new RdfQuadruple(eventIri, baseOnt+"usagePeriod", ""+useCycles+"^^http://www.w3.org/2001/XMLSchema#integer", System.currentTimeMillis()));
}
private void returnCar() {
long time = System.currentTimeMillis();
String baseIri = RentACarSimulation.BASE_OBJECT_IRI;
String baseOnt = RentACarSimulation.BASE_ONTOLOGY_IRI;
String eventIri = baseIri + "/event#" + time;
this.quads.add(new RdfQuadruple(eventIri, "rdf:type", baseOnt+"CarReturnedEvent", time));
this.quads.add(new RdfQuadruple(eventIri, baseOnt+"relatedUser", this.getIri(), time));
this.quads.add(new RdfQuadruple(eventIri, baseOnt+"relatedCar", this.car.getIri(), time));
this.carPool.returnCar(this.car);
this.car = null;
}
public List<RdfQuadruple> getQuadruples() {
List<RdfQuadruple> result = this.quads;
this.quads = new ArrayList<RdfQuadruple>();
return result;
}
public String toString() {
StringBuilder sb = new StringBuilder("[#");
sb.append(this.id);
sb.append(" trait="+this.trait);
sb.append("]");
return sb.toString();
}
}