package com.stylefeng.guns.modular.crossCity.server.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.stylefeng.guns.core.util.ToolUtil; import com.stylefeng.guns.modular.crossCity.dao.*; import com.stylefeng.guns.modular.crossCity.model.*; import com.stylefeng.guns.modular.crossCity.server.ILineSiteService; import com.stylefeng.guns.modular.crossCity.server.IOrderCrossCityService; import com.stylefeng.guns.modular.crossCity.warpper.LocationWarpper; import com.stylefeng.guns.modular.crossCity.warpper.SiteWarpper; import com.stylefeng.guns.modular.specialTrain.model.OrderPrivateCar; import com.stylefeng.guns.modular.specialTrain.server.IOrderPrivateCarService; import com.stylefeng.guns.modular.system.util.DateUtil; import com.stylefeng.guns.modular.system.util.GDMapElectricFenceUtil; import com.stylefeng.guns.modular.system.util.GDMapGeocodingUtil; import com.stylefeng.guns.modular.system.util.ResultUtil; import com.stylefeng.guns.modular.system.util.SystemException; import com.stylefeng.guns.modular.system.util.model.GeoFencingPolygon; import com.stylefeng.guns.modular.taxi.model.OrderTaxi; import com.stylefeng.guns.modular.taxi.service.IOrderTaxiService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @Service public class LineSiteServiceImpl extends ServiceImpl implements ILineSiteService { @Resource private LineSiteMapper lineSiteMapper; @Resource private SiteMapper siteMapper; @Resource private LineShiftDriverMapper lineShiftDriverMapper; @Resource private LineShiftMapper lineShiftMapper; @Resource private LocationMapper locationMapper; @Resource private DriverSelfTripMapper driverSelfTripMapper; @Autowired private DateUtil dateUtil; @Autowired private GDMapElectricFenceUtil gdMapElectricFenceUtil; @Resource private RedisTemplate redisTemplate; @Autowired private IOrderTaxiService orderTaxiService; @Autowired private IOrderPrivateCarService orderPrivateCarService; @Autowired private IOrderCrossCityService orderCrossCityService; @Autowired private MongoTemplate mongoTemplate; @Autowired private GDMapGeocodingUtil gdMapGeocodingUtil; /** * 根据线路id获取排班数据 * @param lineId * @param day * @return * @throws Exception */ @Override public List> queryDriver(Integer lineId, String day, Integer driverId) throws Exception { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Calendar c = Calendar.getInstance(); c.setTime(new Date()); c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), 0, 0, 0); c.set(Calendar.MILLISECOND, 0); if(c.getTimeInMillis() > sdf.parse(day).getTime()){ throw new SystemException("日期不能小于当天"); } List> list = new ArrayList<>(); List lineShifts = lineShiftMapper.queryByLineId(lineId); List> s = lineSiteMapper.queryDriver(lineId, sdf.parse(day), driverId); Calendar calendar = Calendar.getInstance(); calendar.setTime(sdf.parse(day)); String vehicle = (String) redisTemplate.opsForValue().get("VEHICLE"); List integers = new ArrayList<>(); if(ToolUtil.isNotEmpty(vehicle)){ integers = JSON.parseArray(vehicle).toJavaList(Integer.class); } for(LineShift lineShift : lineShifts){ boolean b = true; String[] split = lineShift.getEndTime().split(":"); calendar.set(Calendar.HOUR_OF_DAY, Integer.valueOf(split[0])); calendar.set(Calendar.MINUTE, Integer.valueOf(split[1])); if(calendar.getTimeInMillis() < System.currentTimeMillis()){//结束时间小于当前时间不显示 continue; } Map data = new HashMap<>(); for(Map map : s){ //先判断司机是否在限制接单范围内 boolean bo = false; for(Integer integer : integers){ if(integer.compareTo(Integer.valueOf(map.get("driverId").toString())) == 0){ bo = true; break; } } if(bo){ continue; } int i = orderTaxiService.selectCount(new EntityWrapper().eq("driverId", map.get("driverId")).in("state", Arrays.asList(2, 3, 4, 5, 11)).eq("DATE_FORMAT(travelTime, '%Y-%m-%d')", day)); if(i > 0){ continue; } i = orderPrivateCarService.selectCount(new EntityWrapper().eq("driverId", map.get("driverId")).in("state", Arrays.asList(2, 3, 4, 5, 11)).eq("DATE_FORMAT(travelTime, '%Y-%m-%d')", day)); if(i > 0){ continue; } List driverId1 = orderCrossCityService.queryListOrder(Integer.valueOf(map.get("driverId").toString()), lineShift.getId(), Arrays.asList(5), day); if(driverId1.size() > 0){ continue; } if(Integer.valueOf(map.get("laveSeat").toString()) <= 0){ continue; } if(lineShift.getId().intValue() == Integer.valueOf(map.get("id").toString()).intValue()){ b = false; BigDecimal price = getDefaultDestinationPrice(map); map.put("price", price == null ? "0" : price.toPlainString()); data = map; list.add(data); } } if(b){ data.put("id", lineShift.getId()); data.put("startTime", lineShift.getStartTime() + "-" + lineShift.getEndTime()); list.add(data); } } return list; } private BigDecimal getDefaultDestinationPrice(Map map) { if (map == null) { return null; } Integer totalSeat = map.get("totalSeat") == null ? null : Integer.valueOf(map.get("totalSeat").toString()); BigDecimal price = totalSeat != null && totalSeat == 6 ? getBigDecimal(map.get("defaultPrice7")) : getBigDecimal(map.get("defaultPrice5")); return price == null ? getBigDecimal(map.get("defaultPrice5")) : price; } private BigDecimal getBigDecimal(Object value) { if (value == null || ToolUtil.isEmpty(String.valueOf(value))) { return null; } try { return new BigDecimal(String.valueOf(value)); } catch (Exception e) { return null; } } /** * 根据司机排班数据id获取数据(剩余座位号和总座位数) * @param id * @return * @throws Exception */ @Override public Map querySeat(Integer id) throws Exception { Map map = new HashMap<>(); LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(id); map.put("totalNumber", lineShiftDriver.getTotalSeat()); map.put("number", lineShiftDriver.getLaveSeat()); map.put("content", lineShiftDriver.getLaveSeatNumber()); return map; } /** * 获取线路班次及司机预约情况 * @param lineId * @param time * @param driverId * @return * @throws Exception */ @Override public List> queryLineShiftInfo(Integer lineId, String time, Integer driverId) throws Exception { List lineShifts = lineShiftMapper.selectList(new EntityWrapper().eq("lineId", lineId).eq("state", 1).orderBy("startTime")); List> list = new ArrayList<>(); Map date = dateUtil.getStartAndEndDate(time); for(LineShift lineShift : lineShifts){ Map map = new HashMap<>(); map.put("id", lineShift.getId()); map.put("time", lineShift.getStartTime() + "-" + lineShift.getEndTime()); map.put("state", 3); List lineShiftDrivers = lineShiftDriverMapper.queryByDriver(lineShift.getId(), null, (null != date ? date.get("startTime") : null)); if(lineShiftDrivers.size() >= lineShift.getCarNum()){ map.put("state", 1); } lineShiftDrivers = lineShiftDriverMapper.queryByDriver(lineShift.getId(), driverId, (null != date ? date.get("startTime") : null)); if(lineShiftDrivers.size() > 0){ map.put("state", 2); } //判断时间(当天时间已经过了的班次) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); if(time.trim().equals(sdf.format(new Date()))){ Calendar s = Calendar.getInstance(); String[] split = lineShift.getEndTime().split(":"); s.setTime(new Date()); s.set(Calendar.HOUR_OF_DAY, Integer.valueOf(split[0])); s.set(Calendar.MINUTE, Integer.valueOf(split[1])); if(s.getTimeInMillis() < System.currentTimeMillis()){ map.put("state", 1); } } list.add(map); } return list; } /** * 获取站点 * @return * @throws Exception */ @Override public List querySite(Integer startSiteId) throws Exception { List> sites = null; if(null == startSiteId){ sites = siteMapper.querySite(null); }else{ sites = siteMapper.querySite(startSiteId); } Set set = new HashSet<>(); for(Map site : sites) { set.add(site.get("cityCode").toString()); } List list = new ArrayList<>(); for(String c : set){ SiteWarpper siteWarpper = new SiteWarpper(); List data = new ArrayList<>(); String name = ""; String code = ""; for(Map s : sites){ if(c.equals(s.get("cityCode").toString())){ Map map = new HashMap<>(); map.put("id", s.get("id")); map.put("name", s.get("name").toString()); name = s.get("cityName").toString(); code = s.get("cityCode").toString(); if(null == s.get("lonLat")){ String location = gdMapGeocodingUtil.geocoding(name + s.get("name").toString()); map.put("lonLat", location); Site site = new Site(); site.setId(Integer.valueOf(s.get("id").toString())); site.setLonLat(location); siteMapper.updateById(site); }else{ map.put("lonLat", s.get("lonLat").toString()); } data.add(map); } } siteWarpper.setName(name); siteWarpper.setCode(code); siteWarpper.setSites(data); list.add(siteWarpper); } return list; } /** * 根据站点id获取地点区域 * @param siteId * @return * @throws Exception */ @Override public List> queryLocation(Integer siteId) throws Exception { return locationMapper.queryLocation(siteId); } @Override public ResultUtil> querySelfLocation(Integer driverId, Integer lineShiftDriverId, Integer type) throws Exception { if (driverId == null) { return ResultUtil.tokenErr(); } if (lineShiftDriverId == null || type == null) { return ResultUtil.paranErr(); } if (type != 1 && type != 2) { return ResultUtil.error("type参数错误"); } LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(lineShiftDriverId); if (lineShiftDriver == null) { return ResultUtil.error("班次信息不存在"); } if (!driverId.equals(lineShiftDriver.getDriverId())) { return ResultUtil.error("无权操作此班次"); } if (lineShiftDriver.getCustomerId() == null) { return ResultUtil.error("自主行程信息不存在"); } DriverSelfTrip selfTrip = driverSelfTripMapper.selectById(lineShiftDriver.getCustomerId()); if (selfTrip == null || selfTrip.getState() == null || selfTrip.getState() != 1) { return ResultUtil.error("自主行程信息不存在"); } List data = new ArrayList<>(); if (type == 1) { if (selfTrip.getStartLon() == null || selfTrip.getStartLat() == null) { return ResultUtil.error("上车点坐标不存在"); } data.add(buildCircleLocation(selfTrip.getStartLon(), selfTrip.getStartLat())); return ResultUtil.success(data); } if (ToolUtil.isEmpty(selfTrip.getDestJson())) { return ResultUtil.success(data); } JSONArray array = JSON.parseArray(selfTrip.getDestJson()); if (array == null) { return ResultUtil.success(data); } for (int i = 0; i < array.size(); i++) { JSONObject item = array.getJSONObject(i); if (item == null) { continue; } Double endLon = item.getDouble("endLon"); Double endLat = item.getDouble("endLat"); if (endLon == null || endLat == null) { continue; } data.add(buildCircleLocation(endLon, endLat)); } return ResultUtil.success(data); } private LocationWarpper buildCircleLocation(Double lon, Double lat) { LocationWarpper locationWarpper = new LocationWarpper(); locationWarpper.setType(2); locationWarpper.setCoordinate(lon + "," + lat + ";3000"); locationWarpper.setProvince(""); locationWarpper.setProvinceCode(""); locationWarpper.setCity(""); locationWarpper.setCityCode(""); locationWarpper.setDistrict(""); locationWarpper.setDistrictCode(""); return locationWarpper; } @Override public boolean selfAreaMonitoring(Integer driverId, Integer lineShiftDriverId, Integer type, String lonLat) throws Exception { if (driverId == null || lineShiftDriverId == null || type == null || ToolUtil.isEmpty(lonLat)) { return false; } if (type != 1 && type != 2) { return false; } String[] pointArr = lonLat.split(","); if (pointArr.length != 2) { return false; } Double pointLon; Double pointLat; try { pointLon = Double.valueOf(pointArr[0]); pointLat = Double.valueOf(pointArr[1]); } catch (Exception e) { return false; } LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(lineShiftDriverId); if (lineShiftDriver == null || !driverId.equals(lineShiftDriver.getDriverId()) || lineShiftDriver.getCustomerId() == null) { return false; } DriverSelfTrip selfTrip = driverSelfTripMapper.selectById(lineShiftDriver.getCustomerId()); if (selfTrip == null || selfTrip.getState() == null || selfTrip.getState() != 1) { return false; } if (type == 1) { return isWithinCircle(selfTrip.getStartLon(), selfTrip.getStartLat(), pointLon, pointLat, 3000D); } if (ToolUtil.isEmpty(selfTrip.getDestJson())) { return false; } JSONArray array = JSON.parseArray(selfTrip.getDestJson()); if (array == null || array.isEmpty()) { return false; } for (int i = 0; i < array.size(); i++) { JSONObject item = array.getJSONObject(i); if (item == null) { continue; } Double endLon = item.getDouble("endLon"); Double endLat = item.getDouble("endLat"); if (isWithinCircle(endLon, endLat, pointLon, pointLat, 3000D)) { return true; } } return false; } private boolean isWithinCircle(Double centerLon, Double centerLat, Double pointLon, Double pointLat, Double radiusMeter) { if (centerLon == null || centerLat == null || pointLon == null || pointLat == null || radiusMeter == null) { return false; } double earthRadius = 6371000D; double lat1 = Math.toRadians(centerLat); double lat2 = Math.toRadians(pointLat); double deltaLat = lat2 - lat1; double deltaLon = Math.toRadians(pointLon - centerLon); double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); double distance = earthRadius * c; return distance <= radiusMeter; } /** * 判断点是都在区域范围内 * @param siteId * @param code * @param lonLat * @return * @throws Exception */ @Override public boolean areaMonitoring(Integer siteId, Integer code, String lonLat) throws Exception { List> list = this.queryLocation(siteId); String province = code.toString().substring(0, 2) + "0000"; String city = code.toString().substring(0, 4) + "00"; for(Map map : list){ if(Integer.valueOf(map.get("type").toString()) == 1){//行政区域 if(null != map.get("districtCode")){ if(code.toString().equals(map.get("districtCode").toString())){ return true; } continue; } if(null != map.get("cityCode")){ if(city.equals(map.get("cityCode").toString())){ return true; } continue; } if(null != map.get("provinceCode")){ if(province.equals(map.get("provinceCode").toString())){ return true; } continue; } } if(Integer.valueOf(map.get("type").toString()) == 2){//电子围栏 String[] split = lonLat.split(","); GeoJsonPoint point = new GeoJsonPoint(Double.valueOf(split[0]), Double.valueOf(split[1])); Query query = Query.query(Criteria.where("geoJsonPolygon").intersects(point)); List geoFencingPolygons = mongoTemplate.find(query, GeoFencingPolygon.class); List s_sites = geoFencingPolygons.stream().map(GeoFencingPolygon::getSiteId).collect(Collectors.toList()); if(s_sites.contains(siteId)){ return true; } } } return false; } }