package org.openbakery.racecontrol.persistence; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import org.openbakery.jinsim.Car; import org.openbakery.jinsim.Track; import org.openbakery.racecontrol.data.Driver; import org.openbakery.racecontrol.data.Lap; import org.openbakery.racecontrol.persistence.bean.Profile; import org.openbakery.racecontrol.util.LapComparator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class QueryHelper { private static Logger log = LoggerFactory.getLogger(QueryHelper.class); static Pattern lfsWorldNamePattern = Pattern.compile("profile_lfsworldusername\";s:\\d*:\"([^\"]*)"); private Persistence persistence; public QueryHelper(Persistence persistence) { this.persistence = persistence; } public Lap getFastestLapOnServer(Track track, Car car) { /* * SELECT lap. FROM racecontrol_lap as lap, racecontrol_driver AS driver WHERE driver.id = lap.driver_id AND driver.name = 'Brilwing' AND lap.time = ( SELECT min(lap.time) from racecontrol_driver * AS driver, racecontrol_lap AS lap, racecontrol_race_entry AS entry WHERE driver.id = lap.driver_id AND driver.race_entry_id = entry.id AND entry.track = 'KY2R' AND driver.name = 'Brilwing' * ORDER BY entry.start_time ) */ StringBuilder query = new StringBuilder(); query.append("SELECT lap.* FROM racecontrol_lap as lap, racecontrol_driver AS driver"); query.append(" WHERE driver.id = lap.driver_id"); query.append(" AND driver.car_name = '"); query.append(car.toString()); query.append("'"); query.append(" AND lap.time = ("); query.append("SELECT min(lap.time) from racecontrol_driver AS driver, racecontrol_lap AS lap, racecontrol_race_entry AS entry"); query.append(" WHERE driver.id = lap.driver_id "); query.append(" AND driver.race_entry_id = entry.id"); query.append(" AND entry.track = '"); query.append(track.getShortname()); query.append("'"); query.append(" ORDER BY entry.start_time)"); if (log.isDebugEnabled()) { log.debug("Query: " + query); } try { HashMap<String, String> parameters = new HashMap<>(); List<Lap> laps = (List<Lap>) persistence.queryNative(query.toString(), parameters, Lap.class); if (!laps.isEmpty()) { return (Lap) laps.get(0); } } catch (PersistenceException e) { log.error("Cannot perform query!", e); } return null; } public Lap getFastestLapOnServerForDriver(Track track, Driver driver) { StringBuilder query = new StringBuilder(); query.append("SELECT lap.* FROM racecontrol_lap as lap, racecontrol_driver AS driver"); query.append(" WHERE driver.id = lap.driver_id"); query.append(" AND driver.name = '"); query.append(driver.getName()); query.append("'"); query.append(" AND driver.car_name = '"); query.append(driver.getCarName()); query.append("'"); query.append(" AND lap.time = ("); query.append("SELECT min(lap.time) from racecontrol_driver AS driver, racecontrol_lap AS lap, racecontrol_race_entry AS entry"); query.append(" WHERE driver.id = lap.driver_id "); query.append(" AND driver.race_entry_id = entry.id"); query.append(" AND entry.track = '"); query.append(track.getShortname()); query.append("'"); query.append(" AND driver.name = '"); query.append(driver.getName()); query.append("'"); query.append(" AND driver.car_name = '"); query.append(driver.getCarName()); query.append("'"); query.append(" ORDER BY entry.start_time)"); if (log.isDebugEnabled()) { log.debug("Query: " + query); } try { HashMap<String, String> parameters = new HashMap<>(); List<Lap> laps = (List<Lap>) persistence.queryNative(query.toString(), parameters, Lap.class); if (!laps.isEmpty()) { return (Lap) laps.get(0); } } catch (PersistenceException e) { log.error("Cannot perform query!", e); } return null; } public Lap getFastestPossibleLapOnServer(Track track, Driver driver) { StringBuilder query = new StringBuilder(); query.append("SELECT min(lap.time) AS time"); for (int i = 1; i <= track.getSplits(); i++) { query.append(" min(lap.split"); query.append(i); query.append(") as split"); query.append(i); } query.append(" FROM racecontrol_driver AS driver, racecontrol_lap AS lap, racecontrol_race_entry AS entry"); query.append(" WHERE driver.id = lap.driver_id AND driver.race_entry_id = entry.id AND entry.track = '"); query.append(track.getShortname()); query.append("' AND driver.name = '"); query.append(driver.getName()); query.append("'"); query.append(" AND driver.car_name = '"); query.append(driver.getCarName()); query.append("'"); for (int i = 1; i <= track.getSplits(); i++) { query.append(" AND lap.split"); query.append(i); query.append(" > 0 "); } if (log.isDebugEnabled()) { log.debug("Query: " + query); } return null; } public List<Lap> getFastestsLaps(List<Car> cars, Track track, List<Profile> profiles) throws PersistenceException { if (profiles.size() == 0) { return Collections.emptyList(); } StringBuilder query = new StringBuilder(); query.append("SELECT driver.*, lap.* "); query.append("FROM racecontrol_lap lap "); query.append("INNER JOIN racecontrol_driver AS driver ON lap.driver_id = driver.id "); query.append("INNER JOIN ( "); query.append(" SELECT driver_inner.name as name, min(lap_inner.time) as time "); query.append(" FROM racecontrol_lap as lap_inner "); query.append(" INNER JOIN racecontrol_driver as driver_inner ON lap_inner.driver_id = driver_inner.id "); query.append(" INNER JOIN racecontrol_race_entry as race_entry_inner ON race_entry_inner.id = driver_inner.race_entry_id "); query.append(" WHERE driver_inner.car_name IN ("); boolean firstCar = true; for (Car car : cars) { if (!firstCar) { query.append(", "); } else { firstCar = false; } query.append("'"); query.append(car.toString()); query.append("'"); } query.append(") AND race_entry_inner.track = '"); query.append(track.getShortname()); query.append("' GROUP BY driver_inner.name) as fastest_lap "); query.append("ON lap.time = fastest_lap.time AND driver.name = fastest_lap.name "); query.append("INNER JOIN racecontrol_race_entry as entry ON entry.id = driver.race_entry_id "); query.append("WHERE entry.track = '"); query.append(track.getShortname()); query.append("' AND driver.car_name IN ("); firstCar = true; for (Car car : cars) { if (!firstCar) { query.append(", "); } else { firstCar = false; } query.append("'"); query.append(car.toString()); query.append("'"); } query.append(") AND lower(driver.name) IN ("); boolean first = true; for (Profile profile : profiles) { if (profile.getLastname() != null) { if (!first) { query.append(", "); } else { first = false; } query.append("'"); query.append(profile.getLfsworldName().toLowerCase()); query.append("'"); } } query.append(") ORDER BY driver.name"); log.debug("query: {}", query.toString()); List<Object[]> queryResult = (List<Object[]>) persistence.queryNative(query.toString(), "fastestLap"); List<Lap> lapList = new ArrayList<Lap>(queryResult.size()); Driver previous = null; for (Object[] entry : queryResult) { Driver driver = (Driver) entry[0]; if (previous != null && previous.getName().equalsIgnoreCase(driver.getName())) { // if a driver has the same time driven multiple times then skip this // time continue; } else { previous = driver; } Lap lap = (Lap) entry[1]; lap.setDriver(driver); log.info("Lap {}", lap); lapList.add(lap); } Collections.sort(lapList, new LapComparator()); return lapList; } public int getNumberLapsOnServerForDriver(Track track, Driver driver) { StringBuilder query = new StringBuilder(); query.append("SELECT count(lap.id) FROM racecontrol_lap as lap, racecontrol_driver AS driver, racecontrol_race_entry AS entry"); query.append(" WHERE driver.id = lap.driver_id"); query.append(" AND driver.race_entry_id = entry.id"); query.append(" AND driver.name = :driverName"); query.append(" AND driver.car_name = :carName"); query.append(" AND entry.track = :trackName"); if (log.isDebugEnabled()) { log.debug("Query: " + query); } HashMap<String, String> parameters = new HashMap<>(); parameters.put("driverName", driver.getName()); parameters.put("carName", driver.getCarName()); parameters.put("trackName", track.getShortname()); try { return persistence.queryNativeInt(query.toString(), parameters); } catch (PersistenceException e) { log.error("Cannot perform query!", e); } return 0; } public Lap getFastestLapOnServerForDriver(List<Car> cars, Track track, String driverName, int limit) { StringBuilder carList = new StringBuilder(); for (Car car : cars) { if (carList.length() > 0) { carList.append(", "); } carList.append("'"); carList.append(car.toString()); carList.append("'"); } StringBuilder query = new StringBuilder(); query.append("SELECT lap.* FROM racecontrol_lap as lap, racecontrol_driver AS driver, racecontrol_race_entry AS entry"); query.append(" WHERE driver.id = lap.driver_id"); query.append(" AND driver.race_entry_id = entry.id"); query.append(" AND driver.name = :driverName"); query.append(" AND entry.track = :trackName"); query.append(" AND lap.split1 < 3600000"); query.append(" AND driver.car_name IN ("); query.append(carList.toString()); query.append(")"); query.append(" ORDER BY lap.created_at"); if (limit > 0) { query.append(" LIMIT " + limit); } if (log.isDebugEnabled()) { log.debug("Query: " + query); } HashMap<String, String> parameters = new HashMap<>(); parameters.put("driverName", driverName); parameters.put("trackName", track.getShortname()); Lap fastest = null; try { List<Lap>laps = (List<Lap>)persistence.queryNative(query.toString(), parameters, Lap.class); int i = 1; for (Lap lap : laps) { if (fastest == null) { fastest = lap; fastest.setNumber(i); } if (fastest.getTime() == 0 && lap.getTime() > 0) { fastest = lap; fastest.setNumber(i); } else if (lap.getTime() > 0 && lap.getTime() < fastest.getTime()) { fastest = lap; fastest.setNumber(i); } i++; } if (fastest != null) { if (laps == null) { fastest.setAttempt(0); } else { fastest.setAttempt(laps.size()); } } } catch (PersistenceException e) { log.error("Cannot perform query!", e); } return fastest; } }