188 lines
5.6 KiB
Java
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();
|
|
}
|
|
|
|
|
|
}
|